iptables

iptables ermöglicht die Konfiguration der gleichanmigen Kernel-Module, die sich um Paketfilterung und -umleitung kümmern.

In CentOS 7 wurde iptables durch firewalld, welches erstmalig in Fedora 18 zum Einsatz kam, ersetzt. firewalld einfacher und kommt besser mit Änderungen am Regelwerk zurecht. iptables ist nach wie vor umfangreicher in seinen Möglichkeiten. Tools zur Konvertierung von iptables-Regelwerken nach firewalld werden diskutiert, sind aber Stand 2020 nicht verfügbar.

Die beiden Firewall-Management-Konzepte können nicht parallel existieren. Wer iptables einsetzt, für den gilt:

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

yum -y install iptables-services

systemctl enable iptables
systemctl start iptables

In iptables legen unterschiedliche Tabellen die Art des Umgangs mit den Paketen fest, beispielsweise, ob Pakete gefiltert („filter“-Tabelle) oder übersetzt („NAT“) werden müssen. Eine Tabelle enthält Ketten („chains“) sowie Regeln („rules“). Chains fassen Rules zusammen, zudem sind sie wie die sprichwörtlichen Glieder einer Kette in der Reihenfolge festgelegt: eine Kette von Regeln wird vor dem Routing evaluiert („PREROUTING“-Chain), danach folgen die Regeln zur Weiterleitung von Paketen an lokale Applikationen („INPUT“-Chain) usw. Zur Zusammenfassung von Policies lassen sich eigene Chains erstellen. Die vordefinierten Chains:

PREROUTING

Pakete von extern landen zuerst in dieser Kette - vor dem Routing an Prozesse. Wird für DNAT verwendet (Destination NAT; Zieladresse der Pakete ändern), was bedeutet, dass nachfolgende Prozesse nur die durch die NAT-Regeln umgeschriebenen Pakete sehen.

INPUT

Routing-Entscheidung getroffen, Paket wird einer lokalen Applikation zugestellt.

FORWARD

Routing-Entscheidung getroffen, Paket ist nicht für unsere Maschine bestimmt, wird weitergeleitet und landet direkt in der POSTROUTING-Chain. Das FORWARDing muss in der /etc/systctl.conf eingeschaltet werden.

OUTPUT

Pakete, die durch unseren Server erzeugt wurden, z.B. als Antwort auf einen Request aus der INPUT-Chain, durchlaufen diese Kette.

POSTROUTING

Alle Pakete laufen zwecks SNAT (Source NAT; Quelladresse der Pakete ändern) hier nochmals durch, bevor sie an die Netzwerk-Hardware abgegeben werden, was bedeutet, dass alle Prozesse auf der Linux-Box die Pakete VOR der Änderung sehen. Masquerading ist übrigens eines spezielle Form von SNAT und sollte nur bei dynamischen IP-Adressen zum Einsatz kommen; für statische IP-Adressen verwendet man SNAT.

iptables Standard-Regelwerk erklärt

Ein Beispiel für eine filter-Tabelle, die eingehend alles blockt, jedoch Pings sowie Anfragen auf den SSH-Dienst zulässt (Port 22/tcp).

/etc/sysconfig/iptables
 1*filter
 2:INPUT ACCEPT [0:0]
 3:FORWARD ACCEPT [0:0]
 4:OUTPUT ACCEPT [0:0]
 5-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 6-A INPUT -p icmp -j ACCEPT
 7-A INPUT -i lo -j ACCEPT
 8-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
 9-A INPUT -j REJECT --reject-with icmp-host-prohibited
10-A FORWARD -j REJECT --reject-with icmp-host-prohibited
11COMMIT

Die Angaben [0:0] sind einfach die Anzahl Pakete und die Anzahl der Bytes, die die Chain bisher verarbeitet hat, und werden bei der Arbeit mit iptables-save mit konkreten Werten gefüllt. Für eigene Definitionen also einfach [0:0] verwenden.

iptables reagiert genervt auf Zeilen im Definitions-File, die nur ein Leerzeichen beinhalten, was in einem iptables-restore v1.4.21: no command specified Error occurred at line: ... resultiert. Die letzte Zeile „COMMIT“ muss zudem zwingend noch mit einem Zeilenumbruch abgeschlossen werden (also COMMIT\n).

Die Angaben erklärt:

*filter

Es folgen Regeln für die Paketfilter-Tabelle.

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

Regel zur INPUT-Chain hinzufügen. Modul „state“ verwenden, und auf State „RELATED,ESTABLISHED“ prüfen. Bedeutet: Pakete, die an lokale Applikationen gerichtet sind, werden akzeptiert, wenn das State-Modul erkannt hat, dass sie bereits zu früheren Verbindungen gehören.

iptables kennt die States:

  • ESTABLISHED

  • INVALID

  • NEW

  • RELATED

-A INPUT -i lo -j ACCEPT

Pakete über das localhost-Interface werden immer akzeptiert. Diese Regel ist ein Muss.

-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

Neue TCP-Pakete, die an den Port 22 gerichtet sind, werden akzeptiert - das State-Modul erkennt den Status von TCP- und UDP-Paketen (der Status von UDP-Paketen wird simuliert, da UDP natürlich keine Verbindungen kennt).

-A INPUT -j REJECT --reject-with icmp-host-prohibited

Alle anderen Pakete, die an lokale Applikationen geroutet worden wären, werden höflich zurückgewiesen……

-A FORWARD -j REJECT --reject-with icmp-host-prohibited

…​genau wie Pakete, die nicht für unsere Maschine bestimmt und zur Weiterleitung bestimmt waren.

COMMIT

Fertig.

Aktiviert wird das Regelwek mittels

systemctl iptables restart

Angeschaut wird das aktuelle Regelwerk mit

iptables --list --all

Auf die Reihenfolge kommt es an: diese beiden Regeln würden den SSH-Zugang sperren - Pakete, die eine Regel erfolgreich durchlaufen haben, durchlaufen keine weiteren Regeln mehr.

/etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j REJECT --reject-with icmp-host-prohibited
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

Umgang mit iptables

Liste verfügbare iptables-Module:

cat /proc/net/ip_tables_matches

Umgesetzt mit dem iptables-Kommando:

# List the ruleset
iptables --verbose --list --numeric
# with rule numbers
iptables --verbose --list --numeric --line-numbers
# show NAT rules
iptables --verbose --list --numeric --table nat

# Allow a port (inbound)
# add rule to a specific position
iptables --insert INPUT [rulenum] -p tcp -m state --state NEW -m tcp --dport 9443 -j ACCEPT
# or append rule
iptables --append INPUT -p tcp -m state --state NEW -m tcp --dport 9443 -j ACCEPT

# Allow a port (outbound)
iptables --insert OUTPUT [rulenum] -m tcp -p tcp --dport 3306 -j ACCEPT

Direkt in /etc/sysconfig/iptables:

/etc/sysconfig/iptables
*filter*

# Allow all outbound and all established connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# Deny a port
-A INPUT -p tcp --dport 21 -j REJECT --reject-with icmp-host-prohibited

# A forward rule
-A FORWARD -o eth0 -p tcp -m tcp -s 192.168.26.6 -d 1.2.3.4 --dport 6444 -m state --state NEW -j ACCEPT


*nat*

# DNAT
-A PREROUTING -p tcp -m tcp -m multiport -d 10.80.32.1 --dports 80,443 -j DNAT --to-destination 192.168.26.6

# SNAT
-A POSTROUTING -o eth0 -j SNAT --to-source 10.80.32.1

Logging

/etc/sysconfig/iptables
# log accepted packets
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8009 -j LOG --log-level info --log-prefix "ACCEPT "
-A INPUT -p tcp -m state --state NEW -m tcp --dport 8009 -j ACCEPT

# log denied packets
-A INPUT -j LOG --log-level info --log-prefix "REJECT "
-A INPUT -j REJECT --reject-with icmp-host-prohibited

Blockieren von länderbasierten IP-Bereichen mit GeoIP und iptables

Red Hat-basierte Systeme:

# update and reboot is important to match the current kernel-devel package from repo to that on
# the machine
yum -y update

yum -y install epel-release
yum -y install gcc-c++ make automake kernel-devel wget unzip iptables-devel perl-Text-CSV_XS perl-Net-CIDR-Lite

VER=2.14  # 2017-11, for RHEL 7
VER=3.9   # 2020-02, for RHEL 8+ (xtables v3.x requires iptables v1.6+)

wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/xtables-addons-$VER.tar.xz
tar xf xtables-addons-$VER.tar.xz
cd xtables-addons-$VER

./configure

# RHEL 7 only:
sed -i '/xt_TARPIT.o$/s/^/#/' extensions/Kbuild

make
make install

chcon -vR --user=system_u /lib/modules/$(uname -r)/extra/*.ko
chcon -vR --type=lib_t /lib64/xtables/*.so

Anschliessend:

  • dbip’s GeoIP-Datenbank herunterladen (regelmässig 1x pro Monat).

  • RHEL 7: Perl-Script geoip/xt_geoip_build aus dem neuesten 3er-Release von xtables nehmen und auf die Zielmaschine kopieren.

xtables kann auf „Big Endian“-Systemen („BE“, Solaris) und auf „Little Endian“-Systemen („LE“, Linux) eingesetzt werden. In diesem Ordering erwartet es auch die Binär-Datenbanken. Auf Linux genügt daher das LE-Verzeichnis:

cd geoip
chmod +x geoip/xt_geoip_build
mkdir -p /usr/share/xt_geoip/LE
./xt_geoip_build -S . -D /usr/share/xt_geoip/LE

Tipp

Arbeitet ein System mit „Big Endian“ oder „Little Endian“?

echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6
# Big Endian: 0, Little Endian: 1

Länder blocken:

iptables -m geoip --src-cc country[,country...] --dst-cc country[,country...]

#  Block all incoming traffic except from CH. Use ISO3166 codes.
iptables -I INPUT -m geoip ! --src-cc CH -j DROP

Built on 2022-06-03