Eng ↴
  • Ger
  • Eng
  • Tag cloud
  • Site map
  • Login Login
    Forgot your password?
Lutz Donnerhacke
Navigation
  • Projekte
  • Veröffentlichungen
  • Blog
  • Impressum
  • GDPR
  • Search

Search

Search for "NAT>" returned 31 matches

XDP CGNAT 2: Erstes XDP-Programm

04/09/2026 8:55 pm Lutz Donnerhacke Tags: Linux , Broadband , XDP 0

Nachdem in ein Testbed steht, geht es nun an das erste XDP-Programm. Das Augenmerk liegt zunächst auf einer funktionsfähigen Entwicklungsumgebung für solche Programme.

Mein erstes Programm

So ziemlich das kürzeste Programm, dessen Wirkung man auch bemerkt, wirft einfach alle eingehenden Frames weg. Ausnahmslos. Das sollte in jedem Fall auffallen.

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

SEC("xdp")
int nat_on_stick(struct xdp_md *ctx) {
   return XDP_DROP;
}

char _license[] SEC("license") = "GPL";

Die Includes gestatten die einfache Formulierung der zugrundeliegenden Struktur eines eBPF-Programms, das an die XDP-Schnittstelle eines Interfaces gebunden werden kann. Beim Laden von Code in den Kernel werden viele Dinge überprüft. Dazu gehört auch, dass eine passende Lizenz des Codes vorliegt, die vom Kernel akzeptiert wird. In dem Fall nehme ich die GPL.

Als Programm wird der Kernel nur Funktionen in der Section "xdp" akzeptieren, wenn dann die Bindung ans Interface erfolgen soll. Die Section gibt also an, für welchen Andockpunkt (Hook) das eBPF Programm geeignet ist. Der Name der Funktionen ist egal. Es können auch mehrere Prozeduren in einer Datei existieren, aus denen man später beim Andocken auswählt.

Eine XDP-Funktion bekommt einen Datensatz (Context) übergeben, der den aktuellen Frame, der die Bearbeitung getriggert hat, enthält. Man findet dort Informationen über die beteiligten Interfaces, ggfls. Zeitstempel, aber auch bereits von der Hardware extrahierte Teildaten (z.B. das Vlan) des eingegangenen Frames, und natürlich das Frame selbst.

Der Rückgabewert beschreibt, wie mit dem Frame nach der XDP-Behandlung verfahren werden soll:

  • XDP_DROP: Wirf den Frame weg.
  • XDP_PASS: Bearbeite ihn weiter, als wenn es kein XDP gäbe (wobei der Frame aber verändert worden sein kann)
  • XDP_REDIRECT: Schicke den Frame an eine andere Stelle (Interface, CPU, ...) zur weiteren Bearbeitung
  • XDP_TX: Schicke den (bearbeiteten) Frame zurück an das Interface, von dem er kam.

Es gibt noch weitere Rückgabewerte, aber die sind produktiv nicht von Belang.

Dieses Programm ignoriert also den auslösenden Frame und weist den Device-Treiber an, den Frame zu verwerfen. Es ist also so, als wäre gar nichts auf dem Interface angekommen. Würde man mit tcpdump versuchen, hier Netzwerk-Aktivitäten mitzuschneiden, so sagt der Netzwerk-Treiber stets: Keine Daten angekommen,

Kompilieren

XDP-Programme sollen auf verschiedenster Hardware laufen. Einige Netzwerkkarten erlauben es, diese Programme direkt auf dem Netzwerkchip abarbeiten zu lassen. Die CPU-Architektur zum Arbeitszeitpunkt kann also stark variieren: Es muss nicht die Host-CPU sein. Deswegen werden XDP-Programme als eBPF-Zwischenformat übertragen. Der Compiler darf keinen Maschinen-Code für die aktuelle CPU erstellen, sondern muss für die fremde Architektur cross-compilieren. Dies kann der clang-Compiler mit dem Target "bpf".

# apt install llvm clang xdp-tools make linux-headers-amd64 libbpf-dev
$ clang -target bpf -c nat-on-stick.c

Das Ergebnis ist eine Art Interpreter-Bytecode für eine streng definierte virtuelle Maschine innerhalb des Kernels. Beim Laden übersetzt der Kernel diesen Bytecode in native Maschinesprache, die aber keinen Schaden anrichten kann, weil die strenge Definition eine rigorose Validierung des Codes ermöglicht.

In meinem Fall heißt die Quelldatei "nat-on-stick.c". Der minimale Compileraufruf soll nur das Objekt-File "nat-on-stick.o" mit dem Bytecode erzeugen, kein direkt ausführbares Programm erstellen. Deswegen die Einschränkung mit "-c".

Es gibt weitere sinnvolle Optionen beim Kompilieren:

  • -g Erzeugen von Debug-Informationen (BTF), die später beim Arbeiten mit dem eBPF Dateien sehr nützlich sind.
  • -O2 Erzeugen von gutem Code, auch wenn die Formulierungen durch die Programmiersprache das nicht so her geben.
  • -I /usr/include/x86_64-linux-gnu Einbinden der benötigten Grunddefinitionen für die Architektur, auf der der Cross-Compiler arbeitet

Die letzte Option weist auf eine Stolperfalle hin: Dadurch, dass der Cross-Compiler nicht selbst als BPF-Programm geschrieben ist, sind seine Systembibliotheken normalerweise unbenutzbar. Man müsste die alle für eBPF portieren. Das macht natürlich keinen Sinn, also nimmt man die Systembibliotheken des Hostumgebung und hofft, dass der Compiler den Unterschied schon erkennen wird.

Einige Datentypen sind auf der eBPF-Architektur als 32bit-Typen definiert, die es in meiner 64bit Host-Architektur nicht gibt. Da kommt der Compiler ins Stolpern, weil er die 32bit-Header nicht findet. Glücklicherweise kann man diese aber nachinstallieren, so dass die auch auf der 64bit Host-Architektur parallel genutzt werden können.

# apt install libc6-dev-i386

Den Objektcode kann man sich übrigens auch ansehen:

$ llvm-objdump-19 -S nat-on-stick.o
nat-on-stick.o: file format elf64-bpf
Disassembly of section xdp:
0000000000000000 <nat_on_stick>:
;    return XDP_DROP;
       0:       b7 00 00 00 01 00 00 00 r0 = 0x1
       1:       95 00 00 00 00 00 00 00 exit

Man erkennt den 64bit breiten Bytecode und die symbolische Übersetzung. Für dieses triviale Programm ist der Code auch trivial.

Aktivieren von XDP

Für das Arbeiten mit eBPF-Programmen gibt es ein besonderes Werkzeug "bpftool"

# apt install bpftool

Das Script "xdp-on.sh" läd ein Objekt-File an den xdp-Hook des "nat"-Intefaces im Namespace des "Router"s.

#! /bin/sh

PROG="$1"
if [ ! -s "$PROG" ] ; then
  echo "$0 object-file"
  exit 1
fi

BPFFS="/sys/fs/bpf"
fgrep -q "$BPFFS" /proc/mounts ||
  mount -t bpf bpffs "$BPFFS"

ip netns exec router sh -c "
  bpftool prog load $PROG $BPFFS/nat-proc
  bpftool net attach xdp pinned $BPFFS/nat-proc dev nat
  rm -f $BPFFS/nat-proc
"

Der Weg wirkt etwas kompliziert:

  • Zunächst mal braucht man tatsächlich ein Object-File.
  • Zur Kommunikation mit dem Kernel hilft es, das bpf-Filesystem zu mounten.
  • Damit kann man ein Objekt-File in den Kernel laden und es unter einem bestimmten Namen wieder finden (pinning). Normalerweise bekommt man beim Laden nur eine ID zurück, die man sich merken muss, um das Programm später wieder zu finden. Dies ersetzt hier der Name.
  • Anhand des Names kann man dann das schon in den Kernel geladene Programm an die Netzwerk-Schnittstelle binden.
  • Danach wird der Name nicht mehr benötigt.

In umgekehrter Richtung geht es mit "xdp-off.sh" ähnlich:

#! /bin/sh

ip netns exec router \
  bpftool net detach xdp dev nat 

Es ist auch möglich, sich den Programmcode nach der Bearbeitung durch den Kernel anzusehen

# bpftool prog dump xlated name nat_on_stick
int nat_on_stick(struct xdp_md * ctx):
; return XDP_DROP;
   0: (b7) r0 = 1
   1: (95) exit 

Und das entspricht ja genau dem, was der Objekt-Dump nach dem Kompilieren erzählt hat.

Zusammenfassung

Natürlich will man nicht alles immer von Hand tippen. Also gibt's ein Makefile:

CC = clang
CFLAGS = -target bpf -c -O2 -g -I /usr/include/x86_64-linux-gnu
OBJDUMP = llvm-objdump-19
SUDO = sudo
TESTBED_NS = /run/netns/router

OBJ = nat-on-stick.o

.PHONY: tests
tests: | $(TESTBED_NS)
        $(SUDO) ./tests.sh

.PHONY: install
install: $(OBJ) | $(TESTBED_NS)
        $(SUDO) ./xdp-on.sh $^

.PHONY: clean
clean:
        rm -f *.o *~ *.S *.dot
        $(SUDO) ./xdp-off.sh
        $(SUDO) ./testbed-off.sh

$(TESTBED_NS):
        $(SUDO) ./testbed-on.sh

.c.o:
        $(CC) $(CFLAGS) -o $@ $^

.o.S:
        $(OBJDUMP) -S $^ > $@

test.dot: install
        $(SUDO) ./xdp-dump.sh > $@ 

Der Trick mit TESTBED_NS prüft, ob der Namespace schon existiert und baut bei Bedarf das Testbed auf.

"xdp-dump.sh" ist ein Script, was den geladenen Code zur besseren Visualisierung nach GraphWiz umwandelt:

#! /bin/sh
bpftool prog dump xlated name nat_on_stick visual

Das Ergebnis sieht dann so aus:

xdp-drop

Und der Test?

$ make install tests
clang -target bpf -c -O2 -g -I /usr/include/x86_64-linux-gnu -o nat-on-stick.o nat-on-stick.c
sudo ./testbed-on.sh
sudo ./xdp-on.sh nat-on-stick.o
sudo ./tests.sh

Jetzt geht's los!

### Client2 pings the gateway
PING 192.168.20.254 (192.168.20.254) 56(84) bytes of data.

--- 192.168.20.254 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2054ms

### Client2 pings behind the gateway
PING 100.64.0.1 (100.64.0.1) 56(84) bytes of data.

--- 100.64.0.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2025ms

### Packet dump at the switch port towards the gateway
22:07:33.077927 66:b8:47:f2:ad:8f > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP (0x0806), Request who-has 192.168.20.254 tell 192.168.20.2, length 28
22:07:34.101949 66:b8:47:f2:ad:8f > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP (0x0806), Request who-has 192.168.20.254 tell 192.168.20.2, length 28
22:07:36.053988 66:b8:47:f2:ad:8f > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP (0x0806), Request who-has 192.168.20.254 tell 192.168.20.2, length 28
22:07:37.077923 66:b8:47:f2:ad:8f > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 20, p 0, ethertype ARP (0x0806), Request who-has 192.168.20.254 tell 192.168.20.2, length 28 

Man sieht nur, wie der Client verzweifelt versucht, eine Adressauflösung für die Gateway-Adresse zu bekommen. Aber es kommt keine Antwort zurück.
Das XDP-Programm hat also erfolgreich die Kommunikation mit dem Router verhindert, indem es alle eingehenden Frames verwarf. Oder ist einfach was kaputt?

XDP CGNAT 1: Testbed

04/09/2026 2:39 pm Lutz Donnerhacke Tags: Linux , Broadband , XDP 0

Mit XDP hatte ich ja schon öfter gespielt, es aber nie richtig erklärt. Es steht nun absehbar eine besondere CGNAT-Anforderung im Raum. Deswegen ist es einen Versuch wert, die Implementation komplett in XDP auf diesen UseCase zuzuschneiden.

Testbed

Eine Reihe von Nutzern (Clients) soll aus einem privaten Netz über einen Router, der dann NAT machen soll, ins Internet kommen. Die Verbindungen zwischen den Interfaces sollen über zwei untaggt Bridges eines Switches geführt werden. Die Verbindung des Switches zum Router soll getaggt sein, so dass der Router auf nur einem Interface angeschlossen wird.

        +--------+
        | router |
        +---||---+
    vlan 10 || vlan 20
+-----------||------------+
| switch    /\   untagged |
|          /  \           |
|         /    \          |
| +------|-+  +-|-------+ |
| | public |  | private | |
| +---|----+  +|||||||||+ |
+-----|--------|||||||||--+
      |        |||||||||
+-----|----+   ||||||||`---- Client1
| internet |   |||||||`----- Client2
+----------+   ||||||`------ Client3
               |||||`------- Client4
               ||||`-------- Client5
               |||`--------- Client6
               ||`---------- Client7
               |`----------- Client8
               `------------ Client9 

Voraussetzungen

Die Entwicklung soll auf einem aktuellen Debian laufen. Dieses bringt von Haus aus nicht alle benötigten Pakete vorinstalliert mit. Wenn nötig, werde ich also angeben, welche Pakete nachzuinstallieren sind. Dabei versuche ich möglichst wenig Abhängigkeiten zu erzwingen.

Fragt man die KI nach der Einrichtung von Linux-bridges, so bekommt man eine Menge an Befehlen und Paketen vorgesetzt, die in älteren Distributionen tatsächlich benötigt wurden. Es ist etwas mühselig, aber lohnend, hier auf die aktuellen Werkzeuge zu setzen.

Die Implementierung des Testbeds soll mittels Network-Namespaces erfolgen, so dass ich ohne externe Technik und einen Satz von VMs/Containern/... auskommen kann.

Eines der Probleme bei der Erschaffung neuer Network-Stacks sind die Default-Einstellungen. Da es hier nur um IPv4 geht, möchte ich IPv6 generell ausklopfen, denn diese Pakete stören bei der Entwicklung ziemlich.

Der Switch

Der Switch ist ein Namespace mit zwei Bridges: "public" und "private":

ip netns add switch
ip netns exec switch sysctl -q net.ipv6.conf.default.disable_ipv6=1
ip link add public  netns switch type bridge
ip link add private netns switch type bridge
ip netns exec switch sh -c '
 ip link set public  up
 ip link set private up
'

Der Router

Um zwischen zwei Namespaces Verbindungen zu bekommen, benutzt man veth: Das sind Interface-Paare, die in verschiedenen Namespaces liegen können.

Da diese veth immer paarweise erzeugt werden, haben die Linux-Entwicker es nicht eingesehen, getrennte Sende- und Empfangspuffer vorzuhalten. Die sendende Seite schreibt einfach in den Empfangspuffer auf der anderen Seite. Diese Optimierung wird später noch für schwere Probleme sorgen.

Für die Arbeit mit getaggten Frames, muss die MTU um die vier Byte des Vlan-Headers größer sein.

ip netns add router
ip netns exec router sysctl -q net.ipv6.conf.default.disable_ipv6=1
ip link  add router mtu 1504 netns switch type veth peer nat netns router mtu 1504

Die beiden Vlans werden als getrennte Interfaces durch Kernel zur Verfügung gestellt. Damit brauche ich mich nicht um das Tagging selbst kümmern, wenn ich mit IPs, Routen oder sonstiger Software arbeiten will.

ip netns exec router sh -c '
  ip link add link nat nat.10 type vlan id 10
  ip addr add 100.64.0.10/24 dev nat.10
  ip link add link nat nat.20 type vlan id 20
  ip addr add 192.168.20.254/24 dev nat.20
  ip link set nat up
  ip link set nat.10 up
  ip link set nat.20 up
  sysctl -q net.ipv4.ip_forward=1
'

Das Ergebnis schaut dann schon ganz passabel aus:

# ip netns exec router ip route
100.64.0.0/24 dev nat.10 proto kernel scope link src 100.64.0.10
192.168.20.0/24 dev nat.20 proto kernel scope link src 192.168.20.254

Auf die gleiche Weise lasse ich den Kernel die Vlans auf dem Switch behandeln, um die ungetaggten Frames den Bridges zuzuführen.

ip netns exec switch sh -c '
  ip link add link router router.10 type vlan id 10
  ip link set router.10 master public
  ip link add link router router.20 type vlan id 20
  ip link set router.20 master private
  ip link set router up
  ip link set router.10 up
  ip link set router.20 up
' 

Das Internet

Für den Anfang genügt es, eine einzelne IP zur Verfügung zu stellen.

ip netns add internet
ip netns exec internet sysctl -q net.ipv6.conf.default.disable_ipv6=1
ip link  add internet netns switch type veth peer downlink netns internet
ip netns exec switch ip link set internet master public up
ip netns exec internet sh -c '
  ip addr add 100.64.0.1/24 dev downlink
  ip link set downlink up
' 

Wesentlich an diesem Knoten ist, dass er keine Route zu den privaten Netzen kennt. Wenn also dieser Knoten für die Nutzer erreichbar sein soll, dann muss der Router korrektes NAT machen.

# ip netns exec internet ip route
100.64.0.0/24 dev downlink proto kernel scope link src 100.64.0.1

Die Nutzer

Es gibt eine (skalierbare) Menge an Clients, die über die "private" Bridge des Switches zum Router gelangen und dorthin eine Default-Route zeigen lassen.

for c in $(seq 1 9); do
  ip netns add client$c
  ip netns exec client$c sysctl -q net.ipv6.conf.default.disable_ipv6=1
  ip link  add client$c netns switch type veth peer isp netns client$c
  ip netns exec switch ip link set client$c master private up
  ip netns exec client$c sh -c "
    ip addr add 192.168.20.$c/24 dev isp
    ip link set isp up
    ip route add default via 192.168.20.254
  "
done

Somit sieht die Routingtabelle ziemlich normal aus:

# ip netns exec client6 ip route
default via 192.168.20.254 dev isp
192.168.20.0/24 dev isp proto kernel scope link src 192.168.20.6

Tests

Um die Funktionalität standardisiert zu prüfen, gibt es ein kleines Test-Script:

#! /usr/bin/bash

c=$(($RANDOM%9+1))
dump=/tmp/nat-router.$$
ip netns exec switch tcpdump -enni router > $dump &

echo "### Client$c pings the gateway"
ip netns exec client$c ping -w 3 192.168.20.254

echo "### Client$c pings behind the gateway"
ip netns exec client$c ping -w 3 100.64.0.1

echo "### Packet dump at the switch port towards the gateway"
kill -1 %1
cat $dump
rm $dump

Das tcpdump schneidet den Datenverkehr mit dem Router auf der Switch-Seite mit. Ein Mitschnitt auf der Router-Seite würde nicht viel bringen, denn XDP soll eingreifen, bevor der Kernel die Frames ernsthaft anschaut. Wenn also XDP ein Frame behandelt, wird ein tcpdump auf dem Router davon gar nichts sehen. Dieser frühen Behandlung von Frames ist maßgeblich für den Geschwindigkeits-Vorteil von XDP verantwortlich.

Der eigentliche Test besteht vorerst darin, einen zufälligen Nutzer zunächst das Default-Gateway pingen zu lassen und anschließend das Internet.

# tests.sh 
### Client5 pings the gateway
PING 192.168.20.254 (192.168.20.254) 56(84) bytes of data.
64 bytes from 192.168.20.254: icmp_seq=1 ttl=64 time=0.313 ms
64 bytes from 192.168.20.254: icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from 192.168.20.254: icmp_seq=3 ttl=64 time=0.071 ms

--- 192.168.20.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2055ms
rtt min/avg/max/mdev = 0.059/0.147/0.313/0.117 ms
### Client5 pings behind the gateway
PING 100.64.0.1 (100.64.0.1) 56(84) bytes of data.

--- 100.64.0.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2025ms

### Packet dump at the switch port towards the gateway
15:44:33.909912 4e:3b:d5:b9:61:4d > ca:61:e9:9b:52:84, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 192.168.20.254: ICMP echo request, id 1899, seq 2, length 64
15:44:33.909933 ca:61:e9:9b:52:84 > 4e:3b:d5:b9:61:4d, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.254 > 192.168.20.5: ICMP echo reply, id 1899, seq 2, length 64
15:44:34.933978 4e:3b:d5:b9:61:4d > ca:61:e9:9b:52:84, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 192.168.20.254: ICMP echo request, id 1899, seq 3, length 64
15:44:34.934001 ca:61:e9:9b:52:84 > 4e:3b:d5:b9:61:4d, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.254 > 192.168.20.5: ICMP echo reply, id 1899, seq 3, length 64

Im tcpdump ist schön zu sehen, wie zunächst 3x das Default-Gateway erreicht werden kann und dieses antwortet:

  • Die MAC- und die IP-Adressen der Antwort sind vertauscht.
  • Der ICMP-Typ wechselt von "Echo Request" zu "Echo Reply"
15:44:35.884891 4e:3b:d5:b9:61:4d > ca:61:e9:9b:52:84, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 1, length 64
15:44:35.884922 ca:61:e9:9b:52:84 > fa:92:df:ad:09:b1, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 1, length 64
15:44:36.885910 4e:3b:d5:b9:61:4d > ca:61:e9:9b:52:84, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 2, length 64
15:44:36.885926 ca:61:e9:9b:52:84 > fa:92:df:ad:09:b1, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 2, length 64
15:44:37.909994 4e:3b:d5:b9:61:4d > ca:61:e9:9b:52:84, ethertype 802.1Q (0x8100), length 102: vlan 20, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 3, length 64
15:44:37.910014 ca:61:e9:9b:52:84 > fa:92:df:ad:09:b1, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4 (0x0800), 192.168.20.5 > 100.64.0.1: ICMP echo request, id 1900, seq 3, length 64

Beim Versuch ins Internet zu gelangen sind auch jeweils zwei Frames zu sehen:

  • Die "Echo Request" Anfrage, die ans Gateway gesendet wird (Vlan 20)
  • Die "Echo Request" Anfrage, die das Gateway weiterleitet (Vlan 10)
  • Beim zweiten Frame ist der Absender zwar die MAC des Gateways, aber im Paket steht immer noch die IP des Kunden.
  • Da der Internet-Knoten keine Rück-Route hat, kann er keine Antwort senden.

Aufräumen

Zwischen den Tests sollte man aufräumen können, ohne rebooten zu müssen:

ip netns list | while read ns; do
  ip netns pids $ns | xargs -r kill
  ip netns pids $ns | xargs -r kill -9
  ip netns del $ns
done

Wenn Namespaces gelöscht werden, verschwinden auch die zugehörigen Interfaces. Das klappt allerdings nicht, wenn es noch einen Prozess gibt, der dieses Interface geöffnet hat. Deswegen werden erst alle Prozesse, die diesen Namespace benutzen, freundlich aufgefordert, sich zu beenden. Anschließend werden den Unfolgsamen hart die Ressoucen entzogen. So kann der Namespace entfernt werden.

Damit man das regelmäßig machen kann liegen die Kommandos in drei Scripten:

  • testbed-on.sh
  • tests.sh
  • testbed-off.sh

Diese Scripte sind als Root auszuführen. Da die Entwicklung aber unter einen normalen Nutzer stattfindet, greife ich auf sudo zurück:

apt install sudo

Und nun geht's mit dem ersten Programm los.

Fehlkonfig as a Service

04/02/2026 10:11 am Lutz Donnerhacke Tags: Linux , BSD , Broadband , CPE 5

In die Netze von Internetprovidern speisen die Kunden alles ein, was nicht lokal abgehandelt wird. Gebraucht gekaufte IoT-Geräte, internen Traffic, der am Firmen-VPN vorbei leaked, etc. pp. Ein Großteil davon geht an private IPv4 Adressen, die grundsätzlich nicht erreichbar sind. Leider geben sich die meisten Geräte nicht mit Ablehnungen und Fehlermeldungen zufrieden, sondern bestehen auf einer Antwort. Und wenn sie dafür zig-Mal pro Sekunde anfragen müssen.

Catch All

Die Idee besteht nun darin, Anfragen an garantiert unzustellbare Adressen in einer Weise zu beantworten, dass die anfragenden Geräte zufrieden sind, aber keinen Schaden anrichten können. Gleichzeitig soll der – möglicherweise irritierte – Nutzer erkennen können, was da schief geht. Dazu wird zunächst eine Maschine aufgesetzt, die all den fehlerhaften Traffic abbekommt. Dazu wird der Traffic an nicht anderweitig bekannte, private IPs an diese Kiste geroutet:

(conf)# ip route 10.0.0.0/8 a.b.c.d
(conf)# ip route 172.16.0.0/12 a.b.c.d
(conf)# ip route 192.168.0.0/16 a.b.c.d

Warum nicht auch noch den Shared-IP-Space 100.64.0.0/10? Weil wir den selbst benutzen für die Masse der Endkunden.

Was kommt denn da so geflogen?

100.76.113.229.55323 > 192.168.40.12.389: Flags [S]
100.75.2.125.54724 > 192.168.121.1.20080: UDP
100.98.190.49 > 172.18.10.10: ICMP echo request
100.75.253.235.65019 > 10.3.76.152.389: Flags [S]
100.75.121.232.13564 > 10.10.10.3.18899: Flags [S]
100.75.196.34.63612 > 10.10.10.3.18899: Flags [S]
100.75.8.243.63753 > 10.1.7.20.53: 43789+ A? europe.smartscreen.microsoft.com. (50)
100.75.226.148.62734 > 10.10.10.3.18899: Flags [S]
100.74.166.72.59236 > 10.10.10.3.18899: Flags [S]
100.76.98.43.65100 > 192.168.2.200.22000: Flags [SEW]
100.75.177.69.51982 > 10.10.10.3.18899: Flags [S]

Da haben wir also Ping, LDAP (vermutlich Kontaktversuche in ein AD), DNS (natürlich), die Steuerkonsole für PV-Anlagen (what?) und verschiedene seltsame Ports. Und alles an wilde private Ziele.

Destination NAT

Um auf diese Anfragen reagieren zu können, müssen alle die Pakete auf die lokale Maschine umgeleitet werden. Und dann müssen die Antworten wieder so aussehen, als ob sie von dem eigentlich angefragten Servern stammen. Als lokale Adresse möchte ich die IP 127.0.0.2 auf einem zweiten Loopback oder Dummy-Interface benutzen.

FreeBSD

Nimmt man FreeBSD so gibt es die Implementationen: ipfw und pf. Beide beherrschen den das Umleitung von Pakten an ein anderes Ziel

ipfw add fwd 127.0.0.2 ip from any to 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 recv veth0
(pf) rdr pass inet from any to {10.0.0.0/8,172.16.0.0/12,192.168.0.0/16} -> 127.0.0.2

Wenn dann an dem betreffenden Port ein Dienst lauscht, so antwortet der und die Antwort geht von der lokalen IP wieder nach draußen:

100.79.236.62.42046 > 172.20.10.1.53: 40857*- ...
127.0.0.2.53 > 100.79.236.62.42046: 40857*- ...

Damit kann natürlich niemand etwas anfangen. Es müsst schon von der gleichen privaten IP eine Antwort kommen.

Aber wie? Mit NAT kann man die IP Adressen umschreiben, sich die Umschreibung merken und wieder zurück wandeln. Nur gibt es leider abertausende von möglichen Zielen, die zu natten wären. ipfw-NAT kennt redirect_address und akzeptiert dort auch den Spezialparameter 0.0.0.0.

ipfw nat 1 config if veth0 same_ports redirect_addr 127.0.0.2 0.0.0.0
ipfw add nat 1 from any to 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 recv veth0
ipfw add nat 1 from 127.0.0.2 to any xmit veth0

Der Traffic muss auf dem Hin- und auf dem Rückweg in die richtige NAT-Instanz geschoben werden, damit diese die richtigen Adressen umschreiben kann. In welche Richtung die NAT-Instanz arbeitet, hängt von der Richtung ab, in der das Paket das Interface passieren will. Es macht also einen Unterschied, auf welchem Interface man den Traffic zum NAT umleitet.

Unglücklicherweise funktioniert das aber überhaupt nicht. Es scheint daran zu liegen, dass die IP-Adressen auch aus einem reservierten Bereich stammen. Da scheint die Erkennung dessen, was zu tun ist, durcheinander zu kommen.

Linux

Also der Versuch mit Linux. Das alte iptables hat sich im Rahmen des Netfilter-Projektes weiter entwickelt:

flush ruleset

table ip fremdtraffic {
        chain catch {
                type nat hook prerouting priority dstnat; policy accept;
                ip daddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } counter dnat to 127.0.0.2
        }
}
table ip dienste {
        chain management {
                type filter hook input priority filter; policy accept;
                ip saddr m.g.m.t/net counter accept
                tcp dport { 22, ... } counter reject
        }
}

Die Tables sind Verwaltungs-Container, die man atomar einfügen, aktivieren und löschen kann. Sie gelten für einen bestimmte Art von Daten, hier IPv4.

Die Chains enthalten sequentiell abzuarbeitende Blöcke von Regeln gleicher Funktion (type) an der gleichen Eingriffstelle (hook). Endet ein Regel mit reject, wird das Paket verworfen. Endet eine Regel mit accept, geht's mit der nächsten Chain weiter. Nicht von Regeln erfasste Pakete bekommen die generelle Policy der Chain zu spüren.

Die Reihenfolge (priority) der Chains wirkt pro Eingriffstelle (hook). Haben zwei Chains die gleiche Priorität, ist es unbestimmt, welche Chain zuerst dran kommt.

Von dem o.g. Regelwerk bleibt also übrig:

  • Der Hook prerouting führt seine einzige Regel aus, indem er Pakete an private IPs auf die lokale IP umschreibt (und sich das merkt)
  • Der Hook input führt seine einzige Regel für lokal adressierten Traffic aus und filtert Zugriffe auf Management-Dienste aus, wenn sie nicht von dem zulässigen Managment-Netz stammen.
  • Auf dem Rückweg greift das Nat automatisch ein und übersetzt die Adressen wieder zurück

Aktuell existieren keine Dienste, aber der Kernel kann schon ein paar Dinge selbst:

100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
172.18.10.10 > 100.98.190.49: ICMP echo reply
172.18.10.10 > 100.98.190.49: ICMP echo reply
172.18.10.10 > 100.98.190.49: ICMP echo reply
172.18.10.10 > 100.98.190.49: ICMP echo reply
100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
100.98.190.49 > 172.18.10.10: ICMP echo request
172.18.10.10 > 100.98.190.49: ICMP echo reply
172.18.10.10 > 100.98.190.49: ICMP echo reply
172.18.10.10 > 100.98.190.49: ICMP echo reply

Sieht schon mal gut aus. Der Kernel hat ein Rate-Limit, beantwortet also nicht alle Anfragen.

100.75.121.212.57726 > 192.168.0.101.55443: Flags [S]
192.168.0.101.55443 > 100.75.121.212.57726: Flags [R.]
100.75.196.199.55444 > 192.168.1.166.55444: UDP
192.168.1.166 > 100.75.196.199: ICMP 192.168.1.166 udp port 55444 unreachable

Auch Anfragen an unbekannte Dienste werden korrekt beantwortet: Dienst nicht verfügbar.

Das sieht man dann auch an den Zählern:

 # nft list ruleset
table ip fremdtraffic {
        chain catch {
                type nat hook prerouting priority dstnat; policy accept;
                ip daddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } counter packets 2598458 bytes 166126098 dnat to 127.0.0.2
        }
}
table ip dienste {
        chain management {
                type filter hook input priority filter; policy accept;
                ip saddr m.g.m.t/net counter packets 1880 bytes 333471 accept
                tcp dport { 22, ... } counter packets 21572 bytes 1231360 reject
        }
}

Stellungnahme zum Referentenentwurf für ein „Gesetz zur Einführung einer Speicherpflicht für IP-Adressen und zur Anpassung weiterer digitaler Ermittlungsbefugnisse“

29/01/2026 11:21 pm Lutz Donnerhacke Tags: IPv6 , Internet , Politik , Datenschutz 9

Als Entwickler von Kommunikationslösungen und Dienstleister im Umfeld von Internet-Service-Providern bin ich mit den Realitäten der Internetversorgung für die typischen privaten Haushalte vertraut. Mir ist der Referentenentwurf erst vor wenigen Tagen zugegangen und ich möchte auf ein paar grundsätzliche Punkte in diesem Entwurf hinweisen. Dazu beschränke ich mich auf den Teil, der den Massenmarkt der Internetversorgung für Privatleute betrifft.

In der Begründung des Referentenentwurfes heißt es:

  • Nach dem Entwurf werden Internetzugangsdiensteanbieter erstens verpflichtet, für drei Monate die von ihnen an Endkunden vergebenen IP-Adressen und weitere Daten wie die Portnummer zu speichern, sofern dies für eine eindeutige Zuordnung der IP-Adresse zu einem Anschlussinhaber erforderlich ist. Dadurch können Strafverfolgungs- und Gefahrenabwehrbehörden anhand eines Zeitstempels, einer IP-Adresse und gegebenenfalls einer Portnummer die Bestandsdaten beim Internetzugangsdiensteanbieter abfragen, […]

Der Referentenentwurf sieht dazu insbesondere folgende Änderungen vor:

  • TKG §176 Speicherpflicht und Verwendungsbefugnis von Verkehrsdaten zur Identifizierung von Anschlussinhabern
    (1) Anbieter von Internetzugangsdiensten sind verpflichtet, mit der Zuweisung einer öffentlichen Internetprotokoll-Adresse an einen Anschlussinhaber folgende Daten für drei Monate zu speichern:
    1. die dem Anschlussinhaber für eine Internetverbindung zugewiesene, öffentliche Internetprotokoll-Adresse,
    2. eine eindeutige Kennung des Anschlusses, über den die Internetverbindung erfolgt, sowie eine zugewiesene Benutzerkennung,
    3. das Datum und die sekundengenaue Uhrzeit von Beginn und Ende der Zuweisung der öffentlichen Internetprotokoll-Adressen an einen Anschlussinhaber unter Angabe der jeweils zugrunde liegenden Zeitzone sowie
    4. die der Internetprotokoll-Adresse zugehörigen Portnummern und weitere Verkehrsdaten, soweit diese für eine Identifizierung des Anschlussinhabers anhand einer zu einem bestimmten Zeitpunkt zugewiesenen Internetprotokoll-Adresse erforderlich sind.
  • BKAG § 10b Sicherung von Verkehrsdaten
    (1) Zur Erfüllung der Aufgabe als Zentralstelle nach § 2 Absatz 1 kann das Bundeskriminalamt zum Zwecke einer etwaigen Erhebung gegenüber demjenigen, der öffentlich zugängliche Telekommunikationsdienste anbietet oder daran mitwirkt, anordnen, Verkehrsdaten gemäß § 3 Nummer 70 des Telekommunikationsgesetzes von betroffenen Personen unverzüglich zu sichern (Sicherungsanordnung), wenn die zuständige Strafverfolgungsbehörde oder die zuständige Polizeibehörde noch nicht erkennbar ist […]

Lassen Sie mich dazu einige Begrifflichkeiten aus den referenzierten Gesetzen zitieren:

  • TKG §3(6): Bestandsdaten Daten eines Endnutzers, die erforderlich sind für die Begründung, inhaltliche Ausgestaltung, Änderung oder Beendigung eines Vertragsverhältnisses über Telekommunikationsdienste
  • TKG §3(70): Verkehrsdaten Daten, deren Erhebung, Verarbeitung oder Nutzung bei der Erbringung eines Telekommunikationsdienstes erforderlich sind
  • BSIG §2(31): Protokolldaten Steuerdaten eines informationstechnischen Protokolls zur Datenübertragung, die a) zur Gewährleistung der Kommunikation zwischen Empfänger und Sender notwendig sind und b)  unabhängig vom Inhalt des Kommunikationsvorgangs übertragen oder auf den am Kommunikationsvorgang beteiligten Servern gespeichert werden
  • TDDDG §2(3) Nutzungsdaten die personenbezogenen Daten eines Nutzers von digitalen Diensten, deren Verarbeitung erforderlich ist, um die Inanspruchnahme von digitalen Diensten zu ermöglichen und abzurechnen; dazu gehören insbesondere a) Merkmale zur Identifikation des Nutzers, b)  Angaben über Beginn und Ende sowie über den Umfang der jeweiligen Nutzung und c) Angaben über die vom Nutzer in Anspruch genommenen digitalen Dienste

Die offenkundige Intention des Referentenentwurfs ist, aus Protokolldaten, die an einer bestimmten Stelle (z.B. einem bestimmte Daten bereitstellenden Server) erfasst wurden, einen Rückschluss auf den Kommunikationspartner (z.B. den PC eines Benutzers, der die Daten abruft) ziehen zu können. Wie die gesamte Gesetzeslage so atmet auch der Referentenentwurf die Idee der klassischen Telefonie: Es besteht die (irrige) Annahme, es gäbe eine direkte Kommunikationsverbindung zwischen zwei Teilnehmern, die man – dem Kabel folgend – finden kann. Da Internet-Protokolle i.d.R. tatsächlich eine Kommunikation zwischen zwei Endstellen abbilden, besteht die (irrige) Annahme, jede Gegenstelle sei bereits der Endpunkt der Kommunikation und damit einem Benutzer zuordenbar.

Der fundamentale Irrtum besteht im Glauben an das Prinzip der Ende-zu-Ende-Kommunikation. Dieses Prinzip wurde Mitte der 2000er Jahre durch fortschreitenden Mangel an IPv4 Adressen aufgegeben. Stattdessen entwickelte  sich das Privatkunden-Internet in drei Richtungen, die oft gleichzeitig angeboten werden:

  1. Kunden bekommen öffentliche IPv4-Adressen als Premiumprodukt
  2. Kunden bekommen öffentliche IPv6-Adressen
  3. Kunden bekommen nicht-öffentliche IPv4-Adressen zugewiesen und erreichen das Internet über Mittelboxen, die die Adressen umschreiben (Carrier Grade Network Address Translation – CGNAT)

Um aus den (entfernt erfassten) Protokolldaten auf die Bestandsdaten der (unbekannten) Gegenstelle schließen zu können, müssen die Verkehrsdaten beim ISP rechtzeitig abgefragt werden. Bisher gibt es keine Notwendigkeit für eine längere Speicherung der Verkehrsdaten beim ISP. Aktuell wird seitens der Datenschützer aber eine Frist von einigen Tagen zwecks Beseitigung von Betriebsstörungen toleriert. Dieses Zeitfenster soll der Referentenentwurf auf drei Monate ausdehnen.

Gestatten Sie mir zunächst eine Abschätzung der dabei anfallenden Datenmengen: Im Fall der Zuteilung von öffentlichen IP-Adressen an den Kunden bleibt diese Zuteilung meist mehrere Stunden stabil. Es genügt also zu erfassen, welcher Kunde wann welche Zuteilung für wie lange bekam. Die Datenmengen liegen dabei pro Kunde bei ca. 50 Byte pro Zuweisung (128bit Adresse, 64bit Zeitstempel, 64bit Kundenkennung plus weitere Metadaten). Bei durchschnittlich vier Änderungen pro Tag sind das 20kByte pro Kunde für drei Monate. Ein mittlerer ISP mit ca. 100000 Endkundenanschlüssen benötigt dafür also minimal 2 GByte Speicherplatz. In der Praxis wird die Art der Datenspeicherung das Zehnfache (plus Backup) benötigen.

Im Fall von (CG)NAT ist die Situation deutlich schwieriger. Viele Kunden mit nicht-öffentlichen IPv4-Adressen werden durch Mittelboxen auf wenige öffentliche IPv4-Adressen umgesetzt. Dabei werden die Portnummern der (TCP oder UDP)-Verbindungen umgeschrieben. Ein Verhältnis von 250 Kunden pro öffentliche IPv4-Adresse ist für einen mittleren ISP durchaus typisch. Als Faustformel gilt: Je mehr Kunden ein ISP hat, desto mehr Kunden teilen sich eine öffentliche NAT-IP.

Da nur ca. 64000 Port-Nummern (es gibt reservierte Bereiche) pro IPv4-Adresse zur Verfügung stehen, kann ein Kunde bei einer direkten Zuordnung der Portnummer zum Kunden (Cone-NAT) nur ca. 250 Ports benutzen. Offenbar hat der Referentenentwurf dieses Modell im Blick, wenn von der Erfassung der Portnummern zusammen mit der öffentlichen IPv4-Adresse gesprochen wird.

Leider ist Cone-NAT in der Praxis völlig unzureichend: Die meisten modernen Webseiten benötigen in schneller Folge mehrere hundert Verbindungen. Dazu kommen hunderte von DNS Anfragen. Eine Webseite wie z.B. Google Maps wird mit 250 freien Ports schlicht nicht vollständig aufgebaut. Bei vielen Social-Media Seiten fehlen dann Bilder oder andere Teile des Inhaltes. Eine Wiederverwendung der Port-Nummern ist insbesondere bei UDP Kommunikation schwierig, da es kein definiertes Ende der Kommunikation gibt. Der Port muss also über längere Zeit auf Verdacht mit diesem Kunden belegt bleiben.

Bei der Verwendung von Symmetric-NAT geht auch die Gegenstelle der Kommunikation mit ein. So stehen alle 64000 Ports einer öffentlichen IPv4-NAT-Adresse für jede Server-IP und jeden Server-Port (i.d.R. immer 443) zu Verfügung. Eine Anfrage welcher Nutzer hatte zum Zeitpunkt x die IP y mit Port z ist deswegen nicht beantwortbar. Es wird zusätzlich die Information die eine s-Verbindung mit Server a auf Port b hatte benötigt.

Man benötigt ca. 100 Byte pro Verbindung (3∙32bit IPv4, 3∙16bit Port, 16bit Protokoll, 64bit Zeitstempel, 64bit Kundenkennung plus Metadaten). Mit durchschnittlich einem Verbindungsaufbau pro Minute (über den Tag gerechnet, d.h. einige zig-tausend in kurzer Zeit und dann lange Pausen) bei Wenignutzern entstehen so 13 MByte pro Kunde für drei Monate. Ein mittlerer ISP wird also 2 TByte Verkehrsdaten verwalten müssen, die real sich auf 20 TByte Plattenplatz plus Backup ausdehnen.

Hat der ISP auch einige Poweruser (Familien mit Kindern reichen da schon), so kann man mit dem Mehrfachen an Platzbedarf rechnen. 10% der Nutzer machen jeder für sich so viele Verbindungen auf, wie der Rest aller Kunden zusammen, so dass der Platzbedarf um den Faktor 10 auf 200 TByte (plus Backup) anwächst.

Die Rechnung ist allerdings für normale Nutzung ohne besondere Vorkommnisse. Sollte ein(!) Nutzer Teil einer(!) dDOS-Attacke sein (z.B. durch ein(!) gekapertes IoT-Device), so generiert allein ein(!) solcher Vorgang ca. 1000 Verbindungsaufbauten pro Sekunde: Es entstehen hierbei 360 MByte pro Stunde an Verkehrsdaten für den einzelnen(!) Angriff.

Solche Angriffe passieren leider täglich und sind für die Strafverfolgung von hohem Interesse. Derartige explosionsartig anfallende Datenmengen sind also genau die Verkehrsdaten, auf die der Referentenentwurf abzielt. Deswegen ist es nicht möglich, in Anbetracht der Datenmenge eine Ausnahme für Angriffe von der Speicherpflicht zu machen, wenn der Referentenentwurf überhaupt nützlich sein soll.

Zusammenfassend kann man bei einem mittleren ISP also von ca. 500 TByte an Plattenplatz für die Speicherung von Verkehrsdaten beim Einsatz von CGNAT ausgehen. Backup kommt extra dazu, um im Falle einer Störung nicht die Daten der letzten Monate zu verlieren. Die zusätzlichen Anforderungen an einen mittleren ISP landen also im PByte Bereich, wenn dieser Referentenentwurf so realisiert würde.

Weiter heißt es in der Begründung des Referentenentwurfs:

  • Die Speicherpflicht betrifft zwar alle Nutzer von Internetzugangsdiensten in Deutschland. Allerdings lassen die Daten nichts anderes zu als die Identifizierung des Anschlussinhabers anhand einer IP-Adresse. Es handelt sich gerade nicht um eine Vorratsdatenspeicherung von allen Verkehrs- und Standortdaten. Aus den gespeicherten IP-Adressdaten lassen sich insbesondere keine Surf- oder Bewegungsprofile erstellen. Die Beeinträchtigung insbesondere der unbescholtenen Nutzer ist damit überschaubar.

Diese Aussagen sind bei NAT nicht haltbar. Da für die korrekte Zuordnung beide Seiten der Kommunikation bekannt sein müssen, handelt es sich bei der geplanten Speicherung von Verkehrsdaten um eine unzulässige Vorratsdatenspeicherung, die genaue Rückschlüsse über das Kommunikationsverhalten des Nutzers zulässt. Das betrifft nicht nur die genauen Zeiten der Kommunikation, sondern auch die Kenntnis der Kommunikationspartner, so dass ein genaues Surf- und Bewegungsprofil erstellt werden kann.

Abschließend gibt es also drei Möglichkeiten:

  1. Alle Referenzen auf Portnummern werden aus dem Referentenentwurf entfernt. Dies führt dazu, dass nur die Speicherfrist für die Zuordnung öffentlicher IP-Adressen erweitert wird. CGNAT-Nutzer werden dann nicht erfasst. Dies entspricht einer graduellen Ausweitung der aktuellen Rechtslage.
  2. Der Einsatz von CGNAT wird verboten. Da es nicht genügend IPv4 Adressen für alle Kunden gibt, wird die Anzahl der Internetanschlüsse für Haushalte beschränkt.
  3. Die verpflichtende Umsetzung des RFC 6540 für die deutschen ISPs wird eingefordert: Mit dem Wechsel auf IPv6 only besteht kein Bedarf mehr an NAT. Die Umsetzung des RFC muss deswegen gesetzlich verpflichtend sein, damit die ISPs sich nicht in einem ruinösen Wettbewerb für legacy IPv4-Nutzer gegenseitig kaputt machen. Während der Übergangszeit bleibt es bei Möglichkeit 1 für Bestandsverträge. Neuverträge sind ab einem Stichtag generell nur noch IPv6 only.

Danke für Ihr Interesse.

Datenfluss visualisiert

24/09/2018 4:41 pm Lutz Donnerhacke Tags: Internet , Dokumentation 3

Wenn ein ISP über seine Außenanbindungen Traffic schaufelt, dann ist es oft Glückssache, welches Leitung wieviel Daten abbekommt. Natürlich wird man gezielt versuchen einige Teilnetze nur auf einigen bestimmten Upstreams zu announcieren, damit genau dort der Traffic auch rein kommt. Aber das Finetuning ist sehr schwer. Man müßte ziemlich genau wissen, welcher Datenstrom zu welcher Zeit auf welchem Weg durchläuft, um die Änderung planen zu können.

Details bitte

Kürzlich hatte ich über Netflow geschrieben. Dort wurden die Datenströme nach Quell- und Ziel-AS summiert. jetzt will ich es detaillierter haben.

Weiterhin benötigt werden nun:

  • Der Router, der die Daten einsammelt.
  • Das Peer-ASN mit dem der Router direkt redet.
  • Der Netzblock, der im globalen Routing auftauchen wird.
  • Und der Schönheit wegen, der lokale Dienst, der den Traffic abbekommt oder initiiert.

Um nicht sämtliche IP Adressen als relevant ansehen zu müssen, definiere ich mir einen neuen Flow pro Richtung:

flow record in
 match routing source as 4-octet
 match routing source as peer 4-octet
 match routing destination as 4-octet
 match ipv4 destination address
 match ipv6 destination address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
flow record out
 match routing source as 4-octet
 match routing destination as 4-octet
 match routing destination as peer 4-octet
 match ipv4 source address
 match ipv6 source address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long

Zusätzlich zu den Quell- und Ziel-ASNs nehme ich nun auch noch das Peer-ASN und die Quell- oder Ziel-IP dazu.

So beschränke ich mich auf die IP-Adressen im lokalen Netz (oder halt Transit) und aggregiere auf dem Router schon über die unbekannten externen IPs. Es wäre denkbar, auch IP-Prefixe statt der Adresse zu nehmen, aber ich habe Routing-Objekte, die kleiner sind als einige Prefixe. Also bleibt es bei den Adressen.

IPv4 und IPv6 sind zusammengefaßt, eine von beiden Werten wird schon relevant sein.

Als erste Überraschung präsentiert mir die Ausgabe Peer-ASN an Routern, die gar keine direkte Verbindung zu diesem AS haben!

Es stellt sich heraus, daß das Peer-AS ein abgeleiteter Wert ist, der durch ein Blick in die Routing-Tabelle ermittelt wird. Es zeigt also immer auf das Peer-AS, das der Router genommen hätte, wenn er das Paket jetzt in diese Richtung routen müßte.

Logischerweise ist also das Source-Peer-ASN i.d.R. falsch. Aber auch das Destination-Peer-ASN kann falsch sein, wenn es mehrere gleichberechtigte Wege gibt. Es ist durchaus möglich, das Pakete zum Peer 1 zu schicken und Peer 2 im Netflow zu hinterlegen.

Also stelle ich erstmal auf incoming und outgoing Interface um. Unglücklicherweise kann der Netflow-Collector überhaupt nicht damit umgehen, nur ein Interface zu bekommen. In der Annahme es gäbe beide Interfaces im Flow werden einfach die nächsten zwei Byte nach dem ersten Interface als das fehlende Interface angesehen. Alle anderen Felder werden danach mit einem Offset von zwei völlig fehlerhaft geparst. Also bekommt der Collector seinen Willen und das fehlende Interface (aber nur collected).

flow record in
 match routing source as 4-octet
 match routing destination as 4-octet
 match interface input
 match ipv4 destination address
 match ipv6 destination address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
 collect interface output
flow record out
 match routing source as 4-octet
 match routing destination as 4-octet
 match ipv4 source address
 match ipv6 source address
 match interface output
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
 collect interface input

Achja, die Router-IP. Der nfcapd hat mehrere Module, die man getrennt aktivieren muß. Das Modul 13 schreibt die IP-Adresse des Netflow-Sensors (des Routers) mit.

Damit sind die Werte erst einmal erfaßt.

Mach mal bunt

Da mich aktuell nur IPv4 interessiert genügt es für die Auswertung sich darauf zu konzentrieren:

nfdump -r ... -q -N -A srcip4/26,srcas,inif,router,outif,dstas,dstip4/26 -O bps

Dieses Kommando aggregiert auf Basis von /26er Netzen, für die ich händisch im Auswertescript hinterlegt habe, welches Routing-Object und welcher Zweck gemeint sind.

Das Script schreibt die aggregierten Daten alle fünf Minuten in ein Logfile. Es ersetzt dabei die Interfaces pro Router mit den Peer-AS-Werten anhand einer manuellen Zuordnungstabelle.

Das Script versucht des weiteren, Flows von Transit-Traffic korrekt zuzuordnen. Wenn Quell- und Ziel-ASN ungleich Null sind, habe ich Transit.

Sind auf einem Router Quell- und Ziel-Interface einem Peer zugeordnet ist es einfach, wenn nicht muß man den eingehenden Flow einem Ausgehenden zuordnen, der die gleichen Quell- und Ziel-ASNs aufweist. Dabei kann es passieren, daß der Traffic aufspaltet. In dem Fall entnehme ich das Minimum an übereinstimmenden Traffic und ordne den Rest solange weiter zu, bis der Resttraffic unter der Nachweisgrenze verschwindet.

Im Ergebnis entstehen Einträge der Form:

DHCP 91.137.60.0/22 rudo5 8220 other 94
2906 8220 rudo5 178.19.237.0/24 NAT 86
other 196714 rudo7 178.19.228.0/22 NAT 85
2906 8220 rudo8 rudo6 196714 196714 83

Der Flow ist von links nach rechts zu lesen und die letzte Zahl ist der Traffic in Mbps.

Aus diesen Angaben generiert sich mit Javascript ein SVG.

SVG deswegen, weil es interaktiv ist:

  • Man kann die Daten in fünf-Minuten-Schritten auswählen.
  • Fährt man mit der Maus über eine Kurve, so wird diese hervorgehoben und der Eintrag erscheint als Tooltip.
  • Fährt man mit der Maus über ein Rechteck (Router, Peer, Netz, ...) werden alle durchlaufenden Kurven hervorgehoben und man bekommt die Summenbandbreite als Tooltip.
2018-09-24-163642_1280x1024_scrot

Grün ist eingehender Traffic, blau ausgehender und rot ist Transit. Die Dicke der Linie und die Größe der Rechtecke geht linear mit dem Traffic. Router und Peers haben die Größe der maximalen Kapazität. so sieht man den Auslastungsstand.

Mit dieser Darstellung kann ich nachträglich mir anschauen, was zu bestimmten Stoßzeiten im Netz los war. Ich sehe, welche Routing-Objekte evtl. besser über einen anderen Upstream announciert werden könnten. Auf diese Weise kann ich sehr fein abstimmen, wieviel Traffic auf welcher Leitung herein kommt und muß erst wesentlich später neue Bandbreite zukaufen.

Das Aggregationsschema führt allerdings auch in die Irre. Es ist nicht unterscheidbar, ob es 5000 Flows mit 1 Mbps gab oder 10 Flows mit 500 Mbps: Angezeigt werden 5 Gbps. Das fiel auch erst spät auf, als ein Scan über alle IP Adressen trotz nur wenig Mbps sich zu einem gewaltigen Strom aufplusterte. Aber damit muß man aktuell leben.

Performance Probleme mit NAT

26/07/2018 5:44 pm Lutz Donnerhacke Tags: BSD 0

Nach dem Wechsel auf neuere Hardware (10G) und damit verbunden auch auf den aktuellsten Softwarestand von FreeBSD haben die NAT Kisten sporadisch massive Probleme. Ein glücklicher Zufall gestattete zuerst die Diagnose und dann die Lösung des Problems. CPU Last fällt von 90% (pro Prozeß) auf einstellige Werte.

Spikes

Immer wieder kommt es auf einer NAT Kiste zu akuten Performance-Problemen. Dabei bricht der maximal erreichbare Durchsatz pro TCP-Session auf unter 10Mbps zusammen. Oft ist der Gesamtdurchsatz des Systems auf knapp 200Mbps begrenzt, obwohl da drei mal 10G anstecken. (Für den Anschluß des vierten Interfaces fehlt aktuell ein Rack.)

Im CPU Graphen schaut das dann so aus.

stats-thread-peak

Um kurz nach 18 Uhr hatte die betreffende Maschine ein Lastproblem. Allerdings war es schon nach wenigen Minuten wieder weg.

In den meisten Fällen bisher waren die Lastspitzen noch deutlich kürzer, so daß man sie in diesem Graphen nicht mal richtig sieht.

Da allerdings das Problem nur sporadisch auftritt, nicht reproduzierbar ist, und die Beeinträchtigung der Kunden auch nicht lange genug anhält, um zu spezifischen Störungsmeldungen zu führen, war bisher eine Fehlersuche ergebnislos.

Glückliche Zufälle

Gestern erst hatte ich im Zusammenhang mit FreeBSD ein WTF-Erlebnis, das mit NAT zusammenhängt.

Und heute zeigte eine Maschine erstmals einen stabilen Fehlerzustand.

stats-thread-bummer

Wow, was für ein gewaltiger Vorfall! Endlich mal Zeit zum Debuggen.

Mit dem Hintergedanken des gestrigen Erlebnisses im Kopf fiel irgendwann in einem glücklichen Mitschnitt auf, daß es Pakete gibt, bei denen Quell- und Ziel-IP gleich sind. Noch dazu sind diese IPs auch die öffentlichen IPs des NAT.

Ganz offensichtlich kommt es vor, daß irgendein kruder Netzscanner Pakete schickt, die das NAT als gültig ansieht und nattet. Dabei entstehen Pakete, bei denen Quell- und Ziel-IP gleich sind. Und diese landen dann wieder beim NAT. Dabei entstehen Pakete, bei denen Quell- und Ziel-IP gleich sind. Und diese landen dann wieder beim NAT. Dabei entstehen Pakete, bei denen Quell- und Ziel-IP gleich sind. Und diese landen dann wieder beim NAT. Ähm, das Prinzip sollte klar sein.

Also kurz eine Firewallregel hinzugefügt, die Pakete von NAT-IPs an NAT-IPs verwirft.

Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny UDP 178.19.233.4:63647 178.19.233.4:57691 in via vlan94
Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny UDP 178.19.233.4:64584 178.19.233.4:57691 in via vlan94
Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny TCP 91.137.21.7:42512 91.137.21.7:3888 in via vlan94
Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny UDP 178.19.233.4:62012 178.19.233.4:49655 in via vlan94
Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny UDP 178.19.233.4:6763 178.19.233.4:57691 in via vlan94
Jul 26 17:13:37 server12 kernel: ipfw: 2 Deny TCP 91.137.17.4:14938 91.137.17.4:64906 in via vlan94

Und schon fällt die CPU Last der Netzwerk-Interrupts auf einstellige Prozentzahlen.

Fazit

Ursächlich für den Vorfall ist ein Wechsel von quagga zu bird.

Früher mußten die einzelnen NAT-IPs lokal geroutet werden, nun genügt es, die betreffenden Netze im OSPF zu announcen und sie per ipfw auf den Uplinkports abzugreifen. Eine lokale Route gibt es also nicht mehr.

Sollten solche Pakete trotzdem lokal erzeugt werden, verlassen sie das Gerät und kommen vom nächsten Router wieder zurück. Dabei werden sie wieder dem NAT vorgeworfen.

Es ist zwei glücklichen Zufällen zu verdanken, dieses Problem überhaupt finden zu können: Weil es lange genug andauerte und das betreffende Muster gerade frisch bekannt war.

Und nun können die Kisten endlich mal richtig Last aufnehmen. Ich bin gespannt.

Wenn der Traceroute Kreise tanzt

25/07/2018 1:24 pm Lutz Donnerhacke Tags: WTF , BSD 0

Manchmal überrascht einen eine Trivialität. Ich wollte das Routing einer Server-IP prüfen, aber der Trace wurde zu mir zurück reflektiert. Wie geht das?

Wunder

traceroute to 178.19.224.48 (178.19.224.48), 30 hops max, 40 byte packets
 1  switch1-9-4-1-vl52.net.iks-jena.de (217.17.197.11)  1.470 ms  1.372 ms  1.304 ms
 2  turm1-g001.net.iks-jena.de (217.17.197.49)  0.382 ms  0.438 ms  0.363 ms
 3  rudo8-t001-116.net.encoline.de (5.102.160.98)  0.613 ms  0.574 ms  0.566 ms
 4  switch3-v93.net.encoline.de (5.102.160.161)  1.465 ms  1.141 ms  1.170 ms
 5  server16-vlan58.net.encoline.de (5.102.160.132)  0.567 ms  0.538 ms  0.541 ms
 6  switch4-v94.net.encoline.de (5.102.160.178)  2.181 ms  1.469 ms  1.686 ms
 7  server16-vlan94.net.encoline.de (5.102.160.185)  0.641 ms  0.635 ms  0.575 ms
 8  switch2-v58.net.encoline.de (5.102.160.129)  9.887 ms  3.478 ms  1.380 ms
 9  rudo7-t000-123.net.encoline.de (5.102.160.90)  0.879 ms  0.740 ms  0.721 ms
10  turm1-g001-116.net.iks-jena.de (5.102.160.99)  0.991 ms  0.942 ms  1.012 ms
11  * * *
12  nat-178-19-224-48.net.encoline.de (178.19.224.48)  1.123 ms  1.052 ms  1.025 ms

Der Trace geht raus, kehrt um, kommt zurück und am Ende meint er das Ziel erreicht zu haben.

Dabei trifft er sogar bestimmte Router mehrfach. Das ist deswegen verwunderlich, weil doch die Router ihre Entscheidung allein anhand der Zieladresse fällen. Wie kann also das Paket in verschiedene Richtungen geroutet werden?

Zunächst erst einmal handelt es sich nicht um ein lokales Phänomen, sondern es funktioniert auch von anderen Quellen aus.

traceroute to 178.19.224.48 (178.19.224.48), 30 hops max, 60 byte packets
...
 4  inexio2.gw.network.manitu.net (89.238.127.62)  4.593 ms  4.594 ms  4.592 ms
 5  209-096-244-077.ip-addr.inexio.net (77.244.96.209)  7.633 ms  7.634 ms  7.642 ms
 6  DE-CIX1.de.lambdanet.net (80.81.193.74)  7.605 ms  7.358 ms  6.739 ms
 7  ae2.irt2.fra25.de.as13237.net (217.71.96.45)  7.881 ms  7.878 ms  7.584 ms
 8  ae5.irt1.han87.de.as13237.net (217.71.96.30)  13.407 ms  13.380 ms  13.390 ms
 9  ae7.irt1.ber02.de.as13237.net (217.71.96.133)  16.610 ms  16.613 ms  16.607 ms
10  bb-erf-02-loc.netz.netkom-line.net (109.73.31.198)  213.352 ms  213.364 ms  213.361 ms
11  tnk-ilm-001-loc.netz.netkom-line.net (109.73.31.195)  22.149 ms  20.946 ms  20.579 ms
12  109.73.31.141 (109.73.31.141)  147.983 ms  147.987 ms  147.974 ms
13  tnk-jen-001-loc.netz.netkom-line.net (109.73.31.193)  19.504 ms  19.453 ms  19.471 ms
14  tnk-jen-001-ipt.netz.netkom-line.net (109.73.31.194)  19.468 ms  19.468 ms  19.467 ms
15  rudo7-t010.net.encoline.de (5.102.160.105)  33.994 ms  34.003 ms  34.002 ms
16  switch2-v123.net.encoline.de (5.102.160.91)  34.350 ms  34.407 ms  34.573 ms
17  server16-vlan58.net.encoline.de (5.102.160.132)  33.875 ms  33.879 ms  33.866 ms
18  switch4-v94.net.encoline.de (5.102.160.178)  34.753 ms  35.605 ms  35.596 ms
19  server16-vlan94.net.encoline.de (5.102.160.185)  34.362 ms  34.259 ms  34.179 ms
20  switch2-v58.net.encoline.de (5.102.160.129)  34.800 ms  35.279 ms  34.905 ms
21  rudo7-t000-123.net.encoline.de (5.102.160.90)  34.440 ms  34.203 ms  34.452 ms
22  rudo5-t001-123.net.encoline.de (5.102.160.89)  34.228 ms  34.449 ms  34.435 ms
23  ar2.ber.de.colt.net (213.61.70.177)  55.706 ms  55.705 ms  55.674 ms
24  212.36.135.22 (212.36.135.22)  55.909 ms  56.438 ms  56.417 ms
25  212.36.135.22 (212.36.135.22)  55.398 ms  55.416 ms  55.389 ms
26  * * *
27  * * *
28  * * *
29  nat-178-19-224-48.net.encoline.de (178.19.224.48)  68.590 ms  68.544 ms  68.691 ms

Wow. Hin- und Rückrouting in einem Trace! Man sieht sehr schön den asymmetrischen Rouingweg.

Aber was passiert da?

Schnüffeln

Die Ursache sollte ausschließlich am angesprochenen Server zu suchen sein. Alles andere wäre eine grobe Überraschung, denn dann müßten die Geräte im Transportweg irgendeine Manipulation vorgenommen haben.

Also ein Mitschnitt auf den Außeninterfaces des betroffenen Servers aktiviert:

13:39:51.074580 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 13, length 20
13:39:51.074601 IP 5.102.160.132 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.077408 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 14, length 20
13:39:51.077414 IP 5.102.160.132 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.077939 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 15, length 20
13:39:51.077944 IP 5.102.160.132 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.078590 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 16, length 20
13:39:51.079237 IP 5.102.160.178 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.082388 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 17, length 20
13:39:51.084253 IP 5.102.160.178 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.084855 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 18, length 20
13:39:51.088146 IP 5.102.160.178 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.088802 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 19, length 20
13:39:51.088848 IP 5.102.160.185 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.092134 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 20, length 20
13:39:51.092176 IP 5.102.160.185 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.092892 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 21, length 20
13:39:51.092934 IP 5.102.160.185 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.093756 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 22, length 20
13:39:51.093774 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 22, length 20
13:39:51.097201 IP 5.102.160.129 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.100803 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 23, length 20
13:39:51.100823 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 23, length 20
13:39:51.101499 IP 5.102.160.129 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.102261 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 24, length 20
13:39:51.102280 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 24, length 20
13:39:51.102924 IP 5.102.160.129 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.103742 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 25, length 20
13:39:51.103763 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 25, length 20
13:39:51.103870 IP 5.102.160.90 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.106558 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 26, length 20
13:39:51.106577 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 26, length 20
13:39:51.106687 IP 5.102.160.90 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.107389 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 27, length 20
13:39:51.107408 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 27, length 20
13:39:51.107510 IP 5.102.160.90 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.108284 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 28, length 20
13:39:51.108302 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 28, length 20
13:39:51.108652 IP 5.102.160.99 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.111847 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 29, length 20
13:39:51.111866 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 29, length 20
13:39:51.112220 IP 5.102.160.99 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.113013 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 30, length 20
13:39:51.113032 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 30, length 20
13:39:51.113386 IP 5.102.160.99 > 217.17.192.34: ICMP time exceeded in-transit, length 36
13:39:51.114062 IP 217.17.192.34 > 178.19.224.48: ICMP echo request, id 60099, seq 31, length 20
13:39:51.114080 IP 178.19.224.48 > 217.17.192.34: ICMP echo request, id 60099, seq 31, length 20
13:39:51.115606 IP 217.17.197.43 > 217.17.192.34: ICMP time exceeded in-transit, length 36

Man sieht sehr schön, wie anfangs die Echo-Pakete mit einem Timeout beantwortet werden.

Kurz darauf (ab Sequenznummer 22) tauchen plötzlich Echo-Pakete auf, bei denen Quell- und Ziel-Adresse vertauscht sind. Diese entstehen offenbar direkt nach dem Eingang des ersten Paketes.

Nun dient die Kiste ein (Carrier Grade)-NAT. Ihr Zweck ist es also Pakete umzuschreiben und zwar so, daß möglichst wenig Pakete verloren gehen. Schließlich dient NAT ja dazu, Verbindungen zu ermöglichen! Eine Firewall oder Paketfilter würde Pakete verwerfen. NAT dagegen muß so gut wie möglich raten, wo das Paket eigentlich hin soll.

In diesem Fall geht das NAT systematisch vor:

  • Es nattet die fremde Quell-Adresse auf die eigene öffentliche IP.
  • Und es nattet die eigene öffentliche Ziel-IP zu – tja wohin, achja, da ist ja ein ganz frischer Eintrag in der NAT Tabelle …

Fertig ist der Spiegel.

Gefährlich?

Kann man das mit allen Protokollen machen? Wenn ja, könnte man trivial unter falscher Flagge segeln, oder?

Tracing the path to 178.19.224.48 on TCP port 80, 30 hops max
 1  switch1-9-4-1-vl4.net.iks-jena.de (217.17.192.125)  6.742 ms  2.125 ms  1.139 ms
 2  turm2-g001-5.net.iks-jena.de (217.17.197.50)  0.228 ms
    turm1-g001.net.iks-jena.de (217.17.197.49)  0.350 ms
    turm2-g000-3.net.iks-jena.de (217.17.197.34)  0.265 ms
 3  rudo8-t001-116.net.encoline.de (5.102.160.98)  0.449 ms  0.468 ms  0.423 ms
 4  switch3-v93.net.encoline.de (5.102.160.161)  1.414 ms  1.570 ms  2.359 ms
 5  server16-vlan58.net.encoline.de (5.102.160.132)  0.489 ms  0.431 ms  0.418 ms
 6  switch4-v94.net.encoline.de (5.102.160.178)  1.443 ms  1.166 ms  1.921 ms
 7  server16-vlan94.net.encoline.de (5.102.160.185)  0.429 ms  0.473 ms  0.444 ms
 8  switch4-v94.net.encoline.de (5.102.160.178)  14.355 ms  2.695 ms  1.462 ms
 9  server16-vlan94.net.encoline.de (5.102.160.185)  0.473 ms  0.495 ms  0.465 ms
...

Nein, man kann nicht. Und das ist gut so™.

ASA Konfigs auf Konsistenz prüfen

11/01/2018 11:25 am Lutz Donnerhacke Tags: IPv6 , Cisco , Sicherheit , Dokumentation 0

Wir haben eine Reihe von ASAs im Einsatz, die auf Kundenwunsch gepflegt werden. Wie immer betreffen Änderungswünsche nur die Einrichtung von Freischaltungen, aber nie das Wegräumen von Altlasten. Für diesen Fall gibt es zwei Tools, die ich vorstellen möchte.

Information des Kunden

Zunächst ist es wichtig, den Kunden regelmäßig über die aktuelle Konfiguration zu informieren. Trivialerweise würde man ihm die Konfiguration zugänglich machen.

Aber das ist eine schlechte Idee, da die ASAs einiges an Konfiguration enthalten, die man nicht ständig durch die Gegend reichen möchte. Es gibt auch genug Fälle, wo eine ASA mehrere Kunden bedient (z.B. mehrere Hosting-VLANs). Dann darf natürlich keine Information über die Konfiguration für andere Kunden leaken.

Es ist also notwendig, sich auf die wesentlichen und interessanten Teile zu beschränken. In diesem Fall interessiert den Kunden, welche ACLs und welche NAT Regeln für ihn aktiv sind. Was den Kunden interessiert, hängt von den Interfaces ab, die ihm zugeordnet sind.

Das Script mkacl-from-asaconfig.pl liest auf Standardeingabe eine komplette abgespeicherte ASA-Konfig ein, erwartet als Argument die Liste der interessanten Interfaces (nameif) und gibt aus:

  • die den Interfaces zugeordneten access-groupKommandos
  • die den access-group zugeordneten access-list Einträge
  • die den Interfaces zugeordneten nat Kommandos
  • die dabei referenzierten object-group Definitionen
  • die dabei referenzierten object Definitionen

Ganz praktisch sieht das dann so aus:

$ zcat /archiv/cf.asa.20180111.gz | mkacl-from-asaconfig.pl iks-lab
: Written by enable_15 at 11:13:55.766 CET Thu Jan 11 2018
!
!!!!!!
! active ACLs at interfaces
!!!!!
access-group to_lab out interface iks-lab
!!!!!
! ACLs
!!!!!
access-list to_lab extended permit ip object-group iks any 
access-list to_lab extended permit tcp any object obj-lab1 object-group http_s 
access-list to_lab extended permit tcp any object obj-lab2 object-group http_s 
!
!!!!!!
! extra NATs
!!!!!
!!!!!
! Object groups
!!!!!
object-group network iks
 network-object object o4-iks
 network-object object o6-iks
!
object-group service http_s tcp
 port-object eq www
 port-object eq https
!
!!!!!
! Objects
!!!!!
object network obj-lab1
 host 192.168.91.10
 nat (iks-lab,outside) static o4-lab1-public
!
object network obj-lab2
 host 192.168.91.11
 nat (iks-lab,outside) static o4-lab2-public
!
...
!
!!!!!
! Generated at Thu, 11 Jan 2018 13:35:03 +0100

Diese Auszüge können dem Kunden auf definiertem Wege (z.B. Kundenportal) zur Verfügung gestellt werden.

Es gestattet dem Kunden, sich selbst die aktuelle Konfiguration anzusehen und entlastet die Hotline bei uns.

Inkonsistenzen

Ein ganz anderer Teil des Problem sind Inkonsistenzen und Altlasten. Die Definition eines Objektes, das nicht verwendet wird, ist eine Inkonsistenz. Die Verwendung einer IP Adresse, die nicht mehr in Benutzung ist, ist eine Altlast. Beides soll gefunden werden.

Wie eine Konfiguration auszusehen hat, ist selbstverständlich Ansichtssache. Bei uns hat es sich als günstig herausgestellt, sämtliche IP Adressen in Objekten und Objektgruppen zu sammeln, damit diese schon allein anhand ihrer Benennung oder description auch noch Jahre später zugeordnet werden können. Nur mit klarer Zuordnung ist ein späterer Rückbau überhaupt möglich.

Das Script clean-asa-config.pl liest von der Standardeingabe eine komplette Konfigurationsdatei und listet auf, was unstimmig erscheint:

  • Nicht mehr benutzte access-list, object, object-group. name, tunnel-group, class-map, transform-set, crypto map, ...
  • Elemente, die verwendet werden, aber nicht definiert wurden, werden aufgelistet.
  • Es wird das Anlegen von object oder name Definitionen empfohlen, wenn IPs direkt in der Konfiguration stehen.
  • Ist bei Objekten ein DNS-Name zur IP hinterlegt, so wird geprüft, ob der Name noch zu dieser IP auflöst. Es ist nicht empfehlenswert, direkt mit fqdn statt host zu arbeiten, wenn man feststellen will, ob die intendierte Eintragung noch korrekt ist. fqdn sollte man nur bei dynamischen IPs benutzen.
  • Bei name Definitionen wird geprüft, oben IP und Name noch per DNS zusammen passen.
  • Da name Definitionen agnostisch gegenüber der Protokollfamilie sind, wird für IPv4 ein trailing dot am Namen empfohlen, bei IPv6 nicht.
  • Ausgelaufene Zertifikate führen zur Empfehlung, den trust-point zu löschen.
  • Ebenso soll man unvollständige crypto map Einträge löschen.

Die Ausgabe enthält:

  • die Empfehlung incl, Begründung
  • die direkt ausführbaren Kommandos, um die Empfehlung umzusetzen, ohne den Betrieb zu gefährden
  • alle anderen Verwendungen des Namens oder der IP in der Konfiguration

Wenn Euch etwas auffällt, was man noch testen sollte oder könnte ...

ASA mit mehrfacher Default Route

29/11/2017 4:28 pm Lutz Donnerhacke Tags: Cisco , WTF 0

Eine Appliance, die in einer fremden Umgebung Daten einsammelt, soll von extern angesprochen werden. Zum einen muss der Hersteller Fernwartung machen und zum anderen gibt es eine Gruppe von Stellen, die auf die gesammelten Daten zugreifen sollen. Völlig unerwartet wird das geschützte Netzwerk dieser Stellen ebenfalls mit öffentlichen IP Adressen betrieben, so dass für beide Zwecke eine Default Route benötigt wird. Das Ganze soll trotzdem nur mit einer ASA funktionieren. Eine Aufsplittung in mehrere Kontexte (ASA-Virtualisierung) scheitert am fehlenden Support für Remote-Access. Es muss also anders gehen.

Aufgabenstellung

Die Appliance arbeitet in einem anderen, größeren Netzwerk und benutzt selbst nur private IP Adressen (hier 192.0.2.x). Um alle Messstellen erreichen zu können, zeigt die Default Route dieses Gerätes in das fremde Netzwerk (hier grau).

Der Remote-Access Teil (hier grün) ist ein einfaches Setup. Um die vorab unbekannten Clients erreichen zu können, muss die Default Route ins Internet zeigen. Dieser Uplink der ASA benutzt öffentliche IPs (PA-space, hier 189.51.100.x). Die Remote-Access Clients bekommen aus einem Adresspool des lokalen Netzes IPs, so dass sie ohne weiteres Routing auf die Appliance zugreifen können. Von Seiten der Appliance aus erscheint der Client im LAN.

Die ursprüngliche Annahme war, dass die abfragenden Stellen, die über ein extra gesichertes Netzwerk zugeführt werden, ebenfalls in koordinierter Weise mit nicht-öffentlichen Adressen arbeiten würden. In diesem Fall hätte eine spezifische Route zu all diesen Netzen genügt. Allerdings haben die Planer dieses Netzes den Koordinationsaufwand gescheut und verlangen stattdessen, öffentliche IP-Adressen aus dem lokalen PA-Space zu benutzen, der auch normal über Internet erreichbar ist.

ASA multiple default routes

Die Gegenstellen hinter dem geschützten Netzwerk (hier rot) sind vorab ebenso wenig bekannt, wie die Fernwartungs-Clients (grün). In dem hier skizzierten Bild, soll eine solche Gegenstelle eine ganz andere öffentliche IP Adresse haben (hier 203.0.113.133). Um solche Adressen zu erreichen, müsste eine Default Route ins rote Netz gesetzt werden.

Angefasst werden darf nur die ASA, alle anderen Geräte unterliegen fremder Verfügungsgewalt.

Remote-Access

Die Konfiguration für das Remote-Access VPN gemäß Lehrbuch:

interface Ethernet0/0
 nameif green
 security-level 0
 ip address 198.51.100.25 255.255.255.192
!
interface Ethernet0/1
 nameif gray
 security-level 100
 ip address 192.0.2.5 255.255.255.0
!
route green 0.0.0.0 0.0.0.0 198.51.100.1 1
!
ip local pool vpnippool 192.0.2.101-192.0.2.102 mask 255.255.255.0
!
crypto map vpn_outside 999 ipsec-isakmp dynamic vpn_dyn
crypto map vpn_outside interface green
...

Erwartungsgemäß tut das seinen Dienst:

  • Der entfernte Supportmitarbeiter kann per Default Route erreicht werden.
  • Der entfernte Supportmitarbeiter bekommt über das VPN eine IP aus dem inside-LAN.
  • Die Appliance redet mit ihm über das lokale Netzwerk. Extra Routen werden nicht benötigt.

Einmal hin ...

Um die Stellen, die mit öffentlichen IP Adressen aus dem geschützten Netz kommen, versorgen zu können, sind einige Überlegungen notwendig.

Zuerst fällt auf, dass der Verbindungsaufbau bei unbekannten Gegenstellen nur von extern kommen kann. Die Clients werden ausschließlich eine öffentliche IP au dem Netz 198.51.100.248/29 zugreifen können. Von dem privaten Netz hinter der ASA wissen sie nichts.

Damit die Appliance nichts von den fremden Adressen merkt, braucht es eine Doppel-NAT:

interface Ethernet0/2
 nameif red
 security-level 0
 ip address 198.51.100.254 255.255.255.248
!
object network o-server
 host 192.0.2.4
!
nat (red,green) source dynamic any interface destination static interface o-server

Eingehende Pakete über das rote Interface von beliebiger Quelle an die Interface-IP werden so genanntet, dass die Quell-IP zur grünen Interface-Adresse und die Zieladresse, die der Appliance wird. Damit sieht die Appliance nur Anfragen aus ihrem LAN.

Um zu testen, dass diese Idee auch tut, wird ein Testaufbau erstellt:

ASA multiple default routes Test

Anstelle des roten Netzwerkes, steht ein Linux-Rechner, den man passend konfiguriert:

# ip addr add 198.51.100.254/29 dev eth_rot
# ip addr show eth_rot
1: eth_rot: <BROADCAST,MULTICAST,UP,10000>
    inet 198.51.100.254/29 scope global eth_rot
       valid_lft forever preferred_lft forever 

Zusätzlich bekommt er die fremde IP Adresse. Damit er diese auch als Quelladresse benutzt, gibt es eine spezielle extra Route:

# ip addr add 203.0.113.133/32 dev lo
# ip route add 198.51.100.249/32 src 203.0.113.133 dev eth_rot

Wenn man testweise versucht eine Verbindung zur Appliance herzustellen, scheint es erst einmal zu tun.

# ssh 198.51.100.249
15:42:02  IP 203.0.113.133.35158 > 198.51.100.249.22: S 3034099253:3034099253(0)
15:42:03  IP 203.0.113.133.35158 > 198.51.100.249.22: S 3034099253:3034099253(0)
15:42:05  IP 203.0.113.133.35158 > 198.51.100.249.22: S 3034099253:3034099253(0)

Wie man sieht, geht die Anfrage mit der richtigen Absende-IP raus.

Allerdings kommt keine Antwort zurück. Aber warum?

... und zurück

Ein Blick auf die ASA zeigt, das die Datenpakete korrekt nattet und sogar Antworten bekommt.

 16: 15:42:02   192.0.2.5.35158 > 192.0.2.4.22: S 3034099253:3034099253(0) win 14600
 17: 15:42:02   192.0.2.4.22 > 192.0.2.5.35158: S 2009198346:2009198346(0) ack 3034099253 win 14480
 18: 15:42:03   192.0.2.5.35158 > 192.0.2.4.22: S 3034099253:3034099253(0) win 14600
 19: 15:42:03   192.0.2.4.22 > 192.0.2.5.35158: S 2009198346:2009198346(0) ack 3034099253 win 14480
 20: 15:42:05   192.0.2.5.35158 > 192.0.2.4.22: S 3034099253:3034099253(0) win 14600
 21: 15:42:05   192.0.2.4.22 > 192.0.2.5.35158: S 2009198346:2009198346(0) ack 3034099253 win 14480

Warum kommen die Datenpakete nicht wieder zurück? Weil die Default Route fehlt!

Glücklicherweise ist die ASA kein Router. Genauer gesagt die Routingentscheidung wird in zwei Schritten vorgenommen:

  • Steht das ausgehende Interface nicht fest, so wird die generische Routingtabelle befragt, um das Interface zu ermitteln.
  • Ist allerdings klar, auf welchem Bein ausgesendet werden muss, so wird nur der Teil der Routingtabelle betrachtet, der diesem Interface zugeordnet ist.

Eine der Konsequenzen aus diesem Ansatz erklärt die seltsame Anforderung, bei jeder statische konfigurierten Route immer das Interface mit angeben zu müssen: Um so eine schräge Logik umsetzen zu können, muss man erst mal die Angaben dafür haben.

In diesem Fall genügt es also eine weitere Default Route einzutragen, die eine höhere Metrik hat. Dies stellt sicher, dass die ASA keine zwei gleichberechtigten Routen erhält, mit denen sie nicht umgehen kann. Die Situation für die ASA bleibt also eindeutig.

(conf)# route red 0.0.0.0 0.0.0.0 198.51.100.254 2

An der Standard-Routingtabelle ändert sich damit ja nichts:

C    198.51.100.248 255.255.255.248 is directly connected, red
C    198.51.100.0 255.255.255.192 is directly connected, green
C    192.0.2.0 255.255.255.0 is directly connected, gray
S*   0.0.0.0 0.0.0.0 [1/0] via 198.51.100.1, green

Ganz anders ist nun aber die Situation für die Pakete dar, die aus dem (reverse)-NAT heraus fallen.

  • Der NAT Eintrag enthält die Quell- und Ziel-Interfaces, sowie die IP-Adressen und Ports.
  • Pakete bestehender Flows werden also nicht normal behandelt, sondern anhand des vorhandenen NAT-Eintrags.
  • Damit umgehen sie sämtliches konfiguriertes Routing, ACLs etc. insbesondere die Standard-Routingtabelle.
  • Da das Zielinterface fest steht, greift nur noch die Routingtabelle dieses Interfaces, also die niedrig priorisierte Default Route.

Und siehe an:

# ssh  198.51.100.249 
16:38:20  IP 203.0.113.133.51310 > 198.51.100.249.22: S 3979383937:3979383937(0)
16:38:20  IP 198.51.100.249.22 > 203.0.113.133.51310: S 3186400021:3186400021(0) ack 3979383938
16:38:20  IP 203.0.113.133.51310 > 198.51.100.249.22: . ack 1 win 115
16:38:20  IP 198.51.100.249.22 > 203.0.113.133.51310: P 1:22(21) ack 1 win 114
16:38:20  IP 203.0.113.133.51310 > 198.51.100.249.22: . ack 22 win 115
16:38:20  IP 203.0.113.133.51310 > 198.51.100.249.22: P 1:21(20) ack 22 win 115
16:38:20  IP 198.51.100.249.22 > 203.0.113.133.51310: . ack 21 win 114
 136: 16:38:20    192.0.2.5.51310 > 192.0.2.4.22: S 1381971035:1381971035(0) win 14600
 137: 16:38:20    arp who-has 192.0.2.5 tell 192.0.2.4 
 138: 16:38:20    arp reply 192.0.2.5 is-at e8:b7:48:fd:89:81 
 139: 16:38:20    192.0.2.4.22 > 192.0.2.5.51310: S 2009198346:2009198346(0) ack 1381971036 win 14480
 140: 16:38:20    192.0.2.5.51310 > 192.0.2.4.22: . ack 2009198347 win 115
 141: 16:38:20    192.0.2.4.22 > 192.0.2.5.51310: P 2009198347:2009198368(21) ack 1381971036 win 114
 142: 16:38:20    192.0.2.5.51310 > 192.0.2.4.22: . ack 2009198368 win 115
 143: 16:38:20    192.0.2.5.51310 > 192.0.2.4.22: P 1381971036:1381971056(20) ack 2009198368 win 115
 144: 16:38:20    192.0.2.4.22 > 192.0.2.5.51310: . ack 1381971056 win 114
 145: 16:38:20    192.0.2.5.51310 > 192.0.2.4.22: P 1381971056:1381971848(792) ack
 146: 16:38:20    192.0.2.4.22 > 192.0.2.5.51310: . ack 1381971848 win 126

Hurra!

Spiele mit DirectAccess

18/05/2017 3:11 pm Lutz Donnerhacke Tags: IPv6 , Microsoft , Windows 0

Über DirectAccess hatte ich schon einiges erzählt, und natürlich auch ausprobiert. Was ich aber noch nie angesehen habe, war DirectAccess ohne IPv6 im inneren oder äußeren Netz, also total legacy. In der Schulung habe ich die Gelegenheit dazu und möchte die Ergebnisse nicht vorenthalten.

IPv4 only Lab

Nachdem der DirectAccess Client in die weite Welt verschwunden ist, und er voller Verzweiflung nach Hause telefoniert hat, bietet sich folgendes Bild.

C:\> ipconfig
Ethernet adapter Ethernet 2:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::a19f:cc85:1320:8c4%5
   IPv4 Address. . . . . . . . . . . : 131.107.0.2
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
Tunnel adapter iphttpsinterface:
   Connection-specific DNS Suffix  . :
   IPv6 Address. . . . . . . . . . . : 2002:836b:c8:1000:1934:30a2:9e84:cdf4
   Temporary IPv6 Address. . . . . . : 2002:836b:c8:1000:f037:3b8d:cabc:bfcb
   Link-local IPv6 Address . . . . . : fe80::1934:30a2:9e84:cdf4%24
   Default Gateway . . . . . . . . . :

Es gibt also ein Interface im Internet mit öffentlichen Adressen ohne IPv6 Versorgung. Und dann gibt es den Tunnel nach Hause. Da sowohl Client als auch der DirectAccess Server öffentliche IPs haben, wurde der Tunnel mit 6to4-Adressen aufgebaut.

In den Schulungsunterlagen steht Notice the IP address for Tunnel Adapter is IPHTTPSInterface starting with 2002. This is an IP-HTTPS address. (Fehler sind so übernommen)

Nein, Microsoft! Es ist eine 6to4 Adresse. Offenbar habt Ihr wirklich keine praktische Erfahrungen mit IPv6.

Die zugehörige Routingtabelle zeigt:

c:\> route print -6
===========================================================================
Interface List
  5...00 15 5d 64 4d 4d ......Microsoft Hyper-V Network Adapter #2
  1...........................Software Loopback Interface 1
 24...00 00 00 00 00 00 00 e0 iphttpsinterface
===========================================================================
IPv6 Route Table
===========================================================================
Active Routes:
 If Metric Network Destination      Gateway
  1    331 ::1/128                  On-link
 24   4171 2002::/16                fe80::d92f:34d4:3add:e715
 24    331 2002:836b:c8::/48        fe80::d92f:34d4:3add:e715
 24    331 2002:836b:c8::/64        fe80::d92f:34d4:3add:e715
 24    331 2002:836b:c8:1::/64      fe80::d92f:34d4:3add:e715
 24    331 2002:836b:c8:5::/64      fe80::d92f:34d4:3add:e715
 24    331 2002:836b:c8:1000::/64   On-link
 24    331 2002:836b:c8:1000:1934:30a2:9e84:cdf4/128
                                    On-link
 24    331 2002:836b:c8:1000:f037:3b8d:cabc:bfcb/128
                                    On-link
 24    331 fd68:d6bf:56b6:7777::/96 fe80::d92f:34d4:3add:e715
  5    271 fe80::/64                On-link
 24    331 fe80::/64                On-link
 24    331 fe80::1934:30a2:9e84:cdf4/128
                                    On-link
  5    271 fe80::a19f:cc85:1320:8c4/128
                                    On-link
  1    331 ff00::/8                 On-link
  5    271 ff00::/8                 On-link
 24    331 ff00::/8                 On-link
===========================================================================
Persistent Routes:
  None

Das Routingziel ist eine Link-Local-Adresse, wie es sich für IPv6 gehört. Prima! Und die Adresse ist auch über den Tunnel erreichbar.

C:\>netsh int ipv6 sho nei 24
Internet Address                              Physical Address   Type
--------------------------------------------  -----------------  -----------
2002:836b:c8:1000:d92f:34d4:3add:e715                            Reachable (Router)
fe80::d92f:34d4:3add:e715                                        Reachable (Router)

Spielt man nun mit Browser und Explorer im Netz rum, gibt es offene Verbindungen:

C:\> netstat -n
Active Connections
  Proto  Local Address          Foreign Address        State
  TCP    131.107.0.2:49782      131.107.0.200:443      ESTABLISHED
  TCP    [2002:836b:c8:1000:f037:3b8d:cabc:bfcb]:49785  [fd68:d6bf:56b6:7777::ac10:c8]:80  ESTABLISHED
  TCP    [2002:836b:c8:1000:f037:3b8d:cabc:bfcb]:61893  [fd68:d6bf:56b6:7777::ac10:b]:80  ESTABLISHED

Die Verbindungen sind also offenbar über IPv6 zu einem ULA-Ziel (bäh!).

Das DirectAccess-Gateway macht noch NAT64, bettet also die IPv4 Adressen der LAN-Geräte ins IPv6 ein. Sieht man deutlich.

Dazu muss das Gateway offenbar auch DNS64 machen, um die DNS Antworten umzubiegen. Das sieht man leicht:

c:\>ipconfig /displaydns
Windows IP Configuration
    directaccess-webprobehost.adatum.com
    ----------------------------------------
    Record Name . . . . . : directaccess-WebProbeHost.Adatum.com
    Record Type . . . . . : 28
    Time To Live  . . . . : 213
    Data Length . . . . . : 16
    Section . . . . . . . : Answer
    AAAA Record . . . . . : fd68:d6bf:56b6:7777::ac10:c8

Aber warum macht der Client das? Der hat doch einen ganz anderen DNS Server?

C:\>netsh name show eff
DNS Effective Name Resolution Policy Table Settings

Settings for .Adatum.com
----------------------------------------------------------------------
DirectAccess (Certification Authority)  :
DirectAccess (IPsec)                    : disabled
DirectAccess (DNS Servers)              : 2002:836b:c8:3333::1
DirectAccess (Proxy Settings)           : Bypass Proxy

Settings for DirectAccess-NLS.Adatum.com
----------------------------------------------------------------------
DirectAccess (Certification Authority)  :
DirectAccess (IPsec)                    : disabled
DirectAccess (DNS Servers)              :
DirectAccess (Proxy Settings)           : Use default browser settings

Der Client hat also eine Policy für die Namensauflösung, die bei bestimmten Domains einen anderen DNS Server befragt. Genau, das Gateway.

C:\> ping lon-svr1.adatum.com
Pinging lon-svr1.adatum.com [fd68:d6bf:56b6:7777::ac10:b] with 32 bytes of data:
Reply from fd68:d6bf:56b6:7777::ac10:b: time=4ms
Reply from fd68:d6bf:56b6:7777::ac10:b: time=10ms
Reply from fd68:d6bf:56b6:7777::ac10:b: time=1ms
Ping statistics for fd68:d6bf:56b6:7777::ac10:b:
    Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 10ms, Average = 5ms

Allerdings funktioniert das nur, wenn diese Policy Regeln auch von der Applikation berücksichtigt werden:

C:\> nslookup lon-svr1.adatum.com
Server:  UnKnown
Address:  131.107.0.100

DNS request timed out.
    timeout was 2 seconds.
*** Request to UnKnown timed-out

Fragt man den richtigen Server, gibt es ganz andere Antworten:

C:\> nslookup lon-svr1.adatum.com 2002:836b:c8:3333::1
Server:  UnKnown
Address:  2002:836b:c8:3333::1

Non-authoritative answer:
Name:    lon-svr1.adatum.com
Addresses:  fd68:d6bf:56b6:7777::ac10:b
          172.16.0.11

All das ist mir all die Jahre verborgen geblieben, weil ich IPv6 ausgerollt hatte.

Ich vermisse nichts.

Was IPv6 ändert

Wird auf dem Außeninterface natives IPv6 eingesetzt, verschwinden sofort die 2002-er 6to4 Adressen. Dazu ist anzumerken:

  • Das im Lab die Kommunikation geklappt hatte, liegt daran, dass Microsoft das 2002:836b:c8:1000::/64 auf dem Interface betreibt.
  • Um mit 6to4 Adressen zu kommunizieren, muss man sich auf externe 6to4 Gateways verlassen. Dies kommt ins Spiel, weil der DNS Server 2002:836b:c8:3333::1 angesprochen wird.
  • Da beide Hosts über den IPv4-HTTPS-Tunnel IPv6 im externen Routing komplett umgehen, benötigen sie keine 6to4 Router im Internet.
  • Da beide Server extern öffentliche IPv4 Adressen haben, wird überhaupt 6to4 benutzt. Steht ein Gerät hinter NAT wird es auf Teredo zurück fallen.
  • Teredo funktioniert nicht mit allen NAT-Typen, speziell gibt es Probleme, wenn die öffentliche NAT-IP nicht stabil ist (z.B. bei Carrier Grade NAT oder Large Scale NAT)
  • Mit RFC 6540 ist IPv6 auf den Außeninterfaces Pflicht für die ISPs.

Wird IPv6 im LAN eingesetzt, verschwindet sofort das fc00::/7 ULA Netz. Stattdessen bekommen die Clients die gleiche IP, wie sie auch im LAN hätten. Das hat folgende Implikationen:

  • Der Client ist intern, wie extern unter der gleichen IP ansprechbar.
  • Die Fernwartung wird damit im Unternehmen unabhängig vom Aufenthaltsort des Clients.
  • Da Server und Clients IPv6 einsetzen, entfällt DNS64 und NAT64.
  • Applikationen können mit allen benötigten Ports Verbindungen in alle benötigten Richtungen ausführen. Es ist nicht notwendig im DirectAccess-Server NAT-Helper pro Protokoll zu haben.
  • Auf diese Weise funktionieren Protokolle wie Telefonie, Videokonferenzen, FTP, etc. pp. einfach auch extern.
  • Fremdapplikationen, die ihre eigene Namensauflösung fahren, funktionieren problemlos, weil sich nur das Routing zum DNS Server ändert. Es ist nicht länger notwendig, sich Domainabhängig an unterschiedliche DNS Server zu wenden.

Man sollte sich also wirklich überlegen, ob man weiter auf IPv6 verzichten will.

Next » 1 2 3 4