Firewall Questions

This is a two part question, maybe I should do different threads but I’ll put them in one for now.

I’ll post my firewall if necessary but maybe we can treat this as more of a general knowledge question. Currently my firewall is basically the MikroTik default rules from an RB3011 plus some additional drop rules from inbound DNS requests and inbound SNMP requests. I’m running a CCR with multi VLANs, basically a small business is run from this router in a residential environment.

First, I have some port forwarding done to access my NAS remotely so some computers can sync in the background as my employees and myself are off site. Twice now my NAS has reported failed login attempts and it has blocked the IP addresses. So, this is good that they are blocked since they were not legitimate logins. My question is would any of the various firewall rules that are floating around for adding addresses to block lists on the router have worked in this case? Presumably, a bot or someone discovered the open port and tried to login so they presumably had one connection through my router and then multiple login attempts to the NAS within a minute triggering the NAS security. Just wondering if I can add rules to my firewall to help negate these types of attacks. I wouldn’t think so since the port is open but I hope I’m wrong.

Second, I’ve read a lot of threads about firewalls and it seems a number of people say the default rules are fine in most cases, others add a lot of rules for automatic blocking of addresses like the rules below. Others say why bother with stuff like this since the default firewall rules drop them anyway. Just looking for feedback if stuff like below could help with my NAS question or if stuff like below is of any value. When I had the rules below as part of my router they blocked a lot of addresses and the address list grew fairly large over time. But was it necessary? Or, do default rules block (drop) this type of traffic anyway.

Note, the below isn’t an entire firewall, just a section of my old rules.

add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="Port scanners to list " \
    protocol=tcp psd=21,3s,3,1
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="NMAP FIN Stealth scan" \
    protocol=tcp tcp-flags=fin,!syn,!rst,!psh,!ack,!urg
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="SYN/FIN scan" protocol=tcp \
    tcp-flags=fin,syn
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="SYN/RST scan" protocol=tcp \
    tcp-flags=syn,rst
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="FIN/PSH/URG scan" protocol=tcp \
    tcp-flags=fin,psh,urg,!syn,!rst,!ack
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="ALL/ALL scan" protocol=tcp \
    tcp-flags=fin,syn,rst,psh,ack,urg
add action=add-src-to-address-list address-list="port scanners" \
    address-list-timeout=2w chain=input comment="NMAP NULL scan" protocol=tcp \
    tcp-flags=!fin,!syn,!rst,!psh,!ack,!urg
add action=drop chain=input comment="dropping port scanners" src-address-list=\
    "port scanners"
add action=add-src-to-address-list address-list=trying_to_rdp \
    address-list-timeout=1d chain=input comment="list IP's who try rdp" \
    dst-port=3389 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" dst-port=20-23 protocol=tcp
add action=drop chain=input comment="Drop ssh brute forcers" 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 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 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 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 dst-port=22 \
    protocol=tcp
add action=accept chain=input comment="allow ssh" disabled=yes dst-port=22 \
    protocol=tcp
add action=drop chain=forward comment="drop ssh brute downstream" dst-port=22 \
    protocol=tcp src-address-list=ssh-blacklist
add action=drop chain=input comment="drop ftp brute forcers" dst-port=21 \
    protocol=tcp src-address-list=ftp_blacklist
add action=accept chain=output content="530 Login incorrect" dst-limit=\
    1/1m,9,dst-address/1m protocol=tcp
add action=add-dst-to-address-list address-list=ftp_blacklist \
    address-list-timeout=3h chain=output content="530 Login incorrect" \
    protocol=tcp
add action=drop chain=input comment=\
    "Drop Input AS it should have been allowed by now"
add action=accept chain=Forward

I’m one of the “don’t bother” people. Default firewall is like this:

/ip firewall filter
add chain=input connection-state=established,related,untracked action=accept
add chain=input connection-state=invalid action=drop
add chain=input protocol=icmp action=accept
add chain=input in-interface-list=!LAN action=drop

In other words, accept replies for connections initiated from router, drop nonsense, accept icmp, drop everything else if it’s not from LAN, and finally allow everything else (which means from LAN, because everything else was dropped by last rule). Nice and simple.

Why should I check for various tcp flags, when they should fall into nonsense category anyway and be dropped by connection-state=invalid rule? I admit that I didn’t do thorough testing of everything there is, just few quick tests with nmap so far. And it works, conntrack sees the attempts as invalid packets.

Adding addresses trying rdp or whatever to list, maybe out of curiosity, otherwise it’s mostly pointless. Or if it would be part of larger project, where you’d have several honeypots and you’d be building a blacklist after some additional evaluation of connecting addresses. But for lone router, you’ll just end up with a long list of random addresses without any real value.

Bruteforcers, it’s another futile adventure. The ftp I see in your rules is completely pointless. There’s exactly zero reasons why to have it on router accessible from internet. Ssh, well that’s a little better. Slightly pointless from security perspective, because any sane person uses keys anyway, so bots trying passwords can keep trying until the world ends. But it’s true that it’s annoying to have logs full of failed login attempts. Problem with blacklisting done using firewall is that it’s not really looking for failed login attempts, only for number of connections (*). Be too fast, connect quickly few times and you’ll get blocked too, even if you’re legitimate user. I currently prefer combination of whitelist and port knocking and random bots don’t get even a single chance to do anything.

(*) Same problem occurs if you’d want to protect device behind router. You don’t see inside packets (unencrypted ftp excluded, but hopefully nobody uses that anymore), so you’re still only counting connections. If the internal service isn’t a public one, better think about using some VPN to access it.

So that was one opinion. I’d be happy to see any counterarguments.

There are two purposes of the dynamic blacklists.

One is to save CPU through minimizing the processing of these packets, i.e. to drop them as early as possible in the firewall, which makes sense when they arrive on a significant rate. However, you cannot expect more than just reducing the CPU load, as if they come with a rate which clogs your uplink, dropping them at your end doesn’t help.

The other one is to add protection to authentication protocols where dictionary attacks or brute forcing the password may succeed and thus these protocols are attractive for the attackers; in this case, limiting the number of available attempts per unit of time reduces the probability that the attacker succeeds in a reasonable time frame. This is commonly known as fail2ban strategy, however it requires an ability to reliably detect a failed attempt from a successful one. For some protocols (like ssh), each failed login attempt means a closure of a TCP session, so you can see that on protocol level by means of the firewall and limit the number of connection attempts per unit of time before placing the source address to a blacklist, but for other protocols this approach is not so straightforward. An example would be IPsec which is UDP based so the attacker may keep using the same source port all the time and the firewall cannot reliably distinguish the initial packet of each connection from a mid-connection one as easily as with TCP. So on end systems (like linux machines or the RouterOS if it is itself the server of the attacked service), the way out is to monitor the log of the attacked service and extract attackers’ IP addresses from login fault messages recorded there; if the RouterOS is in a transit position with regard to the attacker and the target, this method is out of question unless you could e.g. make the target send some specific packets to the address of the attacker which RouterOS firewall can recognize and add their destination addresses to the blacklist.

So for your particular case, it depends on the behaviour of the protocol the NAS uses for remote access whether you can reliably identify a failed login attempt on the RouterOS itself, and if not, whether you can run a script on the NAS which would e.g. ping the attacker’s address by a packet with a specific pattern in it to notify Mikrotik about the attacker’s address.

It is tempting to blacklist anything to which the NAS doesn’t respond within a given amount of time, assuming that it doesn’t respond because it has blacklisted it on its own, but I would deem it dangerous because if the NAS e.g. restarts, anything that attempts to connect to it during the restart would be banned.

While I like Sob’s way I still see a reason to implement black listing in case when there’s a service exposed to internet. If one can construct a list of likely attackers, then one might block access to otherwise exposed service.

Example (not entirely realistic): I’m running a public http and https service (hopefully secure enough on the server itself), ssh from select IP addresses, public SMTP (to receive mails for the domain) … and nothing more. While “Sob’s” drop everything else keeps my ssh safe, it does nothing to prevent attackers to try to compromise SMTP or HTTP services. If I’d create blacklist and add somebody trying to access winbox port (which is closed anyway) or ssh port (not from allowed remote addresses), then I’d block access to SMTP and http services as well …
This example surely only works against port-scanners and does nothing against those that only try to use my SMTP service as relay (I have to extract those from log files and add them to FW blacklist in semi-manual way).

I don’t say that blacklisting is useless, but it depends on where you get the blacklist from and how exactly you use it.

For example, since you mentioned smtp, I do believe in external blacklists. They really help, as long as they reflect current state and they are not the “once you get in, you’re never getting out” type. They work because it’s data from large network of devices and they have many samples to work with. There’s good chance that before first spam hits your server, source address is already listed. If you’d be maintaining such list yourself as small subject with just few servers at most, it would be hard to get anything useful. For every address you add, you get spam from two new ones.

If it’s for failed login attempts, then short-time blacklists are also ok. Trouble is that you really need to be able to tell failed logins from legitimate ones. If you aren’t, then it becomes unreliable. You can set some limits that you think are sane, e.g. you could assume that you won’t ever need to connect to ssh server more than three times in fifteen minutes. And most times it will be true and it will work. Until it one day it won’t and you’ll block yourself. It will be when you least need it, of course. Right place for this is on application level.

RouterOS is theoretically in good position for this. If you have some server and standard services, many are not prepared for it and blocking is usually done by external tools scanning logs, you have to configure it individually for each service, and all in all, it seems to me as too much work for something that should just be there (or maybe I’m too lazy). RouterOS is made by single company as integrated product, so implementing fail2ban functionality for all their services would be easy for them. And not just e.g. WinBox, which is better left hidden from the world (while I still believe that it shouldn’t be necessary, my trust was shaken a little by the recent events), but everything, including VPNs, because in principle, they have the same problem as any other service.

And regarding bots trying to break into multiple services at once, it’s possible, but I don’t know if it’s very common. I’d say no, but I also have to say that I don’t have enough data. I did some logging in the past on a server or two and either they just checked if few common ports are open and didn’t do anything further, or they tried to guess password for one service for a while, until they gave up and didn’t come back.

I’m liking this discussion. Great info. Thanks again.

Good stuff - great read!

Would it not be safest to access the servers/NAS by VPN?
The problem with lists and firewall rules predisposes knowing what the allowable WAN internet IPs will be.
If offsite, who knows what one will be using for a WANIP??

I guess it depends upon the level of security sophistication of the NAS server??

@anav, it is a matter of your security concept. Basically https should be as secure as IPsec if using same encryption algorithms and authentication methods, so if you don’t mind handling encryption of each connection separately, there is no need to use a VPN. And if both ways are equally secure, having any of them open to the whole world should be equally safe or risky. So if we leave aside vulnerabilities of both, it boils down to authentication methods: if you use a login and password, the dynamically created blacklist is a way to make brute-forcing or dictionary attacks to the login and password prohibitely expensive in terms of available attempts per unit of time. If you use a certificate to authenticate not only the server to the client but also vice versa, the attacker would have to forge much more data than what is sufficient for a password. If we do not leave vulnerabilities aside, though, then even a single attempt may be sufficient if a vulnerability allows to bypass authentication, so a dynamic blacklist created locally based on failed attempts is not an efficient defense as there will be no failed attempt at all.

Also worth noting is that neither a certificate is the holy grail - it can get stolen as well by attacking the client. So it is just a matter of how important your data are for the attacker, so how much effort is still worth spending to get hold of them.