User Tools

Site Tools


networking:router:mikrotik_fw

Mikrotik RouterOS Firewall

Denial of Service

Port Scanners

View and Modify Blacklists

To view the contents of your Blacklists (created below):

/ip firewall address-list print

Remove a blacklisted IP:

/ip firewall address-list remove numbers=<number_from_list>

Destination NAT (Port Forwarding) Examples

:!: Destination NAT is often called Port Forwarding.

:!: With Mikrotik RouterOS, you do not add an explicit accept firewall rule for forwarded ports as accept is implied.

/ip firewall nat

add action=dst-nat chain=dstnat comment="Forward RDP to Terminal Server" dst-address=123.167.188.34 \
   dst-port=3389 in-interface=ether1 protocol=tcp to-addresses=192.168.0.2

add action=dst-nat chain=dstnat comment="Forward Ports to PBX" dst-address=123.167.188.34 \
   dst-port=5060,10000-20000 in-interface=ether1 protocol=udp src-address-list=vitelity to-addresses=10.10.1.110

add action=dst-nat chain=dstnat comment="Forward Ports to Mail Server" dst-address=123.167.188.35 \
   dst-port=25,465,993,995 in-interface=ether1 protocol=tcp to-addresses=192.168.52.2

Source NAT Examples

http://forum.mikrotik.com/viewtopic.php?f=2&t=11368

Normal masquerade source NAT uses the address of the outbound interface as the external IP:

/ip firewall nat
add action=masquerade chain=srcnat comment="Masquerade (NAT) - Last NAT Rule" out-interface=ether1

Source NAT example with specific external (usually public) IP address:

/ip firewall nat

add action=src-nat chain=srcnat comment="Source NAT with specific public IP x.x.x.x" out-interface=ether1 \
src-address=192.168.1.0/24 to-addresses=x.x.x.x

NAT Bypass

This issue comes up when dealing with VPNs, but I suspect it is also pertinent to discussions of a DMZ.

Here, we bypass NAT in order to route a public subnet out an interface that masquerades all outgoing traffic:

/ip firewall nat add chain=srcnat action=accept comment="NAT Bypass for VPN" place-before=0 \
  src-address=$PublicSubnet

Basic Firewall

FIXME This basic firewall script needs modernization, probably based on the newer default Mikrotik firewall.

Firewall/Router: http://gregsowell.com/?p=4013 Border QoS: http://gregsowell.com/?p=4665

:!: You will want to seriously edit this example to meet your needs.

/ip firewall filter

add action=accept chain=input comment="allow ICMP" disabled=no protocol=icmp

add action=accept chain=input comment="allow winbox" disabled=no dst-port=8291 protocol=tcp

add action=accept chain=input comment="allow api" disabled=no dst-port=8728 protocol=tcp

add action=add-src-to-address-list address-list=trying_to_login address-list-timeout=1d chain=input \
comment="list IP's who try remote login" disabled=no dst-port=20-23 protocol=tcp

add action=drop chain=input comment="drop ssh brute forcers" disabled=no dst-port=22 protocol=tcp \
src-address-list=ssh_blacklist

add action=add-src-to-address-list address-list=ssh_blacklist address-list-timeout=1w3d chain=input \
connection-state=new disabled=no dst-port=22 protocol=tcp src-address-list=ssh_stage3

add action=add-src-to-address-list address-list=ssh_stage3 address-list-timeout=1h chain=input \
connection-state=new disabled=no dst-port=22 protocol=tcp src-address-list=ssh_stage2

add action=add-src-to-address-list address-list=ssh_stage2 address-list-timeout=1h chain=input \
connection-state=new disabled=no dst-port=22 protocol=tcp src-address-list=ssh_stage1

add action=add-src-to-address-list address-list=ssh_stage1 address-list-timeout=1h chain=input \
connection-state=new disabled=no dst-port=22 protocol=tcp

add action=accept chain=input comment="allow ssh" disabled=no dst-port=22 protocol=tcp

add action=accept chain=input comment="accept vpn" disabled=no dst-port=1723 protocol=tcp \
in-interface=ether1-gateway
 
add action=accept chain=input comment="accept vpn gre" disabled=no protocol=gre \
in-interface=ether1-gateway 

add action=drop chain=input comment="drop ftp" disabled=no dst-port=21 protocol=tcp

add action=drop chain=forward comment="drop invalid connections" connection-state=invalid disabled=no

add action=accept chain=forward comment="allow already established connections" disabled=no \
connection-state=established 

add action=accept chain=forward comment="allow related connections" connection-state=related disabled=no

add action=drop chain=input comment="drop Invalid connections" connection-state=invalid disabled=no

add action=accept chain=input comment="allow established connections" connection-state=established disabled=no

add action=accept chain=input comment="acccept lan" disabled=no in-interface=!ether1-gateway \
src-address=192.168.88.0/24

add action=drop chain=input comment="drop everything else" disabled=no

Brute Force Prevention

Country Code

:!: This is probably for more powerful routers with lots of RAM as it could add many rules.

:!: You probably want to put the rules near the top of the list.

Country Code List: https://mikrotikconfig.com/firewall/

  1. Create the script/list of countries to be blocked using the above web site
  2. Copy the IP-Firewall-Address-List.rsc file to the Mikrotik
  3. Import the script
  4. Create a firewall rule referencing the new address list
/import IP-Firewall-Address-List.rsc
/ip firewall filter
add action=drop chain=input comment="Drop traffic by CC - Input chain" in-interface=ether1 log=yes \
    log-prefix="DROP BY CC" src-address-list=CountryIPBlocks
add action=drop chain=forward comment="Drop traffic by CC - Forward chain" in-interface=ether1 log=yes \
    log-prefix="DROP BY CC" src-address-list=CountryIPBlocks

FTP

:!: The block rule must be before rules allowing established connections or it will not function.

:!: This FTP configuration actually looks into the FTP data to see the 530 code.

:!: This appears to be specific to the response of the Mikrotik FTP service (content=) to a failed login attempt and requires the FTP service be enabled to function. If forwarding FTP inward, you might have to change the content= specification.

:!: To have the attacker blocked completely, you can probably just remove the dst-port=21 and the protocol=tcp in the drop rules.

This example allows only 10 FTP login incorrect answers per minute, then bans the attacker (from FTP) for 10 days:

/ip firewall filter

add chain=input protocol=tcp dst-port=21 src-address-list=ftp_blacklist action=drop \
comment="Drop FTP Brute Force Attackers"

add chain=output action=accept protocol=tcp content="530 Login incorrect" dst-limit=1/1m,9,dst-address/1m

add chain=output action=add-dst-to-address-list protocol=tcp content="530 Login incorrect" \
address-list=ftp_blacklist address-list-timeout=10d

If you want to block downstream access as well, you need to also block in the forward chain:

add chain=forward protocol=tcp dst-port=21 src-address-list=ftp_blacklist action=drop \
comment="Drop FTP Brute Force Attackers from Downstream Too"

Then accept new FTP connections not previously blocked:

add chain=input comment="Accept FTP traffic not previously blocked" protocol=tcp dst-port=21 \
connection-state=new action=accept

Telnet

/ip firewall filter

add chain=input comment="Drop Telnet Brute Force Attackers" protocol=tcp dst-port=23 \
src-address-list=telnet_blacklist action=drop disabled=no 

add chain=input protocol=tcp dst-port=23 connection-state=new src-address-list=telnet_stage3 \
action=add-src-to-address-list address-list=telnet_blacklist address-list-timeout=10d  disabled=no

add chain=input protocol=tcp dst-port=23 connection-state=new src-address-list=telnet_stage2 \
action=add-src-to-address-list address-list=telnet_stage3 address-list-timeout=1m disabled=no

add chain=input protocol=tcp dst-port=23 connection-state=new src-address-list=telnet_stage1 \
action=add-src-to-address-list address-list=telnet_stage2 address-list-timeout=1m disabled=no 

add chain=input protocol=tcp dst-port=23 connection-state=new action=add-src-to-address-list \
address-list=telnet_stage1 address-list-timeout=1m  disabled=no

Then allow Telnet connections not previously blocked:

add chain=input comment="Accept Telnet traffic not previously blocked" protocol=tcp dst-port=23 \
connection-state=new action=accept

SSH

Ban SSH attackers for 10 days after three attempts. Change the timeouts as necessary.

/ip firewall filter

add chain=input protocol=tcp dst-port=22 src-address-list=ssh_blacklist action=drop \
comment="Drop SSH Brute Force Attackers" disabled=no

add chain=input protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage3 \
action=add-src-to-address-list address-list=ssh_blacklist address-list-timeout=10d disabled=no

add chain=input protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage2 \
action=add-src-to-address-list address-list=ssh_stage3 address-list-timeout=1m disabled=no

add chain=input protocol=tcp dst-port=22 connection-state=new src-address-list=ssh_stage1 \
action=add-src-to-address-list address-list=ssh_stage2 address-list-timeout=1m disabled=no

add chain=input protocol=tcp dst-port=22 connection-state=new action=add-src-to-address-list \
address-list=ssh_stage1 address-list-timeout=1m disabled=no

If you want to block downstream access as well, you need to block the with the forward chain:

add chain=forward protocol=tcp dst-port=22 src-address-list=ssh_blacklist action=drop \
comment="Drop SSH Brute Force Attackers from Downstream Too" disabled=no

Then allow SSH connections not previously blocked:

add chain=input comment="Accept SSH traffic not previously blocked" protocol=tcp dst-port=22 \
connection-state=new action=accept

Winbox

Ban WinBox attackers for 10 days after three attempts. Change the timeouts as necessary.

/ip firewall filter
     
add chain=input protocol=tcp dst-port=8291 src-address-list=winbox_blacklist \
action=drop comment="Drop WinBox Brute Force Attackers"

add chain=input protocol=tcp dst-port=8291 connection-state=new src-address-list=winbox_stage3 \
action=add-src-to-address-list address-list=winbox_blacklist address-list-timeout=1w3d  
 
add chain=input protocol=tcp dst-port=8291 connection-state=new src-address-list=winbox_stage2 \
action=add-src-to-address-list address-list=winbox_stage3 address-list-timeout=2m  
 
add chain=input protocol=tcp dst-port=8291 connection-state=new src-address-list=winbox_stage1 \
action=add-src-to-address-list address-list=winbox_stage2 address-list-timeout=2m  

add chain=input protocol=tcp dst-port=8291 connection-state=new \
action=add-src-to-address-list address-list=winbox_stage1 address-list-timeout=2m

If you want to block downstream access as well, you need to block the with the forward chain:

add chain=forward protocol=tcp dst-port=8291 src-address-list=winbox_blacklist action=drop \
comment="Drop WinBox Brute Force Attackers from Downstream Too" disabled=no

Then allow Winbox connections not previously blocked:

add chain=input comment="Accept Winbox traffic not previously blocked" protocol=tcp dst-port=8291 \
connection-state=new action=accept

RDP

This configuration counts three attempts within 1 minute to make an RDP connection, then blacklists the attacker for 10 days:

/ip firewall filter

add chain=forward protocol=tcp dst-port=3389 src-address-list=rdp_blacklist action=drop \
comment="Drop RDP Brute Force Attacker" disabled=no

add chain=forward protocol=tcp dst-port=3389 connection-state=new \
src-address-list=rdp_stage3 action=add-src-to-address-list address-list=rdp_blacklist \
address-list-timeout=10d comment="" disabled=no

add chain=forward protocol=tcp dst-port=3389 connection-state=new \
src-address-list=rdp_stage2 action=add-src-to-address-list address-list=rdp_stage3 \
address-list-timeout=1m comment="" disabled=no

add chain=forward protocol=tcp dst-port=3389 connection-state=new \
src-address-list=rdp_stage1 action=add-src-to-address-list address-list=rdp_stage2 \
address-list-timeout=1m comment="" disabled=no

add chain=forward protocol=tcp dst-port=3389 connection-state=new \
action=add-src-to-address-list address-list=rdp_stage1 \
address-list-timeout=1m comment="" disabled=no

Then allow RDP connections not previously blocked:

add chain=input comment="Accept RDP traffic not previously blocked" protocol=tcp dst-port=3389 \
connection-state=new action=accept

What this configuration actually does, is for each incoming attempt it adds the IP address to a list. The first time it gets added to rdp_stage1, then if the IP is still in rdp_stage1 (within a minute) and another attempt is made, it gets added to rdp_stage2, and after it does this two more times it is added to the rdp_blacklist list where it actually gets blocked for 10 days.

:!: If you want it to be more or less aggressive you can change the list timeouts, or even add more lists if you so desire.

Whitelist

You can add a list of these to allow specific IP ranges only:

add chain=forward dst-port=3389 src-address=192.168.0.0/24 action=accept
add chain=forward dst-port=3389 src-address=10.10.1.1/32 action=accept
add chain=forward dst-port=3389 action=drop

Just add as many of the src-address lines you need ahead of the final drop line. If you have a LOT of ranges, you can create an address-list and reference that using this:

add chain=forward dst-port=3389 src-address-list=rdp_acceptlist action=accept
add chain=forward dst-port=3389 action=drop

then add your addresses to the rdp_acceptlist.

To add to the rdp_acceptlist, use the following command:

/ip firewall address-list add list=rdp_acceptlist address=192.168.0.0/24

Protect Local Networks

You can protect local networks from being blacklisted by doing something like this:

  1. Define an address list called local and add your local or protected networks to it
  2. Modify the 'stage1' rules so that they only work on addresses not in the 'local address list
/ip firewall address-list

add address=192.168.0.0/24 comment="Office LAN" list=local
add address=10.10.10.0/24 comment="Management Network" list=local
add address=10.10.5.0/24 comment="Wireless Network" list=local

Here is an example (Winbox) 'stage1' rule modified to exclude local networks:

/ip firewall filter

add action=add-src-to-address-list address-list=winbox_stage1 address-list-timeout=2m chain=input \
connection-state=new dst-port=8291 protocol=tcp src-address-list=!local

IPSec

http://forum.mikrotik.com/viewtopic.php?f=2&t=79151

http://superuser.com/questions/679236/mikrotik-firewall-rule-block-all-connection-except-to-vpn-server

:!: IPSec traffic is not identifiable in FW rules. All traffic will appear to come from the WAN (interface the IPSec tunnel is terminated on) and thus, you can't filter specifically on the IPSec traffic.

L2TP/IPSec uses:

  • TCP port 1701
    • L2TP
  • UDP port 500
    • Internet Security Association and Key Management Protocol (ISAKMP)
    • To negotiate security method (password, certificate, kerberos)
  • AH (Protocol ID 50)
    • Authentication Header
  • ESP (Protocol ID 51)
    • Encapsulated Secure Payload
  • UDP Port 4500
    • NAT Traversal (NAT-T)

Accept L2TP/IPSec connection traffic:

:!: These rules could be further limited by interface and/or source address.

/ip firewall filter
  add chain=input action=accept in-interface=ether1 protocol=tcp dst-port=1701 \
    place-before=0 comment="Accept L2TP"
  add chain=input action=accept in-interface=ether1 protocol=udp dst-port=500 \
    place-before=0 comment="Accept IPSec (ISAKMP)"
  add chain=input action=accept in-interface=ether1 protocol=ipsec-esp \
    place-before=0 comment="Accept IPSec (ESP)"
  add chain=input action=accept in-interface=ether1 protocol=ipsec-ah \
    place-before=0 comment="Accept IPSec (AH)"
networking/router/mikrotik_fw.txt · Last modified: 2022/07/22 10:06 by gcooper