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.