Il numero massimo di connessioni che il kernel riesce a gestire è stabilito da /proc/sys/net/ipv4/ip_conntrack_max
, lo stato attuale delle connessioni riconosciute è invece in
/proc/net/ip_conntrack
.
Vedere questo articolo sul Connection tracking prelevato qui.
Con il tool conntrack
(installato dall'omonimo pacchetto) è possibile vedere le connessioni in essere e manipolarle. Tanto per iniziare si possono vedere e rimuoverle tutte:
conntrack -L conntrack -F
Scenario: an iptables firewall forwards connections from the internet to a local server through a DNAT rule. Hosts on the local LAN want to connect to the local server through its public IP address.
# This is the DNAT rule for internet requests: iptables -t nat -I PREROUTING -d 82.189.151.152 -p tcp --dport 80 -j DNAT --to-dest 192.168.1.32 # This is for the firewall itself: iptables -t nat -I OUTPUT -d 82.189.151.152 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.32:80 # This is for the hosts on the local LAN: iptables -t nat -I PREROUTING -d 82.189.151.152 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.32:80 iptables -t nat -I POSTROUTING -o eth0 -s 192.168.1.0/24 -d 192.168.1.32 -j MASQUERADE iptables -I FORWARD -i eth0 -o eth0 -d 192.168.1.32 -j ACCEPT iptables -I FORWARD -i eth0 -o eth0 -s 192.168.1.32 -j ACCEPT
A web server is reachable from the internet onto a local host (192.168.1.5) via a DNAT rule, local hosts want to use the public address (130.151.100.69) to reach the d-natted server. Traffic will be masqueraded by the firewall with its address (192.168.1.254) on the local LAN (eth0, 192.168.1.0/24):
In /etc/shorewall/interfaces:
#ZONE INTERFACE OPTIONS loc eth0 routeback
For Shorewall 5 we nedd a line in /etc/shorewall/snat:
#ACTION SOURCE DEST PROTO PORT SNAT(192.168.1.254) 192.168.1.0/24 eth0:192.168.1.5 tcp www
Shorewall 4 instead requires a line in /etc/shorewall/masq:
#INTERFACE SUBNET ADDRESS PROTO PORT(S) eth0:192.168.1.5 192.168.1.0/24 192.168.1.254 tcp www
In /etc/shorewall/rules:
#ACTION SOURCE DEST PROTO DEST PORT SOURCE ORIGINAL # PORT DEST. DNAT loc loc:192.168.1.5 tcp www - 130.151.100.69 DNAT net loc:192.168.1.5 tcp www - 130.151.100.69
Mapping different port from outside to inside is handled only in /etc/shorewall/rules, as usual.
Hosts in LAN#1 may access hosts in LAN#2 by just adding a static route to the 192.168.2.0/24 network via the 192.168.1.10 gateway, but it is very annoying to modify the routing table into several hosts.
You can instead make two configurations on the Shorewall firewall. First of all you add the static route into /etc/network/interfaces:
auto eth1 iface eth1 inet static address 192.168.1.1 netmask 255.255.255.0 up /sbin/route add -net 192.168.2.0/24 gw 192.168.1.10 || true down /sbin/route del -net 192.168.2.0/24 gw 192.168.1.10 || true
then you have to add the routeback option for the eth1 interfaces in the /etc/shorewall/interfaces file:
loc eth1 routeback
How the various tables are traversed? This is an handy schema found here:
There is a problem starting Shorewall on a diskless host which mounts its root filesystem via NFS; the standard behaviour of Shorewall on start, is to set a DROP default policy for INPUT and OUTPUT chains before enforcing other rules. In this way the NFS mount gets blocked while Shorewall tries to acquire a lockfile on the disk and the entire host is screwed. The error message is:
lockfile: Sorry, giving up on "/var/lock/shorewall"
There is a non-documented feature called CRITICALHOSTS, this is a list of hosts that requires to never be blocked. Just put into /etc/shorewall/shorewall.conf
someting like:
CRITICALHOSTS="eth0:172.21.10.1 eth0:172.21.10.254"
WARNING the interface name is required, otherwise the iptable rules are syntactically correct, but ineffective. May be this is a bug of Shorewall 4.0.8.
Vedere la definizione del DNS Amplification Attack.
Con un tool tipo iptraf si verifica il traffico DNS cioè UDP porta 53, utilizzando la funzione Statistical breakdowns…, By TCP/UDP port. Se siamo in presenza di un attacco è facile vedere il flood di pacchetti con tcpdump, l'host di destinazione è il nostro server DNS:
tcpdump -i eth0 -n 'port 53 and dst host 148.67.69.17' 16:51:31.065257 IP 185.28.23.10.56539 > 148.67.69.17.53: 9359+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.067428 IP 185.28.23.10.47247 > 148.67.69.17.53: 2560+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.067806 IP 198.176.28.48.24916 > 148.67.69.17.53: 59757+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.068372 IP 198.176.28.48.17633 > 148.67.69.17.53: 30287+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.080435 IP 79.178.169.108.14210 > 148.67.69.17.53: 56049+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.084766 IP 217.79.182.87.18963 > 148.67.69.17.53: 31993+ [1au] ANY? zing.zong.co.ua. (44) 16:51:31.086912 IP 217.79.182.87.47510 > 148.67.69.17.53: 28265+ [1au] ANY? zing.zong.co.ua. (44)
l'IP sorgente può essere più di uno, si tratta ovviamente di un IP spooffato e si tratta della reale vittima dell'attacco DDOS.
In questo caso l'amplificazione consiste nel fatto che una semplice query di tipo ANY su zing.zong.co.ua restituisce una risposta di circa 10k:
host -t ANY zing.zong.co.ua | wc -c 10254
Se la query è identificabile in modo univoco si può rapidamente aggiungere una regola iptables e bloccare tutte le richieste malevole, le relative risposte (che sono il reale peso) non ci saranno. Anzitutto identifichiamo una stringa del payload:
tcpdump -X -i eth0 -n 'port 53 and dst host 148.67.69.17 and src host 217.79.182.87' 16:59:04.205759 IP 217.79.182.87.14717 > 148.67.69.17.53: 28265+ [1au] ANY? zing.zong.co.ua. (44) 0x0000: 4500 0048 1db6 0000 f211 47ec d94f b657 E..H......G..O.W 0x0010: 904c 430f 397d 0035 0034 0000 6e69 0100 .LC.9}.5.4..ni.. 0x0020: 0001 0000 0000 0001 047a 696e 6704 7a6f .........zing.zo 0x0030: 6e67 0263 6f02 7561 0000 ff00 0100 0029 ng.co.ua.......) 0x0040: 2328 0000 0000 0000 #(...... 16:59:04.211641 IP 217.79.182.87.50901 > 148.67.69.17.53: 42235+ [1au] ANY? zing.zong.co.ua. (44) 0x0000: 4500 0048 1db7 0000 f211 47eb d94f b657 E..H......G..O.W 0x0010: 904c 430f c6d5 0035 0034 0000 a4fb 0100 .LC....5.4...... 0x0020: 0001 0000 0000 0001 047a 696e 6704 7a6f .........zing.zo 0x0030: 6e67 0263 6f02 7561 0000 ff00 0100 0029 ng.co.ua.......) 0x0040: 2328 0000 0000 0000 #(......
Attenzione che il punto non è il carattere 0x2e come ci si aspetta:
Hex | ASCII |
---|---|
047a 696e 6704 7a6f 6e67 0263 6f02 7561 | zing.zong.co.ua |
Quindi aggiungiamo la regola iptables:
/sbin/iptables -I INPUT -p udp -m string --hex-string '|047A696E67047A6F6E6702636F027561|' \ --algo bm --from 40 --to 56 -j DROP -m comment --comment "DROP DNS Q zing.zong.co.ua"
Discorso diverso se si vuole limitare il rate delle richieste DNS, in questo modo si prevengono futuri attacchi, indipendentemente dal payload del pacchetto. Ecco uno script che imposta un limite di 4 richieste al secondo per ogni IP sorgente. Un singolo IP viene considerato whitelisted e non sottoposto al rate:
#!/bin/sh limit="4/second" # Trigger rule above this packet rate. burst="20" # Accept a burst of packets from good sources. expire="60000" # Keep the rule for msec. options="! -s 144.76.223.44 -p udp --dport 53 -m hashlimit --hashlimit-name DNS \ --hashlimit-above $limit --hashlimit-burst $burst --hashlimit-htable-expire $expire \ --hashlimit-mode srcip --hashlimit-srcmask 32" case "$1" in start) iptables -I INPUT $options -j DROP #iptables -I INPUT $options -j LOG --log-level debug ;; stop) iptables -D INPUT $options -j DROP #iptables -D INPUT $options -j LOG --log-level debug ;; *) echo "Usage: $(basename $0) {start|stop}" ;; esac
Nella tabella /proc/net/ipt_hashlimit/DNS
troviamo: