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