With the management protocol vulnerabilities, there’s been an interest in port knocking. I’ve been playing around with an alternative using icmp packet sizes as the key. I call it Ping Knocking.
# Choose some random ping packet sizes of at least 100 as a knock sequence.
# Add 28 to the size in the firewall to compensate for protocol overhead.
# After a matching knock sequence, services will be allowed for an hour from your src ip.
/ip firewall filter
# Place this rule early in the list.
add action=jump chain=input comment="Check port knock" icmp-options=8:0-255 jump-target=knock packet-size=!0-99 protocol=icmp
add action=accept chain=input comment="ACCEPT TLS after knock" dst-port=443 protocol=tcp src-address-list=KNOCK-SUCCESS
add action=accept chain=input comment="ACCEPT SSH after knock" dst-port=22 protocol=tcp src-address-list=KNOCK-SUCCESS
add action=return chain=knock comment="KNOCK FAILURE return" src-address-list=KNOCK-FAILURE
add action=add-src-to-address-list address-list=KNOCK-SUCCESS address-list-timeout=1h chain=knock comment="KNOCK 3rd - success 600" packet-size=628 src-address-list=KNOCK2
add action=return chain=knock comment="KNOCK 3rd - success return" src-address-list=KNOCK-SUCCESS
add action=add-src-to-address-list address-list=KNOCK-FAILURE address-list-timeout=1m chain=knock comment="KNOCK 3rd - failure" src-address-list=KNOCK2
add action=return chain=knock comment="KNOCK 3rd - failure return" src-address-list=KNOCK-FAILURE
add action=add-src-to-address-list address-list=KNOCK2 address-list-timeout=1m chain=knock comment="KNOCK 2nd - success 500" packet-size=528 src-address-list=KNOCK1
add action=return chain=knock comment="KNOCK 2nd - success return" src-address-list=KNOCK2
add action=add-src-to-address-list address-list=KNOCK-FAILURE address-list-timeout=1m chain=knock comment="KNOCK 2nd - failure" src-address-list=KNOCK1
add action=return chain=knock comment="KNOCK 2nd - failure return" src-address-list=KNOCK-FAILURE
add action=add-src-to-address-list address-list=KNOCK1 address-list-timeout=1m chain=knock comment="KNOCK 1st - success 400" packet-size=428
add action=return chain=knock comment="KNOCK 1st - success return" src-address-list=KNOCK1
add action=add-src-to-address-list address-list=KNOCK-FAILURE address-list-timeout=1m chain=knock comment="KNOCK 1st - failure"
The advantage of this strategy is that you don’t need special knocking software. You can use a command line ping utility, or simple batch file on Windows:
That’s a question. Http allows to keep connection open and reuse it for further requests. Web server in RouterOS looks like it supports it. But browsers usually use more than one connection for same server and you have no guarantee that all will stay open. And when access for new connections from client times out and it happens that browser will need to open new connection, it will fail. So it might work, but I wouldn’t bet on reliability.
I was attempting to get specific behavior. It appears that some of the knock strategies accept the port sequence with any number of incorrectly guessed ports in between. In other words, a full port scan three times will succeed in opening the management ports. I wanted something that demanded exactly the correct sequence, and would reject a user that offered anything other than the correct sequence. This should provide about 31 bits of entropy (log2(1370^3)) for a guesser to deal with, at a rate of one guess per minute. Enough to cause difficulties for the bots anyway.
Even with the timeout as provided, the penalty of a lost packet is only that you must wait one minute. You’re also free to change the timing to a smaller duration.
Out of curiosity, what kind of network are you on that you’re unlikely to get three ping packets across?
Various ones, that’s the point. When in one of my domestic networks I don’t need road warrior setups; when roaming I’m glad to have some connection at all - mobile, hotel wifi etc. and these can be far from perfect in various parts of the world.
I know I’m rehashing an old post, but this issue has me stumped.
I have done the same thing for demo purposes for the longest time. I’m doing this again this morning and it doesn’t work.
A bit of troubleshooting and I realize that the ICMP-TIMEOUT in conntracking is the issue. If I reduce that value to 2 secondes and add a “ping 127.0.0.1 -n 5” in my batch file, then everything works as expected.
Two questions:
1- Did something change in recent versions that I missed?
2- Is there an impact at shortening ICMP-TIMEOUT?
I’m not using that field. As I inspect the conntrack table, I see my ICMP connection there for 10 secs even though my ping only sent one packet. This is why my other pings are not seen by the other filters as the routeur thinks it’s still the same connection.
I would have guessed that once the ping stops, so does the connection, but not the case
@AlainCasault, from what you wrote I’ve also suspected that something else must have changed.
The timeout (defaulting to 10s) is there to allow ping request and responses with the same value in the identifier field to be recognized to belong to the same connection. The ping utility of most operating systems sends one request per second by default. That means that with a 2s timeout in the connection tracker, a single lost ping request from a sequence may be enough for the connection to disappear from the connection tracking, but that would only cause some trouble in very specific cases (not related to the knocking).
As a separate instance of the ping utility is started in the batch for each packet size, each should send the request with a different identifier value, so even though it is sent from the same source IP to the same destination, each should create its own tracked connection, which is what @coylh’s state automaton relies on - although the firewall rules matching ping packets by size don’t explicitly check connection-state=new, they do implicitly because they follow the chain=input action=accept connection-state=established one, so any ICMP echo request packet matching an already established connection is accepted by that one and never reaches those following rules which check the packet size.
As this is what must be happening in your case and can be affected by reducing the ICMP timeout in the connection tracking settings, there are two possibilities - either your client side OS has started to send the same ID in all requests, or Mikrotik’s connection tracking stopped checking the identifier value.
So I’ve made a test on 6.44.3, and the outcome is that while the connection tracking does check the identifier value, the ping “client” in RouterOS only changes (increments) the identifier value if it hasn’t sent any outgoing echo request for some 15 seconds, and it even reuses the same identifier value for pinging any destination. Plus the sequence numbers in the requests do not start from 1, but that may not be exactly wrong, I haven’t studied the RFC.
The reuse of the identifier value is definitely a bug worth reporting, so according to the rule “you’re affected, you report it” it is your call now to double-check my observations and open a ticket at support@mikrotik.com.