To protect a public DNS nameserver from massive DNS requests/attacks I created a rate limit (connlimit) rule a while ago:
root@dns:~# iptables -I INPUT -p tcp --dport 53 -m connlimit --connlimit-above 10 -j REJECT
root@dns:~# iptables -I INPUT -p udp --dport 53 -m connlimit --connlimit-above 10 -j REJECT
This connection limit rule is triggered as soon as a single source is using more than 10 connections. Connections 11 and more are then automatically rejected.
This results in the following rules shown in the INPUT chain:
root@dns:~# iptables -nvL
Chain INPUT (policy ACCEPT 24925 packets, 1951K bytes)
pkts bytes target prot opt in out source destination
122 9068 REJECT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 #conn src/32 > 10 reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 #conn src/32 > 10 reject-with icmp-port-unreachable
[...]
Although this worked (and proofed to be great helper during attacks), this caused issues with internal DNS nameservers which required frequent mass queries for DNS replication. This means: The created rate limit rule needs an exception for a couple of sources.
To create a an exception to a rule the iptables command supports the exclamation mark (!) which can be used in combination with -s (source) or -d (destination). The goal would be to create the same rate limit rule as seen above, however not for requests coming from 192.168.100.53 and 192.168.200.53, hence create an exclusion.
However when using multiple sources (or destinations), the negated rule cannot be created:
root@dns:~# iptables -I INPUT -p tcp --dport 53 ! -s 192.168.100.53,192.168.200.53 -m connlimit --connlimit-above 10 -j REJECT
iptables v1.8.4 (legacy): ! not allowed with multiple source or destination IP addresses
Instead of trying to combine rate limit and exception rule into one, the rule can be split into a REJECT and an ACCEPT rule as a workaround.
First let's create the general rate limit rules which are applied on all sources:
root@dns:~# iptables -A INPUT -p tcp --dport 53 -m connlimit --connlimit-above 10 -j REJECT
root@dns:~# iptables -A INPUT -p udp --dport 53 -m connlimit --connlimit-above 10 -j REJECT
Then create the exception rule (with -j ACCEPT action) with the allowed sources BEFORE the general rate limit rule (using -I INPUT to insert this rule at the top of the INPUT chain):
root@dns:~# iptables -I INPUT -p tcp --dport 53 -s 192.168.100.53,192.168.200.53 -m connlimit --connlimit-above 10 -j ACCEPT
root@dns:~# iptables -I INPUT -p udp --dport 53 -s 192.168.100.53,192.168.200.53 -m connlimit --connlimit-above 10 -j ACCEPT
This results in the following rules in the INPUT chain:
root@dns:~# iptables -nvL
Chain INPUT (policy ACCEPT 120 packets, 11895 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- * * 192.168.200.53 0.0.0.0/0 udp dpt:53 #conn src/32 > 10
0 0 ACCEPT udp -- * * 192.168.100.53 0.0.0.0/0 udp dpt:53 #conn src/32 > 10
0 0 ACCEPT tcp -- * * 192.168.200.53 0.0.0.0/0 tcp dpt:53 #conn src/32 > 10
0 0 ACCEPT tcp -- * * 192.168.100.53 0.0.0.0/0 tcp dpt:53 #conn src/32 > 10
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 #conn src/32 > 10 reject-with icmp-port-unreachable
0 0 REJECT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 #conn src/32 > 10 reject-with icmp-port-unreachable
[...]
With this workaround, the rate limit is in place for all sources except the ones defined in the -j ACCEPT rules.
Note: Another potential workaround would be to use iptables ipset, but I did not follow up on that.
No comments yet.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Database Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Office OpenSearch PGSQL PHP Perl Personal PostgreSQL Postgres PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder