In short: the psd matcher in the RouterOS firewall recognizes port scans: it adds a weight for each different port that the same address touches in a short time, and when the total reaches the threshold, the rule triggers. Usually, it puts the scanner in an address list, and another rule drops it. Place it below the rules that accept good traffic, and it does not detect slow scans.
What is a port scan, and what does psd do?
A port scan is an address that tries one port after another to discover which services respond. Every public address receives them continuously, from bots and device discovery engines. psd (port scan detection) is the matcher that recognizes them: it looks at TCP and UDP packets arriving from the same host to different destination ports, assigns a weight to each, and sums them up.
The manual describes it as follows: “Attempts to detect TCP and UDP scans”. It counts different ports, not connections: one hundred connections to port 443 count as one port. It only works with IPv4: the matcher is not available in the IPv6 firewall.
What do the four numbers mean?
They are four fields separated by commas: psd=WeightThreshold,DelayThreshold,LowPortWeight,HighPortWeight. From the MikroTik manual: Filter:
- WeightThreshold: the total weight of packets to different ports from the same host beyond which the sequence is considered a scan;
- DelayThreshold: the maximum time between one packet and the next for them to count in the same sequence. If the host waits longer, the new packet does not attach to the previous ones;
- LowPortWeight: the weight of a packet to a privileged port, below 1024 (22, 80, 443…);
- HighPortWeight: the weight of a packet to a port from 1024 and up.
Low ports weigh more because they belong to real services: someone trying them one after another is looking for what is there.
How do I calculate when it triggers?
Multiply the ports by their weight and compare with the threshold. The classic value is psd=21,3s,3,1: threshold 21, maximum 3 seconds between hits, low ports weight 3, high ports weight 1.
- 7 low ports in a row: 7 × 3 = 21, you reach the threshold and the rule triggers (in the lab, it did not trigger with 6 low ports, but it did with 7);
- 21 high ports in a row: 21 × 1 = 21, same result;
- a mix: 4 low ports and 9 high ports make 12 + 9 = 21;
- a burst of port knocking on 3 high ports weighs 3: far from 21.
A real scanner touches hundreds of ports in a few seconds and exceeds the threshold almost immediately. A normal client touches one or two ports and never reaches it.
How do I write it?
With two rules: one that marks the scanner in an address list, one that drops it. The example starts from the input firewall of the Basic Hardening of a MikroTik router, with the interface list WAN and the final rule “IN: everything else”.
/ip firewall filter
add chain=input in-interface-list=WAN protocol=tcp psd=21,3s,3,1 \
action=add-src-to-address-list address-list=port-scanner address-list-timeout=1d \
comment="PSD: annota chi scansiona" place-before=[find comment="IN: tutto il resto"]
add chain=input in-interface-list=WAN src-address-list=port-scanner action=drop \
comment="PSD: scanner fuori" place-before=([find chain=input]->0)
- the first rule is placed at the bottom, right before the final drop: it only sees traffic that no previous rule has accepted;
- the second rule is placed at the top of the
inputchain: anyone on the list is dropped first, even on ports the router normally accepts (such as the VPN); address-list-timeout=1d: after one day, the entry expires automatically. Setting a timeout is important: a false positive does not remain blocked forever;in-interface-list=WAN: the rule only monitors internet traffic. An administrator running a scan from the LAN for work purposes does not lock themselves out.
For UDP scans, add an identical rule with protocol=udp. You can see who is in the list like this:
/ip firewall address-list print where list=port-scanner
/ip firewall filter print stats where comment~"PSD"
Why does it come after the rules that accept good traffic?
Because psd counts all packets that reach it, whether good or bad. Rules are read from top to bottom: a packet accepted by a rule above never reaches the psd rule and does not add weight.
The firewall in the hardening setup above already handles responses to established connections, ping, management WireGuard, and the LAN. Normal traffic stops there. Only what was about to be dropped reaches psd: exactly what you need to inspect.
If you place it at the top, however, it also counts your own services. In the lab, I added a rule with a threshold of 12 above the port knocking rules: a client that, after the correct knock, probed 7 router ports in a row ended up on the blacklist.
⚠️ Warning: the blacklist blocks all traffic from that address to the router. Work in Safe Mode and test the rule from an external address that you do not use to manage the router.
Input, forward or raw: where do I put it?
In input if you want to protect the router itself, which is the most common case: scans on the router’s public address arrive there. psd also exists in the mangle, nat and raw tables, with the same four fields.
- forward: traffic that passes through the router. With
in-interface-list=LANyou can detect a LAN PC scanning the internet or other networks, often an infected PC. Here it is best to only log, without dropping, and review the list; - raw prerouting: the raw table operates before connection tracking. The manual states that filtering in raw “allows saving resources if connection tracking is not required”: this is the right place for the drop rule from list
port-scanner, if there are many scanners.
/ip firewall raw
add chain=prerouting in-interface-list=WAN src-address-list=port-scanner action=drop \
comment="PSD: scanner fuori, prima del conntrack"
What it misses, and who risks getting caught by accident?
It does not detect slow scans. If the time between packets exceeds the DelayThreshold, the packets are not linked into the same sequence and the weight does not increase. A patient scanner, which tries one port every 5 seconds, slips past psd=21,3s,3,1 without being noticed. For that, you need other traps, such as the decoy ports of port knocking.
On the other hand, false positives:
- clients opening many connections to different ports: for example, a monitoring program that checks all router services one by one;
- port knocking: each knock is a packet to a different port, and since the knocks are not accepted, they reach
psd; - apps that check multiple ports: after the initial knock, they check if WinBox, SSH, and other ports respond. These are different ports within a few seconds;
- a shared NAT: behind a single public IP address (a mobile network, a hotspot), there are many users, and for
psdthey count as a single host.
How do psd and port knocking coexist?
Well, if the knocking sequence is short or slow. With psd=21,3s,3,1, a standard knock on 3 high ports weighs 3 and does not trigger anything: in the lab, it never ended up in the list. The problem arises with low thresholds or long sequences of knocks and checks.
The solution is to knock slowly: leave more than the DelayThreshold between each knock. With a 3-second threshold, a knock every 3.5 seconds ensures that each packet starts from zero: in the lab, this way, psd did not trigger. However, remember that the timeout of the knocking address lists must last longer than the wait time: with the 15 seconds from the howto, 3.5 seconds between knocks is perfectly fine.
The complete lock, including the trap for those knocking in the wrong order, is in the howto Port knocking on MikroTik. The escape ports of the trap and psd complement each other: the trap catches those scanning ports sequentially, even slowly, while psd catches those moving fast on any port.
RouterOS port knocking, with its blacklist against scans, is also described in the MikroTik manual: Port knocking.
Tested in the lab on RouterOS 7.24.5 (stable), on input with psd=21,3s,3,1 and TCP scans from a PC: it triggers with 7 low ports, 21 high ports, or 4 low plus 9 high ports; it does not trigger with 6 low or 20 high ports; a scan of 30 ports with 3.5 seconds between each knock passes without being detected; a standard knock on 3 ports does not trigger; with a threshold of 12 above the knocking rules, a client checking 7 ports ends up on the blacklist. UDP, raw, and forward are from the documentation.
Frequently asked questions
What does psd=21,3s,3,1 mean?
Weight threshold of 21, maximum 3 seconds between packets, weight 3 for ports below 1024, and weight 1 for ports 1024 and above. The rule triggers when the same host reaches 21, for example with 7 low ports or 21 high ports in a row.
Where do I place the psd rule in the firewall?
At the bottom of the input chain, immediately before the final drop and below the rules that accept legitimate traffic. The rule dropping the scanner list should instead be at the top, or in raw prerouting to save resources.
Does psd detect slow scans?
No. If more than the DelayThreshold passes between packets, the packets are not linked in the same scan, and the threshold is never reached.
Does port knocking trigger psd?
With psd=21,3s,3,1, a knock on 3 high ports does not: it weighs 3. With low thresholds or checks on many ports, yes. By knocking with more than 3 seconds between each knock, each knock starts from zero, and the rule does not trigger.
Does psd work with IPv6 too?
No, the psd matcher is only available in the IPv4 firewall (/ip firewall).



