Please use a browser that supports javascript

Bogeskov.dk

Port Knocking in RAW/PREROUTING

If you're using the Intrusion blocking and blocking in raw/prerouting (for accessing the NOTRACK target) then you get blocked before you get to the normal port knocking implementation.

I needed to access this issue before intrusion blocking. For instance if you by accident blocks yourself.

There's just this issue with the raw/prerouting table. It doesn't handle sub tables. And the "recent" module can't both check and alter a list in one go. Therefor my approach is to tag the connection attempt with the "mark" module, and then alter the tables accordingly. This also allows for a mark to simplify the matching in the INPUT table.

IF_WAN=eth0
IP_WAN=12.34.56.78

# close port
KNOCKPORT0=10000
# open port sequence
KNOCKPORT1=11111
KNOCKPORT2=22222
KNOCKPORT3=33333

# State numbers
KNOCK1=1
KNOCK2=2
KNOCK3=3
KNOCKED=4

...

# shorthand for connection attempt
KNOCKCMD="iptables -t raw -A PREROUTING -d $IP_WAN -p tcp --tcp-flags SYN,ACK,FIN,RST SYN"

$KNOCKCMD --dport $KNOCKPORT0            -m recent --name knock3 --remove
$KNOCKCMD --dport $KNOCKPORT1                                                           -j MARK --set-mark $KNOCK1
$KNOCKCMD --dport $KNOCKPORT2            -m recent --name knock1 --rcheck --seconds 5   -j MARK --set-mark $KNOCK2
$KNOCKCMD --dport $KNOCKPORT3            -m recent --name knock2 --rcheck --seconds 5   -j MARK --set-mark $KNOCK3
iptables -t raw -A PREROUTING -d $IP_WAN -m recent --name knock3 --update --seconds 600 -j MARK --set-mark $KNOCKED

iptables -t raw -A PREROUTING -m mark --mark $KNOCK1  -j LOG --log-prefix "K=1 "
iptables -t raw -A PREROUTING -m mark --mark $KNOCK1  -m recent --name knock1 --set
iptables -t raw -A PREROUTING -m mark --mark $KNOCK1  -j DROP
iptables -t raw -A PREROUTING -m mark --mark $KNOCK2  -j LOG --log-prefix "K=2 "
iptables -t raw -A PREROUTING -m mark --mark $KNOCK2  -m recent --name knock1 --remove
iptables -t raw -A PREROUTING -m mark --mark $KNOCK2  -m recent --name knock2 --set
iptables -t raw -A PREROUTING -m mark --mark $KNOCK2  -j DROP
iptables -t raw -A PREROUTING -m mark --mark $KNOCK3  -j LOG --log-prefix "K=3 "
iptables -t raw -A PREROUTING -m mark --mark $KNOCK3  -m recent --name knock2 --remove
iptables -t raw -A PREROUTING -m mark --mark $KNOCK3  -m recent --name knock3 --set
iptables -t raw -A PREROUTING -m mark --mark $KNOCK3  -j DROP
iptables -t raw -A PREROUTING -m mark --mark $KNOCKED -j ACCEPT

...

iptables -N knocked
iptables -A knocked ... -j ACCEPT

...

iptables -A INPUT -i $IF_WAN -d $IP_WAN -m mark --mark $KNOCKED -j knocked

a couple of notes:

  • I only use IP_WAN for the case where IF_WAN has more than one ip number
  • I've added the port KNOCKPORT0, which removes your ip from the knocked list
  • the KNOCKCMD is just short hand for adding a rule that detects a connection attempt
  • the --seconds option is used to tell how slow you're allowed to be
  • the --update --seconds is how long your ip is allowed to be idle, before your knocking needs to be done again

I you want to be really obscure you could do this:

iptables -t nat -A PREROUTING -m mark --mark $KNOCKED -m state --state NEW -p tcp --dport  443 -j DNAT --to-destination :1443
iptables        -A INPUT      -m mark --mark $KNOCKED -m state --state NEW -p tcp --dport 1443 -j ACCEPT

and then run a openvpn server in tcp mode on 1443 port sharing with 443, so if you knock you're allowed to connect to your https port with openvpn, but you can still use it as your ordinary ssl website (haven't tried this yet).

If you run on a command line then running:

nc -w 1 12.34.56.78 11111 22222 33333

should take about 3 seconds and open the server for you.

or you could type this in your browser: http://12.34.56.78:11111/, http://12.34.56.78:22222/ & http://12.34.56.78:33333/ with less than 5 seconds to alter each url. If this is your scenario then you might want to increase the 5 seconds timeout in the firewall.

This is all supplied with my iptables-setup package.