Dynamic Address Lists Creation with Port Knocking

Port knocking is a technique used to generate or modify firewall rules on the fly based on connections made to specific predetermined ports. Suppose we have a web-facing service (HTTP, DNS, etc.) that we wish to limit access to based on IP addresses. If all of the clients on the Internet side of the router have static IP addresses, we could simply create address lists in the RouterOS firewall and then open the needed ports only for those address list entries. But what if we have clients on dynamic IP circuits? We can dynamically generate address lists by way of port knocking, with a dash of L7 filtering. First, let’s create an L7 protocol entry:

[sourcecode language=”plain”]
/ip firewall layer7-protocol add comment="" name="port 1234" regexp="^test\$"
[/sourcecode]

What we are doing is creating a layer 7 protocol entry in the firewall that will look for communication on port 1234 and examine the packet payload for the string “test”. Next, we create a filter rule using the L7 entry above that creates an address list entry if the correct conditions are met:

[sourcecode language=”plain”]
/ip firewall filter
add action=add-src-to-address-list address-list=allow address-list-timeout=2h \
chain=input comment="" disabled=no dst-port=1234 layer7-protocol=\
"port 1234" protocol=udp
[/sourcecode]

If a packet is received on port 1234, via UDP protocol, with a payload string of “text”, the sender’s IP address is added to a list called “allow” and that list will expire in two hours. From that point, we can use the “allow” address list to construct a NAT rule that gives access to a certain service inside the network, such as HTTP:

[sourcecode language=”plain”]
/ip firewall nat
add action=dst-nat chain=dstnat comment="" disabled=no dst-port=80 \
in-interface=ether1-gateway protocol=tcp src-address-list=allow \
to-addresses=192.168.88.149 to-ports=80
[/sourcecode]

If an external client’s IP address is on the “allow” list, the NAT rule allows access to a webserver (port 80) inside the network at IP 192.168.88.149. We could also use filter rules to allow access to service(s) on the Mikrotik itself, such as SSH:

[sourcecode language=”plain”]
/ip firewall filter
add action=accept chain=input comment="" disabled=no dst-port=22 protocol=tcp \
src-address-list=allow
[/sourcecode]

We would probably want to expire the list faster than two hours for SSH access, as well as create a sequence of ports and payloads that must be used. A good presentation on extending the port knocking theory with multiple ports and address lists can be found here: http://mum.mikrotik.com/presentations/US10/discher.pdf.

Now, let’s look at how we knock the port(s) from a client machine. There are several utilities to do this, but we’ll use Nping which is part of the Nmap collection (http://nmap.org/). In this case, we’ll use the command line version:

[sourcecode language=”plain”]
C:\>nping 1.2.3.4 –udp -p 1234 –data-string "test"
[/sourcecode]

We replace 1.2.3.4 with the real IP address of the router’s public (WAN) interface, set the UDP option, and craft a data string payload (in double quotes) of “test” that matches our L7 protocol in the router. Once the command is sent, the router should then create an address list entry with our IP address. By using the command line version, we can also create a script and/or schedule Nping to launch every so often to update the address list entry. If the client IP changes, the script would update the router list, and the old entry will expire in two hours.

For a GUI port knock app, have a look at Greg Sowell’s: http://gregsowell.com/?p=2020.