Knockd is a daemon that listens to communication events at the link layer for sequences then acts on them.
what this means, is that you can have the machine running the daemon not even "listen" on the ports (a port scan will not see them as open) and still make it do something you need, from a single command to a full script.Using this technique you could trigger the server to perform any sort of operation you need of it remotely (across the internet) without exposing your home network.
For more information, even though the installation instructions don't work anymore, feel free to have a look at my youtube series about using it on the DD-WRT router.
Overview
what we are going to do is:- setup the server to quietly "listen" for the safe sequences without revealing that its doing so (ports are closed).
- send the sequences using the commonly used telnet command from anywhere other then our home network.
- the server will perform some example operations:
- Email us that a sequence was received and from what IP.
- wake up a neighbor computer
- connect to a Linux based router (Tomato) and open an additional port for 20 seconds and auto close it.
Prerequisites
- Some TCP/IP knowledge is assumed - to keep this page from becoming a two volume book on TCP, i assume you understand how TCP/IP works and what are IP addresses and ports.
- You will need to forward the ports used for the knocking on the router to the machine that is running the daemon.
While less efficient then simply having it on the router, by no means less secure (remember they can be none-open ports and this will still work). - You have already setup Email support for the server using the "Email setup for alerts" guide.
Installation
The installation could not be simpler on Debian, all you need to do is issue:sudo aptitude install knockd
Configure sequences
Once you have installed the package, you need to configure the action you want the daemon to take and the triggering sequences for them.Edit the configuration file /etc/knockd.conf:
sudo vim /etc/knockd.conf
This file has some examples of options you may wish to use.The first default option i leave in there is:
[options] UseSyslog
This configuration will make knocked use the syslog facility instead of a file (like it used to be on the router).Enabling the daemon & starting it
In order to make the daemon enabled for use & startup, it is necessary to edit its syscrl file:sudo vim /etc/default/knockd
Iin the file, change the "start" parameter to 1 to enable it:START_KNOCKD=1
start the daemon by issuing:sudo /etc/init.d/knockd start
WOL sequence
WOL is an acronym for Wake On Lan.This enables you to tell other computers on the network to turn on when you send a specially formed packet to them over the network.
Prerequisites
- You need to enable WOL for the target computer - This is usually a combination of a BIOS setting and a driver setting (out of the scope of this article).
- You have already setup Email support for the server using the "Email setup for alerts" guide.
What we will configure is:
- The sequence that will trigger the script.
- A script that will take the MAC of the computer we want to turn on as a parameter.
- The script will Email us that the command has been issued to what MAC and from what IP.
Doing it this way, has the added advantage of informing you (via Email) that the command was executed (instead of blindly hoping that it did).
Also in case you didn't do the knocking, you both will at lease know that is happened and who did.
Required package
You need to install WOL support for your server, on Debian based systems this is accomplished by simply issuing:sudo aptitude install etherwake
The sequence template
Edit the knockd configuration file:sudo vim /etc/knockd.conf
Add this entry to it:[WOL-Laptop] sequence = 04,04,04,2012,2012,2012,03,03,03 seq_timeout = 50 command = /home/aviad/knockd_wake_up.sh my_laptop %IP% tcpflags = syn
This entry will:- Make a new sequence that will require 3 telnet commands on the ports 04, 2012 and 03.
- Give the sequence 50 seconds to be completed from the moment it was started.
- Call the script we will create later and pass to it two parameters:
- The name of the computer we want to wake
- The IP address of the computer that made the knocking request.
The wake up script
Create a new file:sudo vim /home/aviad/knockd_wake_up.sh
Make this its content:#!/bin/bash email_admin_script() { echo "To: youremail@some-domain.com" > $temp_email_file echo "From: servername@some-domain.com" >> $temp_email_file echo "Subject: Server-name knockd WakeUp" >> $temp_email_file echo "" >> $temp_email_file echo $e_body >> $temp_email_file echo "" >> $temp_email_file echo "As requested by:" >> $temp_email_file echo $from_ip >> $temp_email_file /usr/sbin/ssmtp -t < $temp_email_file echo "Sent an Email to the Admin" } temp_email_file=/tmp/wake_tmp.txt computer="$1" case "$computer" in my_lapotp) e_body="Woke up computer Aviad's E6400 Laptop" MAC=00:81:52:6B:3D:AE ;; my_desktop) e_body="Woke up computer Aviad's E6400 Laptop" MAC=00:18:65:3F:1C:86 ;; esac from_ip="$2" /usr/sbin/etherwake $MAC email_admin_script rm $temp_email_file
This script will take the two parameters that where passed by the knockd daemon, as its input and use them to:- Wake a computer using the etherwake command.
- Send an email to the administrator to let him know that the command has been issued and by whom.
In order to add more computers, simply add additional sequences to the knockd configuration file and expand the "case" statement branches in the script.
start the daemon by issuing:
sudo /etc/init.d/knockd start
Restart the daemon for the settings to take affect, by issuing:sudo /etc/init.d/knockd restart
That's it you should be done.VPN sequence
This sequence will communicate with the home router to open additional ports for VPN communication in response to a knock.By doing this the security of the VPN connection is increased without really changing how the VPN works (i.e. there is no need to change the client and generate certificates etc).
Note: I don't recommend novices to try this one as its way overly complex and is very tied to a specific setup, beyond the fact that it isn't very well tested...
It is possible to have the script change locally set iptable rules instead of the routers rules, but wheres the fun in that?
But in all seriousness I have invested to much energy into this page to simply throw it away...
Also I am truly sorry that it isn't well tested, but since I started writing this page to the time I finished, I have stopped using Tomato as the router firmware and the "home server" as the VPN server, and have returned to using the router as the VPN server with knockd on DD-WRT. This was made possible with the aid of the firmware development kit, which enabled me to inject the knockd and ssmtp packages to the mega firmware on my 8MB flash device (WRT54GSv3 thanks to Mike:)
With that said, once you have the SSMTP and the knockd packages installed on the router (if you managed to rape ipkg to work or by using the dev kit), you can use my personal configuration page here.
Preface
- I used a router with the Tomato firmware.
- I am assuming that you have telnet\SSH access to the router.
- The router is connected to the ISP by using an L2TP type of a dialer.
My configuration file looks like this:
(Of course i have changed the actual port sequence)
[enable-VPN] sequence = 02,02,02,01,01,01,2010,2010,2010 seq_timeout = 120 start_command = /home/aviad/enable_vpn.sh %IP% cmd_timeout = 20 stop_command = /home/aviad/disable_vpn.sh
This configuration will:- Set the window of opportunity, of the sequences' completion, to 120 seconds.
- 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, run the script in /root/enable_vpn.sh and pass to it the IP address of the requester (thats the meaning of the %IP% parameter).
- Wait for 20 seconds and issue the /root/disable_vpn.sh script.
*We are using "three knocks" because that's the way telnet (our call back home program) acts when it cant reach the port, it tries three times before quitting.
Create the action scripts
Our script will connect back to the router that's running the Tomato firmware and inject three additional iptable rules.(it was possible to do on the local server, but this is way cooler ^_^)
The enable script
Ccreate a new script and edit it:sudo vim /home/aviad/enable_vpn.sh
Make this its content:#!/bin/bash ssh root@192.168.1.1 '/sbin/gpio disable 2; /usr/sbin/iptables -t nat -I PREROUTING 2 -d $(nvram get l2tp_get_ip) -s '$1' -p tcp --dport 1723 -j DNAT --to 192.168.1.51:1723; /bin/sleep 2; /sbin/gpio disable 3; /usr/sbin/iptables -I wanin 1 -p tcp -s '$1' -d 192.168.1.51 --dport 1723 -j ACCEPT; /usr/sbin/iptables -t nat -I POSTROUTING 2 -s 192.168.1.0/24 -d 192.168.1.51 -p tcp --dport 1723 -j SNAT --to $(nvram get wan_ipaddr)' exit 0
lets brake it down:
- ssh root@192.168.1.1 - connects to the router using SSH (we will setup no password login in the next step) and run the commands in the quotations.
- gpio disable 2; - turns the router front led on with the orange color (disable=turn on, enable=turn off)
- iptables -t nat -I PREROUTING 2 -d $(nvram get l2tp_get_ip) -s '$1' -p tcp --dport 1723 -j DNAT --to 192.168.1.51:1723 - adds a rule to the NAT table that anything destined for the L2TP was IP with the ogf port 1723 will be directed to the 192.168.1.51 address on the same port.
- sleep 2; gpio disable 3; - sleep for 2 seconds and activate the white led on the front of the router.
- iptables -I wanin 1 -p tcp -s '$1' -d 192.168.1.51 --dport 1723 -j ACCEPT; - add a rule to allow communication from the "wan input" interface to the server only to the address that was passed from the knockd request. (the $1 script parameter is equal to the %IP% parameter)
- iptables -t nat -I POSTROUTING 2 -s 192.168.1.0/24 -d 192.168.1.51 -p tcp --dport 1723 -j SNAT --to $(nvram get wan_ipaddr) - get the IP address of the "WAN" interface (witch apparently isn't the same as the dialer address and source NAT anything from the 192.168.1.0/24 network to the server.
- exit 0 - inform the parent script that the script ran correctly.
The disable script
Create a new script and edit it:
sudo vim /home/aviad/disable_vpn.sh
Make this its content:#!/bin/bash ssh root@192.168.1.1 '/sbin/gpio enable 2; /usr/sbin/iptables -t nat -D PREROUTING 2; /bin/sleep 2; /sbin/gpio enable 3; /usr/sbin/iptables -t nat -D POSTROUTING 2; /usr/sbin/iptables -D wanin 1' exit 0
Lets brake it down:- ssh root@192.168.1.1 - connects to the router using SSH and run the commands in the quotations.
- /sbin/gpio enable 2; - turns the router front led on with the orange color off.
- /usr/sbin/iptables -t nat -D PREROUTING 2; - delete the rule that enabled NAT from out to in.
- /bin/sleep 2; /sbin/gpio enable 3; - sleep for 2 seconds and turn off the white led on the front of the router.
- /usr/sbin/iptables -t nat -D POSTROUTING 2; - delete the the rule that enabled PAT to the server.
- /usr/sbin/iptables -D wanin 1 - delete the rule that enabled communication from the "wan input" to the server.
- exit 0 - inform the parent script that the script ran correctly.
Make the scripts executable:
sudo chmod +x /home/aviad/enable_vpn.sh sudo chmod +x /home/aviad/disable_vpn.sh
Restart the daemon for the settings to take affect, by issuing:sudo /etc/init.d/knockd restart
Setting up a password-less trust
Because we are using SSH to send the commands from the server to the router, and we want the operation to be performed automatically, we need to make the router trust our server.We will do this by creating a public key on our server and inject it into the router.
- Create the RSA public key for the root user (that's the user that will be executing the commands) :
sudo ssh-keygen -t rsa
- Get the content of the public key:
sudo cat /root/.ssh/id_rsa.pub
- The output should look something like:
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA8vBGqHoqY+VPl3VcxmmSprhc0YkhuhPKc1gmKtZ/sLmEB1v3TVeNuTpow0eBdG1JGVTiOfrlkTcrOK1Tm5Kw/I4mb1eAzLKl4Iix8W++FXYon4m2/ygINUhcioBARWe4FzajsS35FnKkjwy8ALGtKk+cU7yRojGr0zMzvVH1XwIzaLiQTKx0xOoftpr5a8Xja84JcMKI2K25mHTvs+XF8ELVqFqTOPNFohAgZBzSlZMuKuAiV4N7z+Htw47sGDo3Dos8ZwHGnOgPQQYTahKGP0dTkk8TBZ7yvQXEsB8X4EmSN2UoWcmqabUA2p7WCnD/s+lDWWEIJpxFmM8LY834mw== root@lenny64template
- Because the router will erase the key on every reboot, we need to create a startup script that will re inject the key back, once the router has been restarted.
- Log into the routers' web-GUI, and go to:
- "Administration"
- "Scripts"
- "WAN Up"
a. Select the "Word Warp" check box (just so the out put would be clearer to read)
b. Type in: echo "past-your-server's-public-key-here"
c. After the key, append to the end of the line, " > /root/.ssh/authorized_keys" (note the space), so that this command will add the servers public key into the authorization keys , as shown in the picture below.
Testing the configuration
Once you have a sequence configured you should be able to see the daemons reaction to knocks by viewing the syslog output while doing some knocks.For this example we will assume you have the sequence of 02, 01 and 2010 set.
You can do that by issuing the tail command on the server:
sudo tail -f /var/log/syslog
On a remote network, open a command prompt and telnet back to the network:telnet your.routers.ip.or.dns 02 telnet your.routers.ip.or.dns 01 telnet your.routers.ip.or.dns 2010
Remember, telnet tries 3 times automatically if the port is unreachable for communication.The output of a successful knock should look like:
May 30 10:01:10 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 1 May 30 10:01:13 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 2 May 30 10:01:14 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 3 May 30 10:01:18 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 4 May 30 10:01:21 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 5 May 30 10:01:25 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 6 May 30 10:01:29 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 7 May 30 10:01:32 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 8 May 30 10:01:33 lenny64template knockd: 62.213.132.44: enable-VPN: Stage 9 May 30 10:01:33 lenny64template knockd: 62.213.132.44: enable-VPN: OPEN SESAME