highlight.nft

    define int_if1 = eth0
    define int_ifs = { $int_if1, $int_if2 }
    redefine int_if2 = wlan0
    undefine int_if2

    filter input iif $int_ifs accept

    # create a new table.
    create table inet mytable

    # add a new base chain: get input packets
    add chain inet mytable myin { type filter hook input priority filter; }

    add rule ip nat prerouting dnat tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }

    add rule ip nat postrouting snat to ip saddr map { 192.168.1.0/24 : 10.0.0.1, 192.168.2.0/24 : 10.0.0.2 }

    add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }

    table ip filter {
        ct timeout customtimeout {
            protocol tcp;
            l3proto ip
            policy = { established: 2m, close: 20s }
        }

        chain output {
            type "ftp" protocol tcp
            ct state invalid, untracked synproxy mss 1460 wscale 9 timestamp sack-perm
            ct state invalid drop
            ct timeout set "customtimeout"
        }
    }

    table ip filter {
        ct expectation expect {
            protocol udp
            dport 9876
            timeout 2m
            size 8
            l3proto ip
        }
    }

    # This also works with named maps and in combination with both concatenations and ranges:
    table ip nat {
            map ipportmap {
                    typeof ip saddr : interval ip daddr . tcp dport
                    flags interval
                    elements = { 192.168.1.2 : 10.141.10.1-10.141.10.3 . 8888-8999, 192.168.2.0/24 : 10.141.11.5-10.141.11.20 . 8888-8999 }
            }

            chain prerouting {
                    type nat hook prerouting priority dstnat; policy accept;
                    ip protocol tcp dnat ip to ip saddr map @ipportmap
            }
    }

    table ip6 x {
        chain y {
            type filter hook prerouting priority mangle; policy accept;
            tcp dport ntp tproxy to [dead::beef] accept
            udp dport ssh tproxy to :2222 accept
            udp dport 155 tproxy ip6 to [dead::beef]:smux accept
            tcp dport 99 tproxy ip to 1.1.1.1:999 accept
        }
    }

    table inet x {
        chain y {
            type filter hook prerouting priority mangle; policy accept;
            udp dport 9999 goto {
                tproxy to :1234 log prefix "packet tproxied: " meta mark set 1 accept
                log prefix "no socket on port 1234 or not transparent?: " drop
            }
        }
    }

    add quota filter user123 { over 20 mbytes }

    describe tcp flags

    filter input ether daddr 20:c9:d0:43:12:d9
    filter output ip daddr 127.0.0.1
    filter output ip daddr localhost
    filter output ip6 daddr ::1
    inet filter output rt ip6 nexthop fd00::1
    add rule inet nat prerouting dnat ip6 to fe80::dead

    ct event set new,related,destroy

    # without [] the port number (22) would be parsed as part of the
    # ipv6 address
    ip6 nat prerouting tcp dport 2222 dnat to [1ce::d0]:22

    # match if route exists
    filter input fib daddr . iif oif exists

    filter output icmpv6 type { echo-request, echo-reply }

    # match incoming packet from 03:00 to 14:00 local time
    raw prerouting meta hour "03:00"-"14:00" counter accept

    # outgoing packet will be encapsulated/encrypted by ipsec
    filter output rt ipsec exists

    # round-robin between 192.168.10.100 and 192.168.20.200:
    add rule nat prerouting dnat to numgen inc mod 2 map \
            { 0 : 192.168.10.100, 1 : 192.168.20.200

        inet filter input meta l4proto {tcp, udp} th dport { 53, 80 }

        input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566 accept

        ip rule add fwmark 1 lookup 100
        ip route add local 0.0.0.0/0 dev lo table 100

        # copy raw frame to another interface
        netdev ingress dup to "eth0"
        dup to "eth0"
    }

    # declare a set to store the limit per saddr.
    # This must be separate from blackhole since the timeout is different
    add set ip filter flood \
        { type ipv4_addr; flags dynamic; timeout 10s; size 128000; }

    # drop packets coming from blacklisted ip addresses.
    add rule ip filter input ip saddr @blackhole counter drop

    add @flood { ip saddr limit rate over 10/second }

    # inspect state of the sets.
    list set ip filter flood