User Tools

Site Tools


doc:appunti:linux:sa:iptables

Iptables

Connection tracking

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

Accessing a DNAT sever from the local LAN using the public IP address

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.

  • The public IP address is 82.189.151.152
  • The private IP of the server is 192.168.1.32
  • The service is TCP port 80 (www)
  • The local netword is 192.168.1.0/24
  • The firewall interface on the LAN is eth0
# 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

Shorewall and DNAT onto a local host

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.

Shorewall with router in local LAN

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.

Shorewall with router in LAN

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

Iptables schema

How the various tables are traversed? This is an handy schema found here:

iptables schema

Shorewall on a diskless host

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.

Usare iptables per mitigare o bloccare un DNS Amplification Attack

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:

  1. Conto alla rovescia per rimuovere la entry dalla tabella
  2. Inirizzo_IP:porta sorgente
  3. Inirizzo_IP:porta destinazione
  4. Credito attuale
  5. Credito massimo: es. (burst 20) * (costo 6400) = 128000
  6. Costo: es. 6400 per 5/s, 8000 per 4/s, cioè 32000 / (n/s)
doc/appunti/linux/sa/iptables.txt · Last modified: 2020/11/23 14:28 by niccolo