MikroTik: Setup Brute Force Protection

The following firewall rules will block port scanners and brute force login attempts for SSH, Telnet, and Winbox by creating a dynamically generated MikroTik address list for each respective protocol/port. Furthermore, each of the SSH, Telnet, and Winbox rules function by staging four address lists together in sequence, each consisting of a Stage1, Stage2, Stage3, and a Black List address list that work in tandem via MikroTik “Jump” chains. For example, a new SSH connection (port 22) to the Mikrotik would be handled in the following order:

  • A new SSH connection hits the dynamic black list, Black List (SSH). The connection’s IP is not found in the black list and is passed to the next rule – a jump rule. However, if the IP were found, the connection would have been dropped.
  • The jump rule sends the data down the chain “Black List (SSH) chain” where the connection’s IP is checked by each of the staged rules/address lists.
  • The connection is checked against the dynamically created address list “Black List (SSH) Stage 3”. The connection’s IP is not found in the address list and is passed to the next rule. However, if the IP were found, the IP would have been added to “Black List (SSH)” for thirty days.
  • The connection is checked against the dynamically created address list “Black List (SSH) Stage 2”. The connection’s IP is not found in the address list and is passed to the next rule. However, if the IP were found, the IP would have been added to “Black List (SSH) Stage 3” for one minute.
  • The connection is checked against the dynamically created address list “Black List (SSH) Stage 1”. The connection’s IP is not found in the address list and is passed to the next rule. However, if the IP were found, the IP would have been added to “Black List (SSH) Stage 2” for one minute.
  • The connection is is added to dynamically created address list “Black List (SSH) Stage 1” for one minute.

SSH Brute Force Protection

#Create SSH Black List
/ip firewall address-list
add list="Black List (SSH)" comment="Black List (SSH)"

#SSH Brute Force Protection Rules
/ip firewall filter
add action=drop chain=input in-interface=ether1 comment="Drop anyone in Black List (SSH)." log=yes log-prefix="BL_Black List (SSH)" src-address-list="Black List (SSH)"
add action=jump chain=input in-interface=ether1 comment="Jump to Black List (SSH) chain." dst-port=22 jump-target="Black List (SSH) Chain" protocol=tcp
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (SSH)" address-list-timeout=4w2d chain="Black List (SSH) Chain" comment="Transfer repeated attempts from Black List (SSH) Stage 3 to Black List (SSH)." connection-state=new log=yes log-prefix="Add_Black List (SSH)" src-address-list="Black List (SSH) Stage 3"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (SSH) Stage 3" address-list-timeout=1m chain="Black List (SSH) Chain" comment="Add successive attempts to Black List (SSH) Stage 3." connection-state=new log=yes log-prefix="Add_Black List (SSH) S3" src-address-list="Black List (SSH) Stage 2"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (SSH) Stage 2" address-list-timeout=1m chain="Black List (SSH) Chain" comment="Add successive attempts to Black List (SSH) Stage 2." connection-state=new log=yes log-prefix="Add_Black List (SSH) S2" src-address-list="Black List (SSH) Stage 1"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (SSH) Stage 1" address-list-timeout=1m chain="Black List (SSH) Chain" comment="Add initial attempt to Black List (SSH) Stage 1." connection-state=new log=yes log-prefix="Add_Black List (SSH) S1"
add action=return chain="Black List (SSH) Chain" comment="Return From Black List (SSH) chain."

Telnet Brute Force Protection

#Create Telnet Black List
/ip firewall address-list
add list="Black List (Telnet)" comment="Black List (Telnet)"

#Telnet Brute Force Protection Rules
/ip firewall filter
add action=drop chain=input in-interface=ether1 comment="Drop anyone in Black List (Telnet)." log=yes log-prefix="BL_Black List (Telnet)" src-address-list="Black List (Telnet)"
add action=jump chain=input in-interface=ether1 comment="Jump to Black List (Telnet) chain." dst-port=23 jump-target="Black List (Telnet) Chain" protocol=tcp
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Telnet)" address-list-timeout=4w2d chain="Black List (Telnet) Chain" comment="Transfer repeated attempts from Black List (Telnet) Stage 3 to Black List (Telnet)." connection-state=new log=yes log-prefix="Add_Black List (Telnet)" src-address-list="Black List (Telnet) Stage 3"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Telnet) Stage 3" address-list-timeout=1m chain="Black List (Telnet) Chain" comment="Add successive attempts to Black List (Telnet) Stage 3." connection-state=new log=yes log-prefix="Add_Black List (Telnet) S3" src-address-list="Black List (Telnet) Stage 2"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Telnet) Stage 2" address-list-timeout=1m chain="Black List (Telnet) Chain" comment="Add successive attempts to Black List (Telnet) Stage 2." connection-state=new log=yes log-prefix="Add_Black List (Telnet) S2" src-address-list="Black List (Telnet) Stage 1"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Telnet) Stage 1" address-list-timeout=1m chain="Black List (Telnet) Chain" comment="Add initial attempt to Black List (Telnet) Stage 1." connection-state=new log=yes log-prefix="Add_Black List (Telnet) S1"
add action=return chain="Black List (Telnet) Chain" comment="Return From Black List (Telnet) chain."

Winbox Brute Force Protection

#Create Winbox Black List
/ip firewall address-list
add list="Black List (Winbox)" comment="Black List (Winbox)"

#Winbox Brute Force Protection Rules
/ip firewall filter
add action=drop chain=input in-interface=ether1 comment="Drop anyone in Black List (Winbox)." log=yes log-prefix="BL_Black List (Winbox)" src-address-list="Black List (Winbox)"
add action=jump chain=input in-interface=ether1 comment="Jump to Black List (Winbox) chain." dst-port=8291 jump-target="Black List (Winbox) Chain" protocol=tcp
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Winbox)" address-list-timeout=4w2d chain="Black List (Winbox) Chain" comment="Transfer repeated attempts from Black List (Winbox) Stage 3 to Black List (Winbox)." connection-state=new log=yes log-prefix="Add_Black List (Winbox)" src-address-list="Black List (Winbox) Stage 3"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Winbox) Stage 3" address-list-timeout=1m chain="Black List (Winbox) Chain" comment="Add succesive attempts to Black List (Winbox) Stage 3." connection-state=new log=yes log-prefix="Add_Black List (Winbox) S3" src-address-list="Black List (Winbox) Stage 2"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Winbox) Stage 2" address-list-timeout=1m chain="Black List (Winbox) Chain" comment="Add succesive attempts to Black List (Winbox) Stage 2." connection-state=new log=yes log-prefix="Add_Black List (Winbox) S2" src-address-list="Black List (Winbox) Stage 1"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Winbox) Stage 1" address-list-timeout=1m chain="Black List (Winbox) Chain" comment="Add initial attempt to Black List (Winbox) Stage 1." connection-state=new log=yes log-prefix="Add_Black List (Winbox) S1"
add action=return chain="Black List (Winbox) Chain" comment="Return From Black List (Winbox) chain."

Port Scanner (WAN/LAN) Brute Force Protection

#Create Port Scanner (WAN) Black List
/ip firewall address-list
add list="Black List (Port Scanner WAN)" comment="Black List (Port Scanner WAN)"

#Port Scanner (WAN) Protection Rules
/ip firewall filter
add action=drop chain=input in-interface=ether1 comment="Drop anyone in the Port Scanner (WAN) list." log=yes log-prefix="BL_Black List (Port Scanner WAN)" src-address-list="Black List (Port Scanner WAN)"
add action=drop chain=forward in-interface=ether1 comment="Drop anyone in the Port Scanner (WAN) list." log=yes log-prefix="BL_Black List (Port Scanner WAN)" src-address-list="Black List (Port Scanner WAN)"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Port Scanner WAN)" address-list-timeout=4w2d chain=input comment="Add TCP port scanner to Port Scanner (WAN) list." log=yes log-prefix="Add_Black List (Port Scanner WAN)" protocol=tcp psd=21,3s,3,1

#Create Port Scanner (LAN) Black List
/ip firewall address-list
add list="Black List (Port Scanner LAN)" comment="Black List (Port Scanner LAN)"

#Port Scanner (LAN) Protection Rules
/ip firewall filter
add action=drop chain=input in-interface=ether1 comment="Drop anyone in the Port Scanner (LAN) list." log=yes log-prefix="BL_Black List (Port Scanner LAN)" src-address-list="Black List (Port Scanner LAN)"
add action=drop chain=forward in-interface=ether1 comment="Drop anyone in the Port Scanner (LAN) list." log=yes log-prefix="BL_Black List (Port Scanner LAN)" src-address-list="Black List (Port Scanner LAN)"
add in-interface=ether1 action=add-src-to-address-list address-list="Black List (Port Scanner LAN)" address-list-timeout=4w2d chain=forward comment="Add TCP port scanner to Port Scanner (LAN) list." log=yes log-prefix="Add_Black List (Port Scanner LAN)" protocol=tcp psd=21,3s,3,1

6 thoughts on “MikroTik: Setup Brute Force Protection”

  1. Hi – Thank you for this. You have a small error in the winbox section. You have a “_” and need a “-” log prefix. See below =
    (Winbox).” connection-state=new log=yes log_prefix=”Add_Black List (Winbox)”

    Also – I am wondering about the port scanner rules WAN vs LAN. Is in-interface=ether 1 necessary for the WAN side? Would the LAN still be that in-interface? I am struggling to understand how these work.

    Thanks for any info – and nice job again.

    1. Hello Tom,

      Thank you for finding the error, much appreciated. I’ve made the corrections as suggested.

      For my particular setup, my WAN/Internet traffic from the modem is connected to interface1 on my MikroTik. With these particular rules I only want to block scanning coming from the WAN port. So any traffic coming in on interface1 (Internet) will be checked by these rules. Also I’m not sure how familiar you are with input vs forward rules. Input rules include anything going to the router from WAN and LAN, specifying the interface for an input rule will help reduce CPU usage and also tell the router from which source you want to block the traffic. Forward rules include anything going “through” the router and not “to” the router. Hope this answers your questions and again, thanks for pointing out the mistake in the script!

      Regards,
      Marthur

  2. Hi Marthur,

    You are most welcome and thank you for putting this together for everyone’s benefit.

    Thank for your your explanation very helpful. I have a couple of other quick related questions that apply:
    1) Is the purpose of adding the named empty address list is for accounting purposes?

    2) Could you just add 22, 23 & 8291 on one main rule and only have one master blacklist jumpchain that creates one master blacklist of burteforcers? I assume you are doing this to see the attempts by stages by port in the logs. Do you think think this will lead through large log files that are more difficult to manage? I am just thinking about logging on the rule that actually adds it to the blacklist. I think, perhaps incorrectly, that if you log a the time it is actually put on the blacklist it will include what port. I could be wrong.

    3) I am still confused by – #Port Scanner (LAN) Protection Rules. You have in-interface as ether1 which is you internet gateway. Wouldn’t the LAN scanning come in via an interface other than your ether1 gateway as listed in the last line? It would seem that it should the LAN either by in-interface or address-list? Now that I think about it, would you ever have something in the forward chain that is coming into ether1?

    Further – perhaps once they are on the list from either the add-address list from either WAN or LAN you don’t need to specify it in the drop rules.

    Thanks again for all your help. I am still learning firewall design and appreciate your time.

    1. Tom,

      Apologies for the late reply.

      1) Yes, the empty address list is for accounting purposes. Good observation!

      2) Yes, but you lose granularity/control. I like to have separate logs for each rule so I can monitor them at times and filter them by port/service. I have my MikroTik setup to log to an external source. For example, I have lots just for scripts that I run, once the log for the scripts gets to a certain size, the older data is overwritten so the log files always rotate out.

      3) Your the first to point this one out. I actually have those rules disabled at the moment. They were originally there for any traffic that is destination NAT’d or port forwarded, which was coming through the WAN interface. Also, any connection that establishes a connection across the WAN would apply as well. For instance, and this is why I ended up turning it off, is that when connecting to various FTP servers, the servers would establish connection to my client on the LAN using multiple ports. This triggered the Port Scanner (LAN) Protection Rules and blocked the FTP server (Doh!). Using Ether1-WAN as the outbound interface instead of the inbound would have done the same thing, but would make more sense in this case. I understand what you’re saying though.

      I’ve been really busy with work as of late, but in the near future I plan on posting a PowerShell script that I wrote that converts domain block lists (http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt) into MikroTik Address List. I currently use it for country, malicious, spam, ad blocking. I just need to find the time to create the instructions and publish them here.

  3. Very nice, and Thank you!

    I have a couple questions about some of the comments and about the rules. When I use “in-interface=ether1” I get an error “ambiguous value of interface, more than one possible value matches input”. But I only have one ether 1. This is on a 2311 and a 3011. Two different boxes at two different places. One with fiber coming in, another is a wireless link. I’ve poked around for a while and can’t sort out why I’m getting this error. Then I began to wonder, is this actually necessary?

    I’ve been lookthing through similar rules in the tik help files and they don’t specify an interface.

    Regarding the rules being separate vs packed together, you may know better than I do but it seems to me that it really doesn’t matter if you pack them together or separate them. Either way, a rule is a rule and has to be processed. If they’re rolled together would they still not have to be processed for each port as a separate process?

    Finally one last question….what is the purpose of a LAN brute force rule? Do you have people inside the network trying to hack your router? Or am I missing something obvious? 🙂
    Thanks again!

    1. I like to specify the interface so that the rule doesn’t get checked on every interface on the router. Also make sure to check the interface name, my interface was renamed from “ether1” to another naming convention I use here in my homelab. In addition, you can group the ports into a single rule if you’d like. I keep mine separate for logging purposes only, it just my personal preference. As for the LAN rule rules, I don’t have these rules blocking anything, but I do have them logging for the purpose of identifying devices that may be port scanning without my knowledge. Hope this info helps – take care!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top