My question might seem simple, but I can’t find the solution. I would like to create dynamic firewall rules with lists of named dynamic and fixed IP addresses. In my example, I am working on securing TCP SSH, HTTPS, and WINBOX connection access to the router:
# 2024-01-13 18:18:18 by RouterOS 7.13.1
# software id = 2UXQ-7TH0
/ip firewall address-list
add comment="List of allowed IPs" list=IPGreenList
add comment="List of banned IPs" list=IPBlackList
add comment="List of IPs blocked for 10s" list=IPBlocked10s
add comment="List of IPs blocked for 30s" list=IPBlocked30s
/ip firewall filter
add action=jump chain=input connection-state=new dst-port=22 jump-target=ssh-auth protocol=tcp
add action=jump chain=input connection-state=new dst-port=443 jump-target=https-auth protocol=tcp
add action=jump chain=input connection-state=new dst-port=8291 jump-target=winbox-auth protocol=tcp
add action=add-src-to-address-list address-list=IPGreenList address-list-timeout=none-dynamic chain=ssh-auth comment="Add to Established list IPGreenList" connection-nat-state="" connection-state=established,related src-address-list=!IPBlackList
add action=add-src-to-address-list address-list=IPGreenList address-list-timeout=none-dynamic chain=winbox-auth comment="Add to Established list IPGreenList" connection-state=established,related src-address-list=!IPBlackList
add action=add-src-to-address-list address-list=IPGreenList address-list-timeout=none-dynamic chain=https-auth comment="Add to Established list IPGreenList" connection-state=established,related src-address-list=!IPBlackList
add action=accept chain=ssh-auth comment="Allow initial connection" connection-state=new src-address-list=IPGreenList
add action=accept chain=winbox-auth comment="Allow initial connection" connection-state=new src-address-list=IPGreenList
add action=accept chain=https-auth comment="Allow initial connection" connection-state=new src-address-list=IPGreenList
add action=add-src-to-address-list address-list=IPBlocked10s address-list-timeout=10s chain=ssh-auth comment="Add to blocked list for 10s" connection-state=new src-address-list=!IPBlackList
add action=add-src-to-address-list address-list=IPBlocked10s address-list-timeout=10s chain=winbox-auth comment="Add to blocked list for 10s" connection-state=new src-address-list=!IPBlackList
add action=add-src-to-address-list address-list=IPBlocked10s address-list-timeout=10s chain=https-auth comment="Add to blocked list for 10s" connection-state=new src-address-list=!IPBlackList
add action=add-src-to-address-list address-list=IPBlocked30s address-list-timeout=30s chain=ssh-auth comment="Add to blocked list for 30s" connection-state=new src-address-list=IPBlocked10s
add action=add-src-to-address-list address-list=IPBlocked30s address-list-timeout=30s chain=winbox-auth comment="Add to blocked list for 30s" connection-state=new src-address-list=IPBlocked10s
add action=add-src-to-address-list address-list=IPBlocked30s address-list-timeout=30s chain=https-auth comment="Add to blocked list for 30s" connection-state=new src-address-list=IPBlocked10s
add action=drop chain=ssh-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked10s
add action=drop chain=winbox-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked10s
add action=drop chain=https-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked10s
add action=add-src-to-address-list address-list=IPBlackList address-list-timeout=none-dynamic chain=ssh-auth comment="Add to blocked list for IPBlackList" connection-state=new src-address-list=IPBlocked30s
add action=add-src-to-address-list address-list=IPBlackList address-list-timeout=none-dynamic chain=winbox-auth comment="Add to blocked list for IPBlackList" connection-state=new src-address-list=IPBlocked30s
add action=add-src-to-address-list address-list=IPBlackList address-list-timeout=none-dynamic chain=https-auth comment="Add to blocked list for IPBlackList" connection-state=new src-address-list=IPBlocked30s
add action=drop chain=ssh-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked30s
add action=drop chain=https-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked30s
add action=drop chain=winbox-auth comment="Drop for failed authentication" connection-state=new src-address-list=IPBlocked30s
add action=drop chain=input comment="Drop for IPBlackList" src-address-list=IPBlackList
/ip firewall nat
add action=masquerade chain=srcnat out-interface-list=WAN
The idea is:
If the client attempts a connection and the authentication is successful on the first attempt, their address is added to IPGreenList.
If the client attempts a connection and authentication fails for the first time, their address is added to IPBlocked10s (blocking any further attempts for 10 seconds).
If the client retries a connection after 10 seconds and authentication fails for the second time, their address is added to IPBlocked30s (blocking any further attempts for 30 seconds).
If the client retries a connection after 30 seconds and authentication fails for the third time, their address is added to IPBlackList (blocking their IP permanently).
Of course, if authentication is successful before three attempts, their IP is validated and added to IPGreenList.
The idea of a firewall is to focus on allowed traffic and simply drop all else.
The only person(s) that need access to the router ( aka the input chain ) is the admin and a source address list works well.
The only viable access method to config the router ( and access all the LANS) is from within the router AFTER accessing it via VPN.
The rest of the users only need access to limited services, normally just DNS and maybe some devices NTP
Access to the router (input) or the LANs (forward) via secure means is best done via VPN, wireguard, l2tp ipsec, openvpn, or zerotier etc… Allowing access to winbox port from the external WANIP directly is plain stupid.
To that end… Get rid of all the excess bloat… /ip firewall filter
{Input Chain}
(default rules to keep) add action=accept chain=input comment=“defconf: accept established,related,untracked” connection-state=established,related,untracked
add action=drop chain=input comment=“defconf: drop invalid” connection-state=invalid
add action=accept chain=input comment=“defconf: accept ICMP” protocol=icmp
add action=accept chain=input comment=“defconf: accept to local loopback (for CAPsMAN)” dst-address=127.0.0.1
( admin rules )
add action=accept chain=input comment=" VPN handshake" ( PUT YOUR SECURE ACCESS PORT/PROTOCOL HERE FOR VPN ) add action=accept chain=input src-address-list=Authorized comment=“Config Access”
add action=accept chain=input comment=“Allow LAN DNS queries-UDP”
dst-port=53 in-interface-list=LAN protocol=udp
add action=accept chain=input comment=“Allow LAN DNS queries - TCP”
dst-port=53 in-interface-list=LAN protocol=tcp
add action=drop chain=input comment=“drop all else”
{forward chain}
(default rules to keep)
_add action=accept chain=forward comment=“defconf: accept in ipsec policy” ipsec-policy=in,ipsec
add action=accept chain=forward comment=“defconf: accept out ipsec policy” ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment=“defconf: fasttrack” connection-state=established,related
add action=accept chain=forward comment=“defconf: accept established,related, untracked” connection-state=established,related,untracked
add action=drop chain=forward comment=“defconf: drop invalid” connection-state=invali_d
( user rules ) add action=accept chain=forward comment=“internet traffic” in-interface-list=LAN out-interface-list=WAN
add action=accept chain=forward comment=“vpn to lan” { PUT YOUR VPN TO LAN RULES HERE }
add action=accept chain=forward comment=“port forwarding” connection-nat-state=dstnat { disable if not required"
add action=drop chain=forward comment=“drop all else”
Unless you have a specific need for SSH, HTTPS etc to the Router itself, drop the idea stick with the VPN method.
With BTH available on ARM devices, wireguard is possible even if
a. you dont have a public IP
b. you cannot forward a port from the ISP router to the MT router.
Ok ANAV,
Thank you for your clear opinion and your argument of stupidity ;
There are indeed several reasons for this request, two of which are :
My learning
The need for simple roaming access via platforms that don’t necessarily allow such VPN or other connections.
Here’s a simple example of what I want to block (photo attached)
And let me just add a comment of my own:
My 17-year-old ZYXELL ZYWALL10s are already capable of doing what you say, the idea is to have active and advanced configuration.
Perhaps solve this issue with a port-knock sequence?
So “client” first needs to hit a certain sequence of UDP/TCP ports before “the gate opens up”
Offcourse then there is still the mandatory authentication, jus make sure you run an up-to-date RouterOS and do NOT use default “admin” usernames etc
Much more simpler, since your original request requires script to run every X time to scan the logs for authentication attempts etc.
There is plenty of postings on this forum on “multi-stage” port-knock sequence.
I’ve used a 3-stage for years, but now I have Wireguard & ZerotTier and only options “to get in”
Do not compare Mikrotik with Zyxell, it is not correct.
In a router, firewall rules have their own order and it is important. The rules are enforced from top to bottom and nothing else. You are wrong! Rules are usually not started with ``Jump’’ but with /Input=allow-established,related…
Anav beautifully described an example of how the sequence of firewall rules looks like and the content of the rules themselves, and if you use such a rule policy, then you will not have log file “red” notifications about someone trying to connect to your ssh, winbox or Telnet, etc.
It looks like you have too many ports open on your router. Blocks the Telnet port so that your router is not hacked from the outside… of course, if it is not necessary for some important task. And as the “good practice” shows, it should be blocked on the RAW chain.
I have nothing against ANAV and I agree with its “fundamental” principle.
As far as my comparison is concerned, my change of choice is proof that MIKROTIK offers dynamic protection possibilities.
Hence my question of the day, without setting up a factory, how can you dynamically blacklist IPs on failed requests?
Mikrotik provides for winbox-auth and other control chains, how can they be implemented?