Search code examples
ipv6natsubnetnftables

nftables - IPv6 port knocking - accept whole subnet


I'd like to add port knocking to a server which is already working. My client sends the magic sequence of packets and the server will add it to a nftables set of allowed clients for specific time. Therefor the clients are allowed to use some services. For details see my configuration below.

Now I want to do the port knocking automatically from my router. For IPv4 this works, but for IPv6 this doesn't work because there is no NAT involved so each client has a unique address. That's why I'd like to add the whole subnet (/56) of the knocking client the set of allowed clients.

Is this possible using nftables? I've read about "flags interval" but I don't understand how to dynamically add the clients subnet to it.

chain input {
    ...
    jump port_knocking
    ...
}

set knock_v6_1 {
    type ipv6_addr
    flags timeout
}
set knock_v6_2 {
    type ipv6_addr
    flags timeout
}
set knock_v6_success {
    type ipv6_addr
    flags timeout
}

chain port_knocking {
    ip6 nexthdr icmpv6 ip6 length 100 set update ip6 saddr @knock_v6_1
    ip6 saddr @knock_v6_1 ip6 nexthdr icmpv6 ip6 length 101 set update ip6 saddr timeout 10s @knock_v6_2
    ip6 saddr @knock_v6_2 ip6 nexthdr icmpv6 ip6 length 102 set update ip6 saddr timeout 10s @knock_v6_success
}

Solution

  • After a successful port knock don't add the source ip of the client but mask it using port_knock_netmask_v6. When checking if a new connection originates from a client after successful knock also mask it using port_knock_netmask_v6.

    define port_knock_netmask_v6 = ffff:ffff:ffff:ff::
    
    table inet filter {
    
        chain input {
            ...
            jump port_knocking
    
            tcp dport 22 ip6 saddr & $port_knock_netmask_v6 @knock_v6_success accept
            ...
        }
    
        set knock_v6_1 {
            type ipv6_addr
            flags timeout
        }
        set knock_v6_2 {
            type ipv6_addr
            flags timeout
        }
        set knock_v6_success {
            type ipv6_addr
            flags timeout
        }
    
        chain port_knocking {
            ip6 nexthdr icmpv6 ip6 length 100 set update ip6 saddr timeout 10s @knock_v6_1
            ip6 saddr @knock_v6_1 ip6 nexthdr icmpv6 ip6 length 101 set update ip6 saddr timeout 10s @knock_v6_2
            ip6 saddr @knock_v6_2 ip6 nexthdr icmpv6 ip6 length 102 set update ip6 saddr & $port_knock_netmask_v6 timeout 1h @knock_v6_success
        }
    
    }