Stop abuse clients/IP's

Hi all,

I got from my friend in Leuven some rules top stop abuse of NTP-servers by some bad clients.

First, follow this website and install iptables-persistant:

https://linuxconfig.org/how-to-make-iptables-rules-persistent-after-reboot-on-linux

Then give these commands:

iptables -A INPUT -m state --state NEW -m udp -p udp --dport 123 -m hashlimit --hashlimit-upto 100/second --hashlimit-burst 115 --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name ntp -j ACCEPT

And second:

iptables -A INPUT -m state --state NEW -m udp -p udp --dport 123 -m hashlimit --hashlimit-above 100/second --hashlimit-burst 115 --hashlimit-mode srcip --hashlimit-srcmask 32 --hashlimit-name ntp -j DROP

Then check with iptables -L

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT udp – anywhere anywhere state NEW udp dpt:ntp limit: up to 100/sec burst 115 mode srcip
DROP udp – anywhere anywhere state NEW udp dpt:ntp limit: above 100/sec burst 115 mode srcip

When you run: iptables-save it should stick at every reboot.

I checked with: chronyc -n clients |sort -rn -k 3,3 | head

And the real bad clients seem to have vanished.

Can somebody confirm this? As I do not want to overload my router with firewall-rules. Looks like Linux is better at this. I just want them to go away!

So, please tell me if this works. My friend in Leuven uses this to fight bad clients.

I don’t really understand what this solves that rate limiting in Chrony isn’t already doing? Or is the goal to stick your head in the sand by not seeing them in Chrony, even though they’re still pounding on your router?

2 Likes

Abusers should be dropped, in total, not even reach Chrony at all.

Some still are. But blocking them, will make them go away.

Chrony so far did a poor job at this. It drops, but drops how?

With the firewall dropping the clients see this sever as NOT-THERE and turn to some other server.

Does it work this way? I do not know….just trying to get rid of bad-clients.

Chrony first sends them a KoD packet, telling them to knock it off. Then it stops responding and ignores them for a while, which from the client perspective looks like the server went completely dead. These clients may still show up in Chrony’s stats still, but rest assured, they’re not getting any response or signs of life.

I’d say it’s better to let Chrony handle it. When it sends a KoD packet, any half decent client will heed it and back off. Bad clients that don’t heed it, well, they’re gonna keep hammering you either way, consuming your inbound bandwidth and burdening your router. Blocking them at the router won’t free up any bandwidth, and just means your router will have to do even more processing.

2 Likes

You cannot prevent packets coming to your server. This is out of your control. What these rules do is block/drop packets if a mad-gone client, that ignored KoD, is sending too many of them to your server. From the client’s POV, it’s as if your server is unreachable/not there. Are clients smart enough to notice this and redirect their hunger to some other server? That I do not know.

Some clients I’ve encountered notice, but in response increase the packet rate even further. It can take days for them to eventually go away.

Quite the contrary in my experience. I drop incoming traffic to some of my servers’ addresses for one day a week in iptables to try to encourage people to update their configurations. Here’s the incoming and outgoing traffic for one of those obsolete addresses (131.111.8.171) over the course of a week:

As you can see, dropping the requests causes their volume to increase by a factor of about 7.

1 Like

For me adding the rules work fine.

The load has dropped in total to normal expected levels.

I did raise the speed to 3mbit from 512kbit, as such the traffic went up. But no massive abuse for long periods of time anymore.

By simply closing the port/dropping packets so they don’t reach Chrony does the trick :ok_hand:

Is that to say your NTP server buckled under the load, but the router’s not even breaking a sweat? I would’ve thought the router was the weak link in the chain, and adding more rules for the router to process means more processing for everything that goes through. Or doesn’t go through, for that matter.

Or is it more for aesthetic purposes, to clean up the graph?

3 Likes

Yeah, these are broken NTP clients. Still, they are unwanted for me so I drop them. My rules are on the server itself. The router’s firewall only has the ports 123(udp) and 4460(tcp) open. The server’s FW drops them. I lowered the setting from 100 to 50 packets/s and while I can see more is dropped, I do not have clients that increase their rate when you drop them, else I’d see that in the amount of packets dropped in the FW which will also increase by a lot.

Let me try to explain.

The router does crack under load. I did use Chrone Ratelimit, but it kept responding.

DROPPING traffic made Chrony invisible for requests…this makes the difference as the abusers go away. Don’t know why but they do.

Chrony kept responding = being there!

Dropping = NOT THERE, no response at all.

So yes, it makes a difference. And it does not matter where the rules are set, router OR server.

The solution is simple, Chrony (or NTPD) should STOP being there for abuse IP’s.

As that is what these rules do, and in time the abusers move away….but not when there keeps being a response.

This is my observation….I may be wrong. However, I see it’s working, requests go down a lot and fast too.

In my opinion Chrony should log IP’s that abuse and ignore requests in total. It doesn’t seem to do that. Again, I could be wrong.

From my understanding, that’s precisely what it’s supposed to do. That is, aside from a small “leak” to prevent bad clients from doubling down by increasing the rate of their requests when they get no response.

But, it would be interesting to see some numbers from your router’s perspective. Since Chrony no longer sees this traffic, have they actually gone away, or are you merely putting your head in the sand while the problem persists? It should be possible to enable logging for specific firewall rules. Or does something like tcpdump have the ability to measure packets per second maybe?

1 Like

Yes they are gone. As the firewall blocks them from reaching Chrony.

root@server:~# chronyc -n clients |sort -rn -k 3,3 |head
91.183.19.198                 108     49   1  -1    51       0      0   -     -
81.242.169.163                 60     30   0   0    11       0      0   -     -
78.29.204.106                  41     15   3   3    41       0      0   -     -
81.82.240.61                   35     10   2   2    43       0      0   -     -
20.238.54.206                  21      7   1   2     5       0      0   -     -
84.199.114.106                 17      5  -4   3     3       0      0   -     -
78.20.251.118                  14      5   0  -1    32       0      0   -     -
78.23.178.98                   15      3   1   3     7       0      0   -     -
178.116.206.174                16      3   0   5     7       0      0   -     -
81.241.201.57                  11      2   1   1    10       0      0   -     -
root@server:~# chronyc -n clients |sort -rn -k 3,3 |head
81.242.169.163                 60     30   0   0    25       0      0   -     -
78.29.204.106                  41     15   3   3    56       0      0   -     -
81.82.240.61                   35     10   2   2    58       0      0   -     -
20.238.54.206                  22      7   1   3     2       0      0   -     -
84.199.114.106                 17      5  -4   3    18       0      0   -     -
78.20.251.118                  14      5   0  -1    46       0      0   -     -
81.241.201.57                  17      4   1   1     1       0      0   -     -
78.23.178.98                   15      3   1   3    21       0      0   -     -
178.116.206.174                16      3   0   5    21       0      0   -     -
109.133.13.8                   12      3  -4   3     5       0      0   -     -

That is all there is left. They are dropped. But I had massive numbers before.

See 91.183.19.198 is gone….

My point is, are they still trying, even thought they’re not reaching Chrony? Because if so, your router still has to deal with them.

It might be cheaper for your router to simply pass everything through, since many routers have hardware acceleration for forwarding traffic, bypassing the CPU. Once firewall rules are introduced, the CPU gets involved, and every single packet arriving has to be compared to every firewall rule. Your server may have less of a challenge filtering this traffic.

So again, it would be interesting to see some numbers from the router, rather than Chrony.

2 Likes

Maybe good to add that at least in the case of NTPd:

  • When a client connects (requests time) from the server it’s IP is written to a list (the MRU list);
  • Ratelimit is applied to clients in this MRU list who exceed the ratelimit settings as defined in discard…

The thing is, historically the default size of the MRU list has been only 600 IPs.
As you can imagine, this is woefully inadequate for busy servers that serve millions of clients…

I know that @davehart has proposed (a long time ago) to increase MRU list to 32,000 entries for such busy servers. Please see the following link if you want to know more.

@Bas I can imagine that having too few entries in the list does not really help identifying/tracking all abusive clients. This is also valid for chrony, which has a similar option: “clientloglimit”.
Default chrony setting for clientloglimit is 4096 IPs. Maximum setting is 16.7 million IPs. Beware that this maximum setting consumes 2GB of RAM. Each entry consumes 128 bytes.

1 Like

Interesting!

As I understand the Chrony docs, clientloglimit is set in bytes. So, clientloglimit 33554432 for 32MB. With 128 bytes per client, that’s enough for 262144 clients.

Indeed. chrony does a very good job at keeping the response rates sane, there’s no need to get iptables involved for rate limiting. The “ratelimit” config directive handles chrony’s rate limiting. There are options to tune ratelimit’s behaviour, but the defaults are actually fairly good.

Then there’s the “clientloglimit” directive. I have set it to 268435456 on my servers. That may be considered a fairly large value, but my servers aren’t tight on memory and I don’t mind allocating 256 MB for this purpose. Besides, some of my servers serve 40-50k requests per second at busier periods, so a larger clientloglimit may be useful.

Edit/addendum/note to future self regarding setting clientloglimit to 256M (~2 million IPs): Requests per second may give an indication of how big the clientloglimit should be set to, but ultimately the key is the unique IP addresses served within some specific time period. I captured 10 minutes of traffic on my two busiest servers and checked how long it takes to reach 2M unique IP addresses. The server that serves the China zone took about 4 minutes to reach 2M unique IP addresses at 33290 qps. It appears that 10 minutes was a slightly too short measuring period for my server that serves the Singapore zone, because within 10 minutes I accumulated only 1946861 unique IP addresses at 25672 qps. Traffic on both of those servers was a little bit quieter today than usually. All in all, the 256M clientloglimit does not seem particularly excessive in my case, but if you’re not doing 10k+ qps a smaller clientloglimit will likely suffice. YMMV, do your own measurements.

2 Likes

Rookie numbers :joy:

root@www:~# chronyc -n clients |sort -rn -k 3,3 |head
141.0.108.160               87022  54906  -2  -3     0       0      0   -     -
195.1.130.116               66603  49559  -4  -4     0       0      0   -     -
79.160.177.178             110373  45215  -2  -2     0       0      0   -     -
94.143.68.147               90505  35986  -3  -3     0       0      0   -     -
46.36.76.163                40781  30562  -5  -5  201m       0      0   -     -
82.147.39.130              593866  28129  -4  -3     0       0      0   -     -
37.253.224.174              48254  27098  -4  -4     0       0      0   -     -
188.69.236.155              36214  26977  -5  -5  406m       0      0   -     -
193.69.145.98               30039  21893   4  -5    75       0      0   -     -
185.179.30.128              39667  21397   3   5   685       0      0   -     -

But this is after using iptables to solve it.
I did use ratelimit before.

My output looks like this, using chrony with “ratelimit interval 4” and “clientloglimit 268435456”.
Pretty ok, i think. No obvious big offenders.

Host Pcks Recvd Pcks Dropd Int Last 2 Pcks Int Last 2 Packets (Sec) Last Pck Recvd
2a02:a44e:9933:0:fe2d:705f:5259:90f9 3342 1851 1 3 130m
2a02:2788:84:297:c85:fa2e:82e8:da85 2713 1510 9 3 44m
2a02:2788:9d5:f1fc:5069:573d:1ad3:1e1 3620 907 2 5 13
2a02:1811:3413:5500:993d:4947:6adb:a4fe 3479 902 3 5 12
2a02:a03f:c7bb:f100:256f:5b2e:13fe:7703 3557 878 2 4 50m
2a02:a03f:80bb:800:49ec:ce14:4277:5229 3622 869 2 6 4
2a02:a03f:c5fe:8d01:821:cf0c:c5b:ec23 3585 866 4 4 3
2a02:a03f:8d84:bf01:1958:2a11:1f57:996c 3536 855 2 6 216
2a02:1811:3510:2500:fcdd:304:88d8:f9c5 3121 842 2 6 145m
2a02:a03f:6afa:2a00:a989:7bdc:7684:65ce 3565 837 2 5 4