Port knocking example

From nftables wiki
Revision as of 14:44, 25 July 2019 by Arturo (talk | contribs) (add another example)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This page shows some examples on how to use portknocking in nftables.

Example 1

Link to original nftables script is here.

Knocking sequence, in this example below, are TCP ports: 123, 234, 345 and 456.

define guarded_ports = {ssh}

table inet portknock {
	set clients_ipv4 {
		type ipv4_addr
		flags timeout
	}

	set clients_ipv6 {
		type ipv6_addr
		flags timeout
	}

	set candidates_ipv4 {
		type ipv4_addr . inet_service
		flags timeout
	}

	set candidates_ipv6 {
		type ipv6_addr . inet_service
		flags timeout
	}

	chain input {
		type filter hook input priority -10; policy accept;

		iifname "lo" return

		tcp dport 123 add @candidates_ipv4 {ip  saddr . 234 timeout 1s}
		tcp dport 123 add @candidates_ipv6 {ip6 saddr . 234 timeout 1s}
		tcp dport 234 ip  saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip  saddr . 345 timeout 1s}
		tcp dport 234 ip6 saddr . tcp dport @candidates_ipv6 add @candidates_ipv6 {ip6 saddr . 345 timeout 1s}
		tcp dport 345 ip  saddr . tcp dport @candidates_ipv4 add @candidates_ipv4 {ip  saddr . 456 timeout 1s}
		tcp dport 345 ip6 saddr . tcp dport @candidates_ipv6 add @candidates_ipv6 {ip6 saddr . 456 timeout 1s}
		tcp dport 456 ip  saddr . tcp dport @candidates_ipv4 add @clients_ipv4 {ip  saddr timeout 10s} log prefix "Successful portknock: "
		tcp dport 456 ip6 saddr . tcp dport @candidates_ipv6 add @clients_ipv6 {ip6 saddr timeout 10s} log prefix "Successful portknock: "

		tcp dport $guarded_ports ip  saddr @clients_ipv4 counter accept
		tcp dport $guarded_ports ip6 saddr @clients_ipv6 counter accept
		tcp dport $guarded_ports ct state established,related counter accept

		tcp dport $guarded_ports counter reject with tcp reset

	}
}

Example 2

Link to original nftables script is here.

Knocking sequence, in this example below, are TCP ports: 123, 234, 345 and 456.

#!/usr/bin/env nft -f
flush ruleset

table ip Inet4 {
  set Knocked_1 {
    type ipv4_addr
    flags timeout
    timeout 10s
    gc-interval 4s
  }
  set Knocked_2 {
    type ipv4_addr
    flags timeout
    timeout 10s
    gc-interval 4s
  }
  set Knocked_3 {
    type ipv4_addr
    flags timeout
    timeout 10s
    gc-interval 4s
  }
  set Knocked_4 {
    type ipv4_addr
    flags timeout
    timeout 2m
    gc-interval 4s
  }

  chain Knock_1 {
    set add ip saddr @Knocked_1
  }
  chain Unknock_1 {
    set update ip saddr timeout 0s @Knocked_1
  }
  chain Knock_2 {
    set update ip saddr timeout 0s @Knocked_1
    set add ip saddr @Knocked_2
  }
  chain Unknock_2 {
    set update ip saddr timeout 0s @Knocked_2
  }
  chain Knock_3 {
    set update ip saddr timeout 0s @Knocked_2
    set add ip saddr @Knocked_3
  }
  chain Unknock_3 {
    set update ip saddr timeout 0s @Knocked_3
  }
  chain Knock_4 {
    set update ip saddr timeout 0s @Knocked_3
    set add ip saddr @Knocked_4 log prefix "Port-Knock accepted: "
  }

  chain RefreshKnock {
    set update ip saddr timeout 2m @Knocked_4
  }

  chain PortKnock {
    ct state new ip saddr @Knocked_4 goto RefreshKnock
    tcp dport 456 ct state new ip saddr @Knocked_3 goto Knock_4
    tcp dport 345 ct state new ip saddr @Knocked_3 return
    ip saddr @Knocked_3 ct state new goto Unknock_3
    tcp dport 345 ct state new ip saddr @Knocked_2 goto Knock_3
    tcp dport 234 ct state new ip saddr @Knocked_2 return
    ip saddr @Knocked_2 ct state new goto Unknock_2
    tcp dport 234 ct state new ip saddr @Knocked_1 goto Knock_2
    tcp dport 123 ct state new ip saddr @Knocked_1 return
    ip saddr @Knocked_1 ct state new goto Unknock_1
    tcp dport 123 ct state new goto Knock_1
  }

  chain FilterIn {
    type filter hook input priority 0
    policy drop

    # allow established/related connections
    ct state established,related accept

    # early drop of invalid connections
    ct state invalid drop

    # allow from loopback
    meta iif lo accept

    # allow icmp
    ip protocol icmp accept

    # port-knocking
    jump PortKnock

    # misc. filtering
    # ...
  }

  chain FilterOut {
    type filter hook output priority 0
    policy accept
  }
}