Knock Knock, can you open the Firewall? (Linux & MikroTik practical examples)
Wouldn’t it be amazing to have no services exposed to simple scanners that continuously scan the public network’s IP addresses without giving up accessing your home network’s resources from the Internet?
Introduction
A lot of people that have a server or NAS at home require to publish some services on the Internet, through the so-called port forwarding technique on their home routers. Exposing services makes them detectable by port scanners, which can understand what machines or servers are running in your home network, which version of software they run and what vulnerabilities may affect them. This analysis can be the first step for a malicious user that wants to penetrate into your intranet.
The linux knockd daemon solution
Some years ago my home router was a simple low-power alix-1c mini-computer and I’ve accomplished the task of having no services exposed to port scanners by using the port knock server knockd: as the linked MAN page explains, this service listens to every packet received on a network interface and can execute specific commands upon the reception of a single packet or, more usefully, a sequence of packets. As the examples on the MAN page show, you can tell knockd to insert an iptables rule when it sees a specific sequence of packets in a specified amount of time, then wait some seconds and execute another command when the timer is expired.
Let’s suppose you have a server with IP address 192.168.0.100 listening for ssh connections on port 22/TCP, which you want to expose on port 1022/TCP on the public network, but only when the router sees a sequence of packets like 2222/TCP, 3333/UDP, 4444/TCP received within 15 seconds time frame, and only for 10 seconds.
To accomplish what I’ve said above, I would configure a permanent port forwarding rule that translates packets with destination port 1022/TCP received on the internet-facing interface, such as ppp0, of the linux router into packets with destination port 22/TCP and destination IP address 192.168.0.100. This is accomplished in the PREROUTING chain of the iptables’ NAT table. Then I would put a jump into a special KNOCKD_FWD_RULES (I’ve named it FWD_RULES because I could have also a special chain for KNOCKD_INPUT_RULES for rules related to traffic destined to the linux router) chain just after the rule that allows ESTABLISHED,RELATED traffic (which has already been authorized) in the FORWARDING chain of the FILTER table and configure knockd to add/remove rules in that special chain to allow traffic destined to 192.168.0.100 port 22/TCP.
Linux implementation example
Iptables configuration (it must be adapted to your configuration, here I’m considering a fresh firewall with a DROP policy on the chains, i.e. drop everything not explicitly allowed):
Knockd configuration:
Note: we open the door only for a TCP SYN packet, because the following packets from the outside will be matched by the first FORWARDING rule that allows packet beloning to RELATED or ESTABLISHED connections.
Now, when you are outside your home network and need to connect to your home server, you can do the following:
- Send the three magic packets to the public IP address of your home router, by using an FQDN such as myhomenetwork.no-ip.org (you can register 3 IPs for free on NO-IP, for example)
- Establish an SSH connection within 10 seconds from the sending of the magic sequence of packets
So, let’s try to connect from a client that exits on the Internet with IP x.x.x.x
ssh -p 1022 myhomenetwork.no-ip.org
[timeout - firewall closed]# Send the magic sequence of packets from client x.x.x.x
nmap -Pn -sS -p 2222 myhomenetwork.no-ip.org
nmap -Pn -sU -p 3333 myhomenetwork.no-ip.org
nmap -Pn -sS -p 4444 myhomenetwork.no-ip.org
[firewall opens the door, new connections allowed from x.x.x.x]
sleep 2sssh -p 1022 myhomenetwork.no-ip.org
[connection established]
[firewall closes the door, no NEW connections are allowed from x.x.x.x]
[established connection from x.x.x.x keeps going on]
What I find beautiful about this approach is that:
- Your firewall is opened only for your client public ip address and only for 10 seconds, so the service is exposed only for the IP address that generated the magic sequence of packets.
- The service stops being exposed after 10 seconds, and if you established a connection within that small time frame, it will not be stopped after the special rule is removed from KNOCKD_FWD_RULES, because your traffic matches the established connections’ accept rule at the beginning of the FORWARD chain. This implies that if your client is NATted on a public IP address with tens of other clients, your service will be opened to the other clients behind the same public address only for 10 seconds, then it will “disappear”.
As you can see on the knockd MAN page I’ve linked above, you can implement even more complex behaviors, by using for example a file with a list of sequences that can be used to trigger a knockd event and each time a sequence is used it is invalidated, in order to avoid reply attacks if someone is sniffing the network where your client is connected and understands the magic sequence you use.
Knocking on a MikroTik door
3 years ago I’ve moved from a Linux router to a MikroTik HAP² router in my home network and I wanted to implement a sort of knockd by using the tools provided by RouterOS. We don’t have a knockd implementation for RouterOS but we can implement the example of the previous section using dynamic ADDRESS-LISTS, which are a useful way to group IP addresses that can be used as matching condition in firewall rules and that allows you to add an IP address with an expiration time.
We can do what follows:
- Check if a packet with destination port 2222/TCP with the SYN flag on is received on ppp0 interface and add the source IP address to KNOCK_FIRST address list with an expiration time of 15 seconds.
- Check if a packet with destination port 3333/UDP is received on ppp0 interface by an IP address within KNOCK_FIRST address list and add the source IP address to KNOCK_SECOND address list with an expiration time of 10 seconds (I decrease the timeout since less packets are needed to complete the magic sequence).
- Check if a packet with destination port 4444/TCP with the SYN flag on is received on ppp0 interface by an IP address within KNOCK_SECOND address list and add the source IP address to TRUSTED_SOURCES address list with an expiration time of 10 seconds, which is the time frame in which the client must start the connection to the temporary exposed service.
- Implement a forwarding rule that allows new sessions from TRUSTED_SOURCES to the intranet service on port 22/TCP of IP 192.168.0.100 (we still allow the established/related sessions to go on, without checking the source).
MikroTik implementation example
This is the MikroTik implementation:
Here you can see the configuration in a more readable syntax-highlighted format (I’m using Sublime-Text with MikroTik syntax highlighing):
You can monitor the insertion of the public IP address in the address-lists with the following command:
[admin@MikroTik] > /ip firewall address-list print
Flags: X - disabled, D - dynamic
# LIST ADDRESS CREATION-TIME TIMEOUT
0 D KNOCK_FIRST x.x.x.x jun/15/2020 15:17:30 12s
1 D KNOCK_SECOND x.x.x.x jun/15/2020 15:17:30 8s
2 D TRUSTED_SOURCES x.x.x.x jun/15/2020 15:17:30 9s
Knocking from a mobile client
In the previous sections I’ve shown you how you can knock from a computer by using nmap, but what if you need to connect to your home server via smartphone or tablet? You can easily find port-knocking applications such as Port Knock on iOS, which allows you to specify the sequence of TCP/UDP packets to send, a port to probe after sending the magic sequence and that even allows you to establish connections via protocols such as SSH (I prefer to use dedicated clients such as Prompt on iOS). Maybe the 10 seconds timeout we’ve used is too short if you plan to connect via mobile using different apps for port knocking and for the SSH connection, I think you can safely increase it to 20–30 seconds.
Follows an example of Port Knock iOS app configuration that knocks to myhomenetwork.no-ip.org on ports 2222/TCP, 3333/UDP, 4444/TCP and after that probes port 1022/TCP to check if it is open, providing you immediate feedback about the reception of the magic sequence by your home router (it also launches an SSH connection to port 1022 with user myuser after knock, but this can be omitted if you want to use some other client for the SSH connection)
Conclusions
I hope that this article will be useful for anyone who wants to make his home network a little bit less exposed to the threats of the Internet. Again, you can try the configurations I’ve shown on EVE-NG with the MikroTik cloud router before implementing them into your network or before convincing yourself to buy one of their amazing routers.
Originally published at http://networkingpills.wordpress.com on June 15, 2020.