How can I drop the first SYN packet (or the first SYN/ACK reply) received by my server?
I have a test VPS set up to capture and analyze malicious traffic directed to non-standard TCP ports, for example attacks on sshd running on a high port. Using BGP, an IPv4 /23 is routed to the VPS. With the nftables rules below, connection attempts to any port 20000-60000 are redirected to SSHD.
flush ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
tcp dport 20000-60000 counter redirect to 22
}
chain postrouting {
type nat hook postrouting priority 100;
}
}
table filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
This works and results in ~20,000,000 address/port combinations that will connect to sshd.
The problem is that I'm only interested in attacks that retransmit an unanswered SYN (the vast majority probe with only one SYN, as scanning all ports on all IPv4 addresses is quite expensive). I've tried various methods, based on conntrack state, packet count and even expiration, all to no avail. I suspect that they are somehow interacting with the redirect.
For example, adding this to the output chain:
tcp sport 22 ct expiration > 55 counter drop
causes all SYN packets to be dropped. Using 'conntrack -E', you can see the expiration timer going down with each subsequent SYN, but when it gets below 55, the packets keep getting dropped.
Environment: Debian bullseye, kernel 5.10.0, nftables v0.9.8, conntrack v1.4.6.
What am I doing wrong? TIA for any suggestions.