nftables is a pain in the rear

Due to people saying iptables is deprecated etc. I decided to move my iptables scripts - working perfectly for years - to nftables. What a dog's breakfast. Simple things become complicated and some can't be done at all.

Add a rule temporarily? In iptables it is -A, do the task, then -D the same rule. In nftables, adding the rule is fine but to delete it you have generate handles and identify the correct handle to delete.

Export as JSON? Broken, in that it is not reversible (sets containing CIDR are exported with a 'length' parameter)

List sets with contents? Nope. There's a "--terse" flag to remove the contents of sets, but (at least in 1.0.7 which is what my test distro provides) there's no way to just list sets with their contents, i.e. 'nft list sets' doesn't show it by default and there's no flag to include it.

Export as a script? In iptables it is iptables-save. In nftables there's 'list ruleset' but that gives the entire structure. I want it in the same script format as iptables-restore-translate generates so that I can easily "grep -v" a chain. No solution from searching the web, so at the moment, the simplest approach is to keep everything in an iptables "master file" and re-translate it each time.

So many "that is being worked on" comments. My conclusion is it has fancy features but someone has forgotten to complete the basic use cases. Possible I'm just ignorant, or maybe my search skills are just crap.

End rant.

Thanked by (2)Shot² burntascii
«1

Comments

  • AuroraZeroAuroraZero ModeratorHosting ProviderRetired

    Welcome to progress my friend. Stuff that works fine gets broken and turned to pure shit.

    Free Hosting at YetiNode | Cryptid Security | URL Shortener | LaunchVPS | ExtraVM | Host-C | In the Node, or Out of the Loop?

  • ufw allow 22 ; ufw enable

    Thanked by (1)yoursunny
  • Our usual is:

    sudo ufw allow 222/tcp
    sudo ufw enable
    sudo ufw deny out 25/tcp
    sudo ufw route deny 25/tcp
    sudo ufw allow 5201
    sudo ufw allow 2015/tcp
    
    • 222 is our SSH port; too much noise on 22.
    • 25 is blocked to prevent accidental spam.
    • 5201 is for iperf3.
    • 2015 is for temporary use such as Python HTTP server to transfer a file.
    Thanked by (2)admax Blembim

    No hostname left!

  • amen. trying to convert to nftables made my head spin. luckily ufw just uses it anyway now and still doing custom stuff using iptables(nft).

  • This is yet one of the reasons why Linux will always suck.

    Standardize, Rebuke, Repeat.

    Thanked by (3)localhost flips VirMach

    My pronouns are like/subscribe.

  • @Crab said:
    ufw allow 22 ; ufw enable

    Not sure if you're proposing that as an alternative to my 1000+ iptables rules file, but thanks for the suggestion.

    Thanked by (1)Janevski
  • @AuroraZero said:
    Welcome to progress my friend. Stuff that works fine gets broken and turned to pure shit.

    Probably a fair & concise summary of how I feel.

  • @tetech said:
    Not sure if you're proposing that as an alternative to my 1000+ iptables rules file, but thanks for the suggestion.

    Without knowing any details about your use case, my point was simply to introduce UFW (Uncomplicated Firewall) which takes care of most common firewall needs with a very simple and easy interface. Naturally it is not a silver bullet for everything and sounds like your use case is very complex for which UFW might not be a suitable solution.

    Thanked by (1)yoursunny
  • @Crab said:

    @tetech said:
    Not sure if you're proposing that as an alternative to my 1000+ iptables rules file, but thanks for the suggestion.

    Without knowing any details about your use case, my point was simply to introduce UFW (Uncomplicated Firewall) which takes care of most common firewall needs with a very simple and easy interface. Naturally it is not a silver bullet for everything and sounds like your use case is very complex for which UFW might not be a suitable solution.

    OK, understood. Probably not a viable solution in this case, but appreciate the suggestion.

    Thanked by (1)Crab
  • Agreed. The only objective advantage I found in nftables is that a single rule definition covers IPv4 and IPv6, but apart from that iptables has better usability and more features.

  • I've has this thought too that feeling like i have to move from iptables to nft for modernization.

    But what's really advantages of nft over iptables tho?

  • Came to the same conclusion, tried to learn nftables years back when I thought iptables might actually get removed from Debian.

    Struggled with what was then a complete dogs dinner and so stuck with the iptables emulation package. Still using that today and it would take a lot to make me revisit. Sounds like things haven't improved, are any distros planning to retire the iptables package?

  • VirMachVirMach Hosting Provider

    @WSS said:
    This is yet one of the reasons why Linux will always suck.

    Standardize, Rebuke, Repeat.

    Windows sucks too. Completely ignore for 10-15 years, randomly decide to "improve" it (like with Notepad or Settings) in a weird way, introducing a bunch of problems in the process. I've never had it just straight up crash and relaunch itself and crash again from trying to relaunch and open all the various Notepads I had open that I forgot to close. I've never had File Explorer just break. Even the taskbar just breaks. I love it when you click on an icon and it decides it doesn't want to do anything or you close out a program that has multiple instances/tabs and it doesn't even update the list until you scroll up and down to refresh the list.

    Everything sucks. As for Linux my personal preference for whatever I want to do for myself that is unimportant usually involves loading in the oldest thing I can find, I don't care if it's EOL. Actually I do, I'd rather it be EOL, it usually means they stopped needlessly messing with it so much and definitely didn't introduce new bugs along the way and there's proper documentation I can find for it.

    I find myself just disliking everything, maybe I'm just not hip anymore. I'd get rid of Windows in a heartbeat if it didn't mean I'd have to deal with Linux, and vice versa. I'd love Linux if I just had infinite time to waste over the most mundane thing. At least then it has the potential to work and I have the power to make it work, but at what cost?

  • @quicksilver03 said:
    Agreed. The only objective advantage I found in nftables is that a single rule definition covers IPv4 and IPv6, but apart from that iptables has better usability and more features.

    @Blembim said:
    But what's really advantages of nft over iptables tho?

    One thing is covering IPv4 and IPv6 with a single rule as @quicksilver03 said. In principle, having sets of IP addresses is a nice thing - rewrite the set rather than flushing a chain and re-adding the rules. In principle, being able to split rules across multiple files in the config directory rather than one massive rules file is a nice thing. In theory, the atomicity is nice (i.e. nothing breaks because someone hits your site half-way through a chain re-write), but the chances of this actually being a problem seem pretty miniscule.

    I say "in principle" to some of these things because they don't actually work in practice - so you put rules in different files, but if you want to update them programmatically then it doesn't work, because there aren't the proper tools for merging/splitting/exporting rulesets.

    @cochon said:
    Struggled with what was then a complete dogs dinner and so stuck with the iptables emulation package. Still using that today and it would take a lot to make me revisit. Sounds like things haven't improved, are any distros planning to retire the iptables package?

    It seems some are starting to remove the iptables kernel module and use "iptables-nft", e.g. Alpine from 3.19. This mostly keeps the iptables interface, although Alpine is even messing with that now (have to do iptables-legacy-save instead of iptables-save, or just overwrite the binary).

    Thanked by (2)Blembim cochon
  • @VirMach said: Windows sucks too. Completely ignore for 10-15 years, randomly decide to "improve" it (like with Notepad or Settings) in a weird way, introducing a bunch of problems in the process.

    Agree with this too.

    Seriously starting to think about BSD-based stuff.

  • @tetech said:
    1000+ iptables rules

    Write your rules in C as an eBPF program.
    This covers at least ingress traffic processing and is more powerful than any firewall rules.
    https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_XDP/

    No hostname left!

  • @yoursunny said:

    @tetech said:
    1000+ iptables rules

    Write your rules in C as an eBPF program.
    This covers at least ingress traffic processing and is more powerful than any firewall rules.
    https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_XDP/

    Any sample you can point to of how to do the equivalent of this?

    CHAIN=$1
    iptables -F ${CHAIN}
    while read ip; do
      iptables -A ${CHAIN} -s ${ip} -j ACCEPT
    done <${IPFILE}
    iptables-save > /etc/iptables/rules-save
    
  • @tetech said:
    iptables -A ${CHAIN} -s ${ip} -j ACCEPT

    1. Declare a BPF map of HASH type that holds the IPv4 addresses you want to accept.
    2. In the XDP program, parse the IPv4 header, and lookup the BPF map with the source address filter.
    3. Return XDP_PASS if the lookup finds an entry.
    4. In userspace program, load the IPFILE into the BPF map.
    5. Repeat the same for IPv6.

    No hostname left!

  • @yoursunny said:

    @tetech said:
    iptables -A ${CHAIN} -s ${ip} -j ACCEPT

    1. Declare a BPF map of HASH type that holds the IPv4 addresses you want to accept.
    2. In the XDP program, parse the IPv4 header, and lookup the BPF map with the source address filter.
    3. Return XDP_PASS if the lookup finds an entry.
    4. In userspace program, load the IPFILE into the BPF map.
    5. Repeat the same for IPv6.
    $ Declare a BPF map of HASH type that holds the IPv4 addresses you want to accept.
    -ash: Declare: not found
    

    Oh wait... maybe that wasn't a sample?

    Thanked by (1)mfs
  • (and I'm not doing that to be a dick, more to highlight that what takes one shell line is going to involve some large programming exercise and learning some new framework)

  • @tetech said:

    @yoursunny said:

    @tetech said:
    1000+ iptables rules

    Write your rules in C as an eBPF program.
    This covers at least ingress traffic processing and is more powerful than any firewall rules.
    https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_XDP/

    Any sample you can point to of how to do the equivalent of this?

    CHAIN=$1
    iptables -F ${CHAIN}
    while read ip; do
      iptables -A ${CHAIN} -s ${ip} -j ACCEPT
    done <${IPFILE}
    iptables-save > /etc/iptables/rules-save
    

    I realise it's only meant as an example, but as an aside I'd use an ipset rule for this sort of thing, way more efficient, especially if you want to block whole continents ;)

    Thanked by (3)skorous yoursunny tetech
  • @cochon said:

    @tetech said:

    @yoursunny said:

    @tetech said:
    1000+ iptables rules

    Write your rules in C as an eBPF program.
    This covers at least ingress traffic processing and is more powerful than any firewall rules.
    https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_XDP/

    Any sample you can point to of how to do the equivalent of this?

    CHAIN=$1
    iptables -F ${CHAIN}
    while read ip; do
      iptables -A ${CHAIN} -s ${ip} -j ACCEPT
    done <${IPFILE}
    iptables-save > /etc/iptables/rules-save
    

    I realise it's only meant as an example, but as an aside I'd use an ipset rule for this sort of thing, way more efficient, especially if you want to block whole continents ;)

    :lol:

  • I think its more useful to just use iptables / ufw and adopt xdp based solutions as soon as possible if you are interested in actual advancements. ;)

    Thanked by (1)yoursunny
  • @VirMach said:

    @WSS said:
    This is yet one of the reasons why Linux will always suck.

    Standardize, Rebuke, Repeat.

    Windows sucks too.

    Computers suck. People suck. Screw them both.

    Thanked by (2)skorous lukast__

    My pronouns are like/subscribe.

  • @tetech said:

    @Crab said:
    ufw allow 22 ; ufw enable

    Not sure if you're proposing that as an alternative to my 1000+ iptables rules file, but thanks for the suggestion.

    People using ufw and cloud firewalls don't understand what stateful and stateless firewall is.

  • @tetech said:

    @yoursunny said:

    @tetech said:
    1000+ iptables rules

    Write your rules in C as an eBPF program.
    This covers at least ingress traffic processing and is more powerful than any firewall rules.
    https://docs.ebpf.io/linux/program-type/BPF_PROG_TYPE_XDP/

    Any sample you can point to of how to do the equivalent of this?

    CHAIN=$1
    iptables -F ${CHAIN}
    while read ip; do
      iptables -A ${CHAIN} -s ${ip} -j ACCEPT
    done <${IPFILE}
    iptables-save > /etc/iptables/rules-save
    

    I feel you can simplify what you're trying to do using sets.

    Here's an example of what my nftables rules look like -- my use case is to have SSH access anywhere (since I travel a lot) and then just have the website running on this server accessible via a CDN, and the list of CDN IPs go inside two sets, one for v4 and the other for v6.

    #!/usr/sbin/nft -f
    
    flush ruleset
    
    table inet filter {
        set web_ipv4 {
            type ipv4_addr
            flags interval
        }
    
        set web_ipv6 {
            type ipv6_addr
            flags interval
        }
    
        chain input {
            type filter hook input priority 0; policy drop;
    
            iif lo accept
            ct state established, related accept
            ct state invalid drop
    
            ether type arp accept
            meta l4proto { ipv6-icmp, icmp } accept
            meta nfproto ipv6 udp sport 547 udp dport 546 accept
            meta nfproto ipv4 udp sport 67 udp dport 68 accept
    
            tcp dport 22 accept
            ip saddr @web_ipv4 tcp dport { 80, 443 } accept
            ip6 saddr @web_ipv6 tcp dport { 80, 443 } accept
        }
    
        chain forward {
            type filter hook forward priority 0; policy drop;
        }
    
        chain output {
            type filter hook output priority 0;
        }
    }
    

    For adding new IPs to the @web_ipv4 and @web_ipv6 sets, I do:

    nft add element inet filter web_ipv4 '{' "$ip" '}'
    nft add element inet filter web_ipv6 '{' "$ip" '}'
    

    However, mostly I just pull in new IPs and remove IPs from an automated source. Therefore, what I like to do is define a extract_ips_nft_set method that looks like this:

    function extract_ips_nft_set() {
        nft --json list set inet filter "$1" | jq -r '.nftables[]
            | with_entries(select(.key == "set"))
            | select(length > 0)
            | .set.elem[].prefix
            | .addr + "/" + (.len | tostring)' | sort || true
    }
    

    Then, I compute the list of elements to add and delete like this:

    extract_ips_nft_set web_ipv4 > current_ipv4
    extract_ips_nft_set web_ipv6 > current_ipv6
    
    curl -sSf https://some.ip.list/list-v4.txt | sort > new_ipv4
    curl -sSf https://some.ip.list/list-v6.txt | sort > new_ipv6
    
    for ip in $(comm -23 current_ipv4 new_ipv4); do
        nft delete element inet filter web_ipv4 '{' "$ip" '}'
    done
    
    for ip in $(comm -23 current_ipv6 new_ipv6); do
        nft delete element inet filter web_ipv6 '{' "$ip" '}'
    done
    
    for ip in $(comm -13 current_ipv4 new_ipv4); do
        nft add element inet filter web_ipv4 '{' "$ip" '}'
    done
    
    for ip in $(comm -13 current_ipv6 new_ipv6); do
        nft add element inet filter web_ipv6 '{' "$ip" '}'
    done
    
  • edited December 2024

    apt install iptables iptables-persistent
    readlink -f $(which iptables)

    if it gives you something like /usr/sbin/xtables-nft-multi your iptables already uses nftables behind the scenes, so why bother

    The xtables-nft tools allow you to manage the nf_tables backend using the native syntax of iptables(8), ip6tables(8), arptables(8), and ebtables(8).

    You should use the xtables-nft tools exactly the same way as you would use the corresponding original tools.

    Adding a rule will result in that rule being added to the nf_tables kernel subsystem instead. Listing the ruleset will use the nf_tables backend as well.

    When these tools were designed, the main idea was to replace each legacy binary with a symlink to the xtables-nft program, for example:

    /sbin/iptables -> /usr/sbin/iptables-nft-multi
    /sbin/ip6tables -> /usr/sbin/ip6tables-nft-multi
    /sbin/arptables -> /usr/sbin/arptables-nft-multi
    /sbin/ebtables -> /usr/sbin/ebtables-nft-multi

    The iptables version string will indicate whether the legacy API (get/setsockopt) or the new nf_tables api is used:

    iptables -V
    iptables v1.7 (nf_tables)

  • tetechtetech OG
    edited December 2024

    @supriyo_biswas said: I feel you can simplify what you're trying to do using sets.

    I think my made-up example has been taken too literally. Yes, sets are good, and it was very nice that you shared your rules and a script, in particular your jq function could be quite useful, and if I kept going with nft then you've probably saved me some time, thank you! But don't you think that's a bit of a hack, and nft --not-terse list sets would be better?

    @egoror said: apt install iptables iptables-persistent
    readlink -f $(which iptables)

    if it gives you something like /usr/sbin/xtables-nft-multi your iptables already uses nftables behind the scenes, so why bother

    Sorry, the point here is evading me.

  • @tetech said:
    Sorry, the point here is evading me.

    You have no reason to move your iptables scripts because "iptables" is using nftables nowadays. iptables is a symlink to xtables-nft-multi, and uses iptables syntax on nftables backend. Just use iptables as usual.

    Thanked by (1)yoursunny
  • @tetech said:

    @supriyo_biswas said: I feel you can simplify what you're trying to do using sets.

    I think my made-up example has been taken too literally. Yes, sets are good, and it was very nice that you shared your rules and a script, in particular your jq function could be quite useful, and if I kept going with nft then you've probably saved me some time, thank you! But don't you think that's a bit of a hack, and nft --not-terse list sets would be better?

    I had no idea this was a trauma dump thread. Anyway, personally I just like to go with whatever works, and it was easier to bite the bullet and learn nftables.

Sign In or Register to comment.