Quick Links

We've shown you how to trigger WOL remotely by "Port Knocking" on your router. In this article, we will show how to use it to protect a VPN service.

Image by Aviad Ravivbfick.

Preface

If you've used DD-WRT's built in functionality for VPN or, have another VPN server in your network, you might appreciate the ability to protect it from brute force attacks by hiding it behind a knock sequence. By doing this, you will filter out the script kiddies that are trying to gain access to your network. With that said, as stated in the previous article, port knocking is not a replacement for a good password and/or security policy. Do remember that with enough patience an attacker can discover the sequence and perform a replay attack.

Also keep in mind, that the downside of implementing this is that when any VPN client/s want to connect, they would have to trigger the knock sequence beforehand and that if they can't complete the sequence for any reason, they will not be able to VPN at all.

Overview

In order to protect *the VPN service we will first disable all possible communication with it by blocking the instantiating port of 1723. To achieve this goal, we will use iptables. This is because, that is how communication is filtered on most modern Linux/GNU distributions in general and on DD-WRT in particular. If you'd like more information about iptables checkout its wiki entry, and have a look at our previous article on the subject. Once the service is protected, we will create a knock sequence that would temporarily open the VPN instantiating port and also automatically close it after a configured amount of time, while keeping the already established VPN session connected.

Note: In this guide, we are using the PPTP VPN service as an example. With that said, the same method can be used for other VPN types, you'll just have to change the blocked port and/or communication type.

Prerequisites, Assumptions & Recommendations

Lets get cracking.

Default "Block new VPNs" rule on DD-WRT

While the below snippet of "code" would probably work on every, self-respecting, iptables using, Linux/GNU distribution, because there are so many variants out there we will only show how to use it on DD-WRT. Nothing is stopping you, if you wish, from implementing it directly on the VPN box. However, how to do so, is beyond the scope of this guide.

Because we want to augment the router's Firewall, it is only logical that we would add to the "Firewall" script. Doing so, would cause the iptables command to be executed every time the firewall is refreshed and thus keeping our augmentation in place for keeps.

From DD-WRT's Web-GUI:

  • Go to "Administration" -> "Commands".
  • Enter the below "code" into the text-box:
            inline="$( iptables -L INPUT -n | grep -n "state RELATED,ESTABLISHED"  | awk -F : {'print $1'} )"; inline=$(($inline-2+1)); iptables -I INPUT "$inline" -p tcp --dport 1723 -j DROP
        
  • Click on "Save Firewall".
  • Done.

What is this "Voodoo" command?

The above "voodoo magic" command does the following:

  • Finds where is the iptable line that enables already established communication to pass through. We do this, because A. On DD-WRT routers, if the VPN service is enabled, it will be located just below this line and B. It is essential to our goal of continuing to allow already established VPN sessions to live on after the knocking event.
  • Deducts two (2) from the output of the listing command to account for the offset caused by the informational column headers. Once that's done, adds one (1) to the above number, so that the rule that we are inserting will come just after the rule that allows already established communication. I've left this very simple "math problem" in here, just to make the logic of "why one needs to reduce one from the rule's place instead of adding one to it" clear.

KnockD configuration

We need to create a new triggering sequence that will enable new VPN connections to be created. To do this, edit the knockd.conf file by issuing in a terminal:

        vi /opt/etc/knockd.conf
    

Append to the existing configuration:

        [enable-VPN]
sequence = 02,02,02,01,01,01,2010,2010,2010
seq_timeout = 60
start_command = iptables -I INPUT 1 -s %IP% -p tcp --dport 1723 -j ACCEPT
cmd_timeout = 20
stop_command = iptables -D INPUT -s %IP% -p tcp --dport 1723 -j ACCEPT

This configuration will:

  • Set the window of opportunity to complete the sequence, to 60 seconds. (It's recommended to keep this as short as possible)
  • Listen to a sequence of three knocks on ports 2, 1 and 2010 (this order is deliberate to throw ports scanners off track).
  • Once the sequence has been detected, execute the "start_command". This "iptables" command will place an "accept traffic destined to port 1723 from where the knocks came from" on the top of the firewall rules. (The %IP% directive is treated specially by KnockD and is replaced with the IP of the knocks origin).
  • Wait for 20 seconds before issuing the "stop_command".
  • Execute the "stop_command". Where this "iptables" command does the reverse of the above and deletes the rule that allows communication.

That's it, your VPN service should now be connectable only after a successful "knock".

Author's tips

While you should be all set, there are a couple of points that i feel need mentioning.

  • Troubleshooting. Remember that if you're having problems, the "troubleshooting" segment at the end of the first article should be your first stop.
  • If you want, you can have the "start/stop" directives execute multiple commands by seperating them with a semi-colen (;) or even a script. Doing so will enable you to do some nifty stuff. For example, I have knockd send me an *Email telling me that a sequence has been triggered and from where.
  • Don't forget that "There's an app for that" and  even though its not mentioned in this article, you are encouraged to grab StavFX's Android knocker program.
  • While on the subject of Android, don't forget that there is a PPTP VPN client usually built into the OS from the manufacturer.
  • The method of, blocking something initially and then continuing to allow already established communication, can be used on practically any TCP based communication. In fact in the Knockd on DD-WRT 1 ~ 6 movies, I've done way back when, I've used the remote desktop protocol (RDP) which uses port 3389 as an example.

Note: In order to do this, you will need to get Email functionality on your router, which currently there really isn't one that works because the SVN snapshot of OpenWRT's opkg packages is in disarray. That is why I suggest using knockd directly on the VPN box which enables you to use all the options of sending email that are available in Linux/GNU, like SSMTP and sendEmail to mention a few.


Who Disturbs My Slumber?