I’ve been looking through the wiki and googling but haven’t found anything on this
I’ve got port knocking working in my basement lab connected to my internal network and verified the wan side from my existing lan segment (before I move to be my primary router to the Internet)
However I wonder if I can restrict the source addresses where port knocking can occur from? Right now if I put the source networks in my portknock_allowed list it will be implicitly open
Just would like to restrict port knocking to specific addresses instead of entire public network
You can add a src-address=x.x.x.x/m criteria to the first port in the port knock list.
Also, if you have more than one range of addresses, you can create an address list called e.g. knock_sources, populate it with the IP blocks you wish to permit and use src-address-list=knock_sources in the first port of the knock sequence.
Although one might make the case that this defeats the purpose of port knocking.
Port knocking is basically there to protect the presence of a protected port from scanning activities. The port, when opened via a successful knock, should still have standard security measures on it anyway. The idea of port knocking is to allow people to access a port from arbitrary sources. If you know where you want the access to come from, you may as well just leave the port open but filtered to only that set of addresses and not require the knock. Obviously, the particulars of your case may be different and require the additional measure, but in general I’d say that there’s no need for a port knock sequence from only a specified list of sources.
Port nocking is that a port is opened to only the knockers address after knocking on other ports in the right sequence.
An other sequence can close the port again after usage on for that external address. This by generating a addresslist of to close addresses by an script.
I don’t known how to use the sequence on only the port that is to be opened.
Actually, what you can do is make the final rule which opens the protected port do so with only a 60-second timeout. So long as your filter rules have entries which allow established,related connections, then the access to the protected port will continue working even after the knock expires.
Example:
Suppose you’re protecting port 22 of the Mikrotik itself.
This is protected by the input chain
Suppose the input chain has a flow something like this:
allow established,related
allow icmp
allow LAN interfaces
port knock sequence (successful knock grants access for 60 seconds)
allow tcp/20 from hosts in the “knock_success” list
drop everything else
if some unknown remote host attempts to connect to port 22, the SYN packet will be dropped and the sender will have to wait and eventually time out the attempt.
If some friendly remote host completes the port-knock sequence, then they are added to the “knock_success” list for 60 seconds.
The knock-authorized host then connects to port tcp/22 and establishes an SSH session.
Then the knock_success times out.
After this, if the remote host attempts to make a second connection to tcp/22, this will be ignored by the router just as the first example (unknown remote host).
However, the established session will not be broken because it is allowed by the established,related rule which comes first in the input chain.
I use port knocking for some remote access. I am doing exactly what the OP is wanting to do. My “normal” port knock is four steps. I have a short port knock that only works from one address that only takes two steps. That way when I’m at the one specific address, I can get in easier, but when not coming from that one address, I have to use the four step port knock (which does not use the same ports as the two step).
BTW, any time the final step is reached (either the two step or the four step), the router sends me an E-Mail so I know right away that the port knock has been used.
I tried the established/related with an IKe2 connection however I can’t get it blocked in filters. I assume the IPSEC module establish the connection by itself, and the only way to block is to use RAW filter.
What I was trying to explain (but perhaps I was in a rush just before posting) is…
\
Use port knocking 3 or 4 steps or whatever to get in to the protected device (e.g. a computer behind the Mikrotik or the Mikrotik itself)
Limit which hosts can actually do the port knocking to a specific set of address blocks that actually can even attempt to do the port knocking so the public internet has no chance of port knocking.
Here are my rules right now… and I can put the addresses that I want into the PORTKNOCK_ALLOWED but then it is explictly allowed regardless of port knocking. I’d just like to limit where the port knocking can actually occur so that way it can be obscure to even trusted hosts until I activate it myself. Perhaps the “Src Address” could be used but then you would have to do multiple rules for your trusted hosts.
I have one comment about your port knock design. This may sound nit-picky, but following best practice and “structured” design helps make things easier to troubleshoot for both yourself and for anyone else who has to administrate a box after you… May not be an issue if this is a home router, but good habits are always worth forming…
Your rules cause a successful knock to add the authenticated host to a dstnat rule. Otherwise, the pinhole “doesn’t exist” for that source.
This is not the best way to do this.
It would be better for the dstnat to always exist w/o any criteria on who the source is, etc.
In essence, the dstnat rule means: “Port 1234 = ssh to my internal box”
This should be true for all cases.
Anyone you don’t want having access to this pinhole should be filtered using the filter table. Don’t get in the habit of making translations that work in some cases and not others. In your simple situation, there’s no big difference except some obscure academic “best practice” concept - but imagine there were many more rules (hundreds) and the functionality of access filtering is woven between whether something nats or not / whether it’s filtered or not. . . different behavior in different rules. It would be a nightmare to debug if something were to go wrong.
So make the pinhole work for all IP addresses, but then use the forward chain of the filter table to limit access to it - i.e.. the src-IP is in the “hosts-who-have-successfully-knocked” list.
And I’m not sure if I confused you, but in my original suggestion, I meant that there should be a list of “hosts-who-may-knock” which is not the same as “hosts-who-have-knocked-successfully” or the phase1, phase2, etc. lists. Just make the phase1 rule also require that the src-address be in the “hosts-who-may-knock” list. Think of it as a static permanent phase0
and you rely on the filter of PORTKNOCK_ALLOWED to actually allow it to make it to the NAT rule.
I’m a unix/network admin so the feedback is welcome on this sort of thing for better design anyway even if this is to be used in a home network at this point. I’m tired of consumer gear issues and my OpenWRT/LEDE 17.01.4 on my TP-LINK TL-WDR4300(s) has been sporadically crashing lately with unknown reboot(s) every couple of days to hours sometimes. I didn’t experience with Chaos Calmer 15.01 (OpenWRT) but the project has fallen behind/stalled (and security bug fixes are lacking) after the LEDE project split off (and I know they are supposed to be reforming as OpenWRT).
So I’m doing a RB750GR3 and I’ll be using 1 Unifi AC-PRO in the house and 1 in the backyard shed (when we build a new one next year (run a cat6 to it)) to (hopefully) provide coverage of our 1500 sq ft 2 storey (brick exterior) house and the backyard (hopefully two of these will be enough). My understanding is the Unifi should have much better coverage than consumer routers anyway (400ft (I know unobstructed but my 45ft long house with this on the top floor should be adequate).
Right now my router/AP is in the front closet of the house by the entry door and another one (rtr as an AP only) in a corner in the master bedroom. I ran cat6 throughout the house but I never thought about 2 jacks at every room (except I do have cat6 for phone lines that could be re-purposed I suppose) nor the budget/time (I have more than 2 ports in some rooms such as my office and home theatre area but bedrooms have one coax, one telephone cat6) and one network (cat6)). However, by splitting the router and AP into the Mikrotik and Unifi I don’t have to worry about where the router is located and then I can put the AP at one of the other jacks such as the book case at the top of our stairs to the 2nd floor (with a combined device I couldn’t do that)
( I will likely move the modem and router to the front closet (so as to not clutter the basement patch panel wiring area). Currently the router only in the front closet with a jack from the cable modem and one back to my LAN switch. I have coax in the closet so I can put cable modem there and run a LAG to my switch or 1 to my 24 port and 1 to my 8 port switch instead of back and forth because of the AP location )
Anyway, I’m not sure how to incorporate “hosts-that-may-knock” into these rules along with having “hosts-who-have-knocked-successfully” and I’m open to changing to this sort of rules that make more sense than “PORTKNOCK_ALLOWED”.
As I said I’d like to just limit where the port knocking can occur from and I guess you can’t have 2 src-address-lists accompanying an input rule but could you do a jump or something to continue the rule matching or something?
That is, check for hosts is in “hosts-that-may-knock” and if they are in that then check to see if they are knocking successfully and if so add them to the “hosts-who-have-knocked-successfully”
I know that I’m likely going to be address space of my country at bare minimum and likely from specifically places where I work or play but I likely won’t be knocking from a foreign country and if I was in a foreign country I may go through an intermediary host first.
That happens for symmetric connections because the device is making an outbound connection attempt at the same time which puts a connection entry in the table and allows the traffic through the established/related match which usually is the first in the table.
You can prevent that by putting your block rules before that established/related rule. Of course the more you put there, the more overhead. But putting them in the RAW table has the same effect (as this is processed before the forward/input tables as well).
I don’t know what I did wrong yesterday evening but it works now PERFECTLY…I am so ashamed that I did manage to implement something that simple in one go.
Many thanks to ZeroByte for the setup and pe1chl making me having a new run at this!!!
update: I do now know why it did not work yesterday evening.
So my RAW filter Returns the traffic and Filter Rules looks if it is New traffic with a address stated in the address-list. Nothing in the address-list then goes to the bottom and get some how automagically accepted. By what or who I don’t know so I have now a selective drop on UDP at the bottom that is catching those connections that bugged me yesterday.
Well your design may work when you want to leave your pinhole ssh connectivity to the entire public internet when you attempt to do a knock sequence, it does not work when you want to restrict the access to a specific set of subnets or hosts. I have been playing with this setup and your suggestion to not have a src-address-lists on the dst-nat will in fact allow access in from unauthorized IP addresses from my testing (if you don’t put a restriction on dst-nat rule)
Sorry I changed the original 1234 NAT port to 1022 so as to not confuse my port knocking ports (obfuscated from my config) of 1234, 567, 890
If I enable this rule #7 then it will allow connections from my test hosts of 192.168.1.15 and 192.168.1.11 WITHOUT PORT KNOCKING sequence in fact…
I found that if I use a jump rule I can in fact do the source based address list (hosts-who-may-knock) to then go into the port knocking test at that point to get access. I disabled my existing rules and create new rules under a chain called input-knock and jump to those based on the src-address-list.
15 chain=input action=jump jump-target=input-knock src-address-list=hosts-who-may-knock
16 X ;;; accept WAN connections inbound on port 1022 to Mikrotik RTR destined for computer on port 22
chain=input action=accept connection-state=new protocol=tcp src-address-list=PORTKNOCK_ALLOWED in-interface=ether1 dst-port=1022 log=no
log-prefix=""
17 X chain=input action=accept connection-state=established
18 X chain=input action=add-src-to-address-list connection-state=new protocol=tcp src-address-list=PORTKNOCK_STAGE_2 address-list=PORTKNOCK_ALLOWED
address-list-timeout=15m in-interface=ether1 dst-port=890 log=no log-prefix=""
19 X chain=input action=add-src-to-address-list connection-state=new protocol=tcp src-address-list=PORTKNOCK_STAGE_1 address-list=PORTKNOCK_STAGE_2
address-list-timeout=20s in-interface=ether1 dst-port=567 log=no log-prefix=""
20 X chain=input action=add-src-to-address-list connection-state=new protocol=tcp address-list=PORTKNOCK_STAGE_1 address-list-timeout=20s
in-interface=ether1 dst-port=1234 log=no log-prefix=""
21 ;;; drop all other WAN connections inbound to MikroTik RTR on WAN port (ether1)
chain=input action=drop in-interface=ether1 in-interface-list=WAN log=no log-prefix=""
..
..
29 ;;; accept WAN connections inbound on port 1022 to Mikrotik RTR destined for computer on port 22
chain=input-knock action=accept connection-state=new protocol=tcp src-address-list=PORTKNOCK_ALLOWED in-interface=ether1 dst-port=1022 log=no
log-prefix=""
30 chain=input-knock action=accept connection-state=established
31 chain=input-knock action=add-src-to-address-list connection-state=new protocol=tcp src-address-list=PORTKNOCK_STAGE_2
address-list=PORTKNOCK_ALLOWED address-list-timeout=15m in-interface=ether1 dst-port=890 log=no log-prefix=""
32 chain=input-knock action=add-src-to-address-list connection-state=new protocol=tcp src-address-list=PORTKNOCK_STAGE_1
address-list=PORTKNOCK_STAGE_2 address-list-timeout=20s in-interface=ether1 dst-port=567 log=no log-prefix=""
33 chain=input-knock action=add-src-to-address-list connection-state=new protocol=tcp address-list=PORTKNOCK_STAGE_1 address-list-timeout=20s
in-interface=ether1 dst-port=1234 log=no log-prefix=""
34 ;;; drop all other WAN connections inbound to MikroTik RTR on WAN port (ether1)
chain=input-knock action=drop in-interface=ether1 in-interface-list=WAN log=no log-prefix=""
35 chain=input-knock action=return
During my testing from 192.168.1.15 I can get in using the port knocking sequence but could not get in from my test node 192.168.1.11 until after adding to the hosts-who-may-knock address list and then following the port knocking sequence.
[admin@MikroTik] /ip firewall address-list> print
Flags: X - disabled, D - dynamic
# LIST ADDRESS CREATION-TIME TIMEOUT
0 ;;; TEST BOXES
hosts-who-may-knock 192.168.1.15 nov/14/2017 14:39:32
1 hosts-who-may-knock aaa.bbb.0.0/16 nov/14/2017 14:39:38
2 hosts-who-may-knock xx.yyy.zzz.0/28 nov/14/2017 14:39:41
3 hosts-who-may-knock ccc.ddd.ee.0/24 nov/14/2017 14:39:45
4 D PORTKNOCK_STAGE_1 192.168.1.15 nov/14/2017 17:44:06 4s
5 D PORTKNOCK_STAGE_2 192.168.1.15 nov/14/2017 17:44:09 6s
6 D PORTKNOCK_ALLOWED 192.168.1.15 nov/14/2017 17:44:12 14m50s
[admin@MikroTik] /ip firewall address-list>
I hope this helps out someone else in the future that wants to restrict the port knocking to specific network segments/hosts and not leave it open to the public internet and as I said in my testing you need to put a source address list on the dst-nat or you are allowing access directly to the NATed port. You can restrict the port knocking to known address blocks or reverse the logic and put in known blacklists or countries known to have lots of hackers, etc For me I want to allow this only from the places I work or play or my devices
I suppose I could do like one of the posters suggested and make a more complex sequence for the general internet usage possibly in the future. I’d like to know how to send the string sequence for port knocking next.
I use my access on Android and the app I use is Port Knocker and you can automatically open the used client which is using just opened port.
Limiting the exposure of the possibility to knock can be done in RAW filters with address-list. List for counties can be generated on mikrotikconfig.com
The most likely reason your filter didn’t work on the “wide open” dstnat rule is because you’re using the input chain for most of the work in your port knocking sequence, and I presume that you are also trying to filter the pinhole the same way.
Since your knock-protected port is one which will be dstnat translated to an internal host, the access to this port must be done with the forward chain in the filters table, not the input chain.
So if you have an un-qualified NAT rule:
action=dstnat protocol=tcp dst-port=1234 to-address=192.168.88.2 to-port=22
this would of course NAT in all situations…
To filter it, you would use a filter rule like this:
/ip firewall filter add chain=forward protocol=tcp dst-port=22 src-address-list=knock_authorized dst-address=192.168.88.2
A few notes:
note that the dst address and port are the internal versions, not the public IP/port. This is because dstnat happens BEFORE filtering, and srcnat happens AFTER filtering
this is now a forwarded connection (throguh the router, not to the router) so it is in the forward chain
This rule should come after the accept established/related rule so that it’s only checked on new connections.
If there’s a rule in your forward chain which allows connection-nat-state=dstnat , then you’ll need to make another rule which blocks dst=192.168.88.2 dst-port=22 and place it BEFORE the rule which allows dst-nat state connections.
OK I’m a bit confused now… does the Mikrotik have an implicit permit all at the end of the firewall rules that we have to explicitly deny?
I just inserted a new rule 25 to explicitly drop wan dstnat at the very end… iptables which I imagine this firewall is based on has an implicit deny all at the end. All other commercial firewall’s I’ve ever dealt with have an implicit deny rule at the end.
Maybe this is what has been messing me up as I was expecting an implicit deny at the end of the access list. So I need to explictly put a deny at the end of the input, output, forward and my new input-knock chains then?
18 ;;; defconf: accept in ipsec policy
chain=forward action=accept log=no log-prefix="" ipsec-policy=in,ipsec
19 ;;; defconf: accept out ipsec policy
chain=forward action=accept log=no log-prefix="" ipsec-policy=out,ipsec
20 ;;; defconf: fasttrack
chain=forward action=fasttrack-connection connection-state=established,related
21 ;;; defconf: accept established,related, untracked
chain=forward action=accept connection-state=established,related,untracked log=no log-prefix=""
22 chain=forward protocol=tcp dst-address=192.168.88.254 src-address-list=PORTKNOCK_ALLOWED in-interface=ether1 dst-port=22
23 ;;; defconf: drop invalid
chain=forward action=drop connection-state=invalid
24 ;;; defconf: drop all from WAN not DSTNATed
chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface-list=WAN
25 chain=forward action=drop connection-state=new connection-nat-state=dstnat in-interface-list=WAN
This seems to work now if I have my nat rules like this
Yes, it does. When you want to deny everything that falls through the list, you need to place a deny (or drop) without any matching at the end of the list.