Chains

Your MikroTik router have 3 main chains for rules: Input, Output and Forward.

Packets with a destination ip on the router (see /ip addresses for a list) will be checked with the input chain, so for the router itself or if you have local devices where public IPs are port forwarded to a NATed IP, you need to use the input chain.

The output chain is for packets with a source IP on the router, meaning all packets originating on the router will be checked with the output chain. If you are using the router as DNS server for your local network, it's DNS requests will be using the output chain.

The forward chain is for all packets going through the router - being forwarded to a public IP either inside or outside of the router. In a server environment, the forward chain is therefore what you use the most. In a very basic server environment, on the forward chain you will want to accept ports like 80+443 (web) for everyone, accept 22+3389 (ssh/rdp) for yourself, and drop the rest of the packets.

A MikroTik router processes rules from the top to the bottom and stops processing more rules, whenever it finds a rule that is true for the packet. If it doesn't meet any rules that are true, the packet is accepted, you should therefore end the list with a drop rule with in-interface set to your internet interface. If you forget the in-interface, the drop rule will affect all packets going both in and out, and probably stop a lot of things on your clients from working, as you primarily want only to drop traffic from the outside getting in.

Actions

You will primarily be using two actions. You either accept the packets or you drop the packets. Accept will stop processing any more rules and let the packet through. Drop will also stop processing any more rules, and delete (drop) the packet without letting the sender know that the packet is dropped. You can also reject the packet, that is delete the packet and tell the sender that you deleted it, but by doing that you are really aiding any malicious sender, by letting them know that there is a device here. So it is generally not recommended to reject, just drop it.

Connections: New or established/related?

In your firewall - especially on a core device like your router - you need to minimize the amount of checks, as each check requires precious CPU power. Routers therefore use connection tracking, to check the connection state. For all new connections, we need to check all our rules, to see if we want the connection to go through. But for all subsequent packets in the same connection, we don't need to check them as the connection have already been checked, so for all connections already established (or related, that is ex. an FTP connection opening another data port), we want to accept all the packets.

Therefore it is usually wise to begin your firewall rules with an input/forward accept rule for all connection-state=established/related. As a MikroTik stops processing rules further down the list, whenever a rule is found to be true, you can bypass all subsequent rules and minimize CPU usage for all established/related packets, by putting this rule at the top of your firewall list.

If your router is protecting servers, the established/related rule should be chain=forward. If it is in front of your office or home, it should be chain=input. If there are both clients with local IPs and servers with public IPs behind your router, you need two rules, one with both chains.

Addressing

For your servers inside your network, you will usually be accepting connections depending on their destination addresses, destination ports or combinations. Or you can use destination address lists, to check for a list of different IPs created in /ip firewall address-list.

Jumping chains

To reduce the rules checked per connection, you can save a lot of checks by jumping to different chains. That means Goto, if you ever programmed Basic. If you need to accept different protocols for a specific server, all connections will have to be checked with each rule. But if you instead start by jumping to your own chain, depending on the server IP, you have reduced the check to only one check for all other connections, besides those to the specific server.

If you type your own chain name (instead of input/output/forward) when you create a new filter rule, a new chain will be created. For the next filter rule you create, you will see this new chain available in the chain list.

Document with comments

Firewall rules quickly become complex and you will find it hard to remember their reason. In Winbox use the shortcut Ctrl+M to add comments to every rule you create, so that later, you will be able to remember, why this specific rule exists.

Debugging

If you find parts of your firewall hard to understand, you can add extra accept/drop rules to see if they catch the traffic. Any filter rule you add, will provide a counter showing all traffic they have matched, so adding extra temporary rules, may help you debug and understand your firewall.

Fasttrack

For even higher speed, you can let packets skip parts of the routers internal systems. You do this by adding fasttrack filter rules and mangle rules. It may produce the speed you need, but remember that to obtain the speed it also means that these packets are skipping parts of the router that are often essential (like the firewall), so use fasttrack with caution. Read more about Fasttrack.

Connections and protocols

The two major protocols used are UDP and TCP.

An UDP packet just get sent, and there is no response - therefore there is no connection for UDP, it's just a packet that may or may not be received by the destination, the sender won't know.

TCP works by opening connections. Often you use a hostname, like www.tikdis.com, so first a DNS server is checked to get the IP. With the IP, the TCP/IP connection can be opened.

First the sender starts the 3-way handshake, by sending a A SYN (synchronize) packet. Then the www.tikdis.com server responds with a SYN-ACK (synchronize acknowledgement) packet to acknowledge the SYN packet is received. And finally the sender sends ACK to the server, to acknowledge that a connection is established. Until the connection is established, the router regards the connection as new, so 3 packets are needed to establish a connection. If a user watches a movie at a size of 2 GiB, the server needs to send roughly 1,5 million packets to deliver the full movie. So using established rules, you can save extreme amounts of the routers processing power. Or by creating firewalls without proper established rules, you can quickly overload any router.

Ending a connection properly, means executing a 4-way handshake using FIN and ACK. A MikroTik router will close (tcp-close-wait-timeout) a connection, if there is no response for 10 seconds. This is much faster than the Linux default which is 60 seconds - there is a comparison here.

Connection-state invalid

A MikroTik router considers a connection invalid, if it have not received the proper 3-way handshake. So in most situations, you can and should drop invalid connections, as they are probably an attempt to break into your network. There are however a few situations, where invalid connections are in fact valid.

If you are using BGP or OSPF, you might have internet traffic incoming at one router, and going out on another router if BGP have concluded that this is the shortest path. This will mean that part of the 3-way handshake is on one router, and the other part is on the other router. This is fine and fully acceptable, but this also means that both MikroTik routers will put the connection in connection-state=invalid. Dropping invalid packets in this situation, will create strange scenarios, that will be very hard to debug. So be careful dropping invalid packets, if you are using BGP or OSPF.

Stop brute-force hacking on your entire network

Most admins know, that you should only open ports you need, and drop all other packets. But often there are web applications that you have to leave open to the public, even though you would prefer to lock them down by IP/VPN. In a hosting environment it might be phpMyAdmin and WordPress.

Setting up brute-force prevention on your router, will immensely increase your security. And it may reduce huge amounts of traffic, that may be eating up CPU on you web/database servers, when brute-force attempts are running. Here are some examples of banning a user trying to brute force the router:

Blacklist and ban IP for 3 hours after 10 incorrect FTP logins in a minute on the router

In this example we inspect the content in the package, looking for the the text 530 Login incorrect, that we know our FTP server responds, if the login fails. This requires that the connection is not encrypted, and that we know the response of our server.

Blacklist and ban IP for 1 day after 3 incorrect SSH logins in 3 minutes on the router

This example protects the ssh service on the router. It works by adding the ip to a list, if a connection is not established, because if the packet going through failed to establish a connection, the login attempt must have failed. It is repeated 3 times adding the IP to a new list, to set ban the IP after 3 login attempts.

Blacklist and ban IP for 3 hours after 3 incorrect SSH/RDP logins in 3 minutes at the server network

This is the same as the example above, but we are now checking SSH and RDP (Microsoft remote/terminal service) for brute force attempts for servers inside our network. You can add extra ports, to brute-force protect more services in your network.