====== Mikrotik RouterOS Firewall ====== ===== Denial of Service ===== http://wiki.mikrotik.com/wiki/DoS_attack_protection ===== Port Scanners ===== http://wiki.mikrotik.com/wiki/Drop_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= ===== 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 ===== http://wiki.mikrotik.com/wiki/Bruteforce_login_prevention http://mikrotik.romelsan.com/home/bruteforce-protection http://wiki.mikrotik.com/wiki/Port_Knocking ==== 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/ - **Create the script/list** of countries to be blocked using the above web site - **Copy the ''IP-Firewall-Address-List.rsc'' file** to the Mikrotik - **Import the script** - **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: - Define an address list called ''local'' and add your local or protected networks to it - 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)"