Öffentlich routbarer IPv6-Linux-Container

7

Mein Ziel ist es, eine routingfähige öffentliche IPv6-Adresse für jeden meiner Docker-Container zu haben. Ich möchte über das IPv6-Protokoll eine Verbindung zu und aus meinen Containern herstellen können.

Ich verwende Linode und habe einen öffentlichen IPv6-Pool erhalten:

2600:3c01:e000:00e2:: / 64 routed to 2600:3c01::f03c:91ff:feae:d7d7

Diese "geroutete" Adresse wurde von dhcp automatisch konfiguriert:

# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
       valid_lft 2591987sec preferred_lft 604787sec
    inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
       valid_lft forever preferred_lft forever

Ich habe einen AAAA-Datensatz eingerichtet ipv6.daaku.org, um die Arbeit zu vereinfachen:

# nslookup -q=AAAA ipv6.daaku.org
ipv6.daaku.org  has AAAA address 2600:3c01:e000:e2::1

Zum Testen habe ich diese Adresse manuell zugewiesen:

# ip -6 addr add 2600:3c01:e000:00e2::1/64 dev eth0
# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2600:3c01:e000:e2::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
       valid_lft 2591984sec preferred_lft 604784sec
    inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
       valid_lft forever preferred_lft forever

Ich kann dies jetzt von meinem IPv6-fähigen Heimnetzwerk aus anpingen:

# ping6 -c3 ipv6.daaku.org
PING6(56=40+8+8 bytes) 2601:9:400:12ab:1db7:a353:a7b4:c192 --> 2600:3c01:e000:e2::1
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=0 hlim=54 time=16.855 ms
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=1 hlim=54 time=19.506 ms
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=2 hlim=54 time=17.467 ms

--- ipv6.daaku.org ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 16.855/17.943/19.506/1.133 ms

Ich habe die Adresse entfernt, weil ich sie nur im Container haben möchte, und bin zum ursprünglichen Zustand zurückgekehrt:

# ip -6 addr del 2600:3c01:e000:00e2::1/64 dev eth0
# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
       valid_lft 2591987sec preferred_lft 604787sec
    inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
       valid_lft forever preferred_lft forever

Ich habe einen Docker-Container ohne Netzwerk in einem anderen Terminal gestartet:

# docker run -it --rm --net=none debian bash
root@b96ea38f03b3:/#

Zur Vereinfachung der Verwendung steckt es in einer Variablen fest:

CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' b96ea38f03b3)

Richten Sie die Netze für diese PID ein:

# mkdir -p /run/netns
# ln -s /proc/$CONTAINER_PID/ns/net /run/netns/$CONTAINER_PID

Erstellt ein neues Gerät, weist ihm die IP zu:

# ip link add container0 link eth0 type macvlan
# ip link set container0 netns $CONTAINER_PID
# ip netns exec $CONTAINER_PID ip link set dev container0 name eth0
# ip netns exec $CONTAINER_PID ip link set eth0 up
# ip netns exec $CONTAINER_PID ip addr add 2600:3c01:e000:00e2::1/64 dev eth0

Zurück im anderen Terminal, wo ich den Container gestartet habe:

# ip -6 addr show eth0
22: eth0@gre0: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500
    inet6 2600:3c01::a083:1eff:fea5:5ad2/64 scope global dynamic
       valid_lft 2591979sec preferred_lft 604779sec
    inet6 2600:3c01:e000:e2::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::a083:1eff:fea5:5ad2/64 scope link
       valid_lft forever preferred_lft forever

# ip -6 route
2600:3c01::/64 dev eth0  proto kernel  metric 256  expires 2591976sec
2600:3c01:e000:e2::/64 dev eth0  proto kernel  metric 256
fe80::/64 dev eth0  proto kernel  metric 256
default via fe80::1 dev eth0  proto ra  metric 1024  expires 67sec

Dies funktioniert nicht und ich kann weder eine Verbindung zum Container herstellen ( ping6 ipv6.google.comals Test verwenden) noch den Container über das Internet von meinem Heimnetzwerk aus ( ping6 ipv6.daaku.orgals Test verwenden) anpingen.

Update: Ich habe es geschafft, ausgehendes IPv6 auf folgende Weise zum Laufen zu bringen :

ip -6 addr add 2600:3c01:e000:00e2::1111:1/112 dev docker0 &&
ip6tables -P FORWARD ACCEPT &&
sysctl -w net.ipv6.conf.all.forwarding=1 &&
sysctl -w net.ipv6.conf.all.proxy_ndp=1

CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' 4fd3b05a04bb)
mkdir -p /run/netns &&
ln -s /proc/$CONTAINER_PID/ns/net /run/netns/$CONTAINER_PID &&
ip netns exec $CONTAINER_PID ip -6 addr add 2600:3c01:e000:00e2::1111:20/112 dev eth0 &&
ip netns exec $CONTAINER_PID ip -6 route add default via 2600:3c01:e000:00e2::1111:1 dev eth0

IPv6-Routen auf dem Host:

# ip -6 r
2600:3c01::/64 dev eth0  proto kernel  metric 256  expires 2582567sec
2600:3c01:e000:e2::1111:0/112 dev docker0  proto kernel  metric 256
2600:3c01:e000:e2::/64 dev eth0  proto kernel  metric 256
fe80::/64 dev eth0  proto kernel  metric 256
fe80::/64 dev docker0  proto kernel  metric 256
fe80::/64 dev veth1775864  proto kernel  metric 256
fe80::/64 dev veth102096c  proto kernel  metric 256
fe80::/64 dev vethdf3a55b  proto kernel  metric 256

IPv6-Routen im Container:

# ip -6 r
2600:3c01:e000:e2::1111:0/112 dev eth0  proto kernel  metric 256
fe80::/64 dev eth0  proto kernel  metric 256
default via 2600:3c01:e000:e2::1111:1 dev eth0  metric 1024

Ich kann es immer noch nicht von meinem Heimcomputer aus anpingen.

Daaku
quelle
Welche Linux-Distribution verwenden Sie?
Michael Hampton
Ich benutze Arch Linux.
Daaku
Haben Sie die IPv6-Weiterleitung im Kernel aktiviert?
Sander Steffann
Ja, ich glaube, ich habe die Weiterleitung korrekt eingerichtet. Siehe Update oben.
Daaku

Antworten:

2

Ich denke, Ihr Problem hängt mit dem Routing zusammen. Das Problem ist, dass Ihnen eine Wohnung zugewiesen /64wurde, Sie sich jedoch für ein Sub-Subnetz von a entschieden haben /112. Dies ist für ausgehenden Datenverkehr in Ordnung, da Ihr Container-Host alle einzelnen Sub-Subnetze kennt. Wenn Ihr ISP jedoch die Rückgabepakete verarbeitet, weiß er nicht, dass Sie die Unterabschnitte abgetrennt haben 2600:3c01:e000:e2::1111:0/112und dass diese über weitergeleitet werden sollten 2600:3c01:e000:00e2::1. Sie erwarten nur, dass das Ganze 2600:3c01:e000:00e2::/64dort sitzt, direkt verbunden und über Unicast erreichbar ist.

Das Problem ist, dass es keinen Mechanismus gibt , der Ihrem ISP mitteilt, dass Sie sich entschieden haben, mit dem Sub-Subnetz zu beginnen (eigentlich ist das eine Lüge, es gibt eine Reihe von Möglichkeiten - aber alle erfordern die Zusammenarbeit Ihres ISP). Ihre einfachste Wette ist wahrscheinlich zu stoppen Routing des Verkehrs auf die Behälter, und starten Sie überbrücken es.

Ich kann dir nicht genau sagen, wie das geht. Ich habe es versucht, und mehrere Leute haben freundlich darauf hingewiesen, dass ich falsch lag. Hoffentlich kann jemand das klären. Das Problem bleibt jedoch, dass Sie Ihre Container mit Ihrer Next-Hop-Route und umgekehrt verbinden müssen, anstatt sie weiterzuleiten.

MadHatter
quelle
docker0 ist eine Brücke, keine Schnittstelle
Bryan
docker0 ist schon eine brücke. Docker hat eine Hilfeseite zum Ersetzen durch Ihre eigene Bridge .
Michael Hampton
Danke, das hatte ich vermutet. Das Problem war, was mit dem Verkehr auf dem Weg von docker0der Welt und umgekehrt passiert , und ich schlage vor, dass dieser Hop überbrückt (und nicht geroutet) werden sollte. Es mag der richtige Weg sein, dies zu tun, indem man eth0die docker0Brücke erweitert - wie gesagt, ich bin kein Experte für Containerisierung -, aber ich bin mir ziemlich klar darüber, was das OP tun muss, selbst wenn ich kann Ich weiß nicht genau, wie er es machen soll.
MadHatter
Ich hätte wahrscheinlich gerade die / 64 an docker0 weitergeleitet.
Michael Hampton
@MichaelHampton Ich bin froh, die gesamte / 64 auch an docker0 weiterleiten zu können. MadHatter die / 64-Routen zu 2600: 3c01 :: f03c: 91ff: feae: d7d7 / 64 - kann das die andere Adresse auf dem eth0-Internet-Link sein?
Daaku
1

In Docker 1.0 gibt es zwei Optionen zum Aktivieren der IPv6-Konnektivität für Docker-Container. Ich musste den lxc-Treiber anstelle von libcontainer verwenden, damit beide Methoden funktionieren. Möglicherweise können Sie RADVD verwenden. Ich habe es nicht versucht.

1) Lassen Sie den Provider die / 64 an Ihren Docker-Host weiterleiten . Dies ist die einfachste Option. Aktivieren Sie die IPv6-Weiterleitung und weisen Sie Docker0 / 64 zu. Sie müssen dieses Netzwerk nicht in kleinere Netzwerke aufteilen (z. B. / 112), es sei denn, Sie haben mehrere Docker-Bridges oder mehrere Docker-Hosts.

Diese Methode wird in Andreas Neuhaus 'Blogbeitrag "IPv6 in Docker Containers" ausführlich behandelt. Siehe http://zargony.com/2013/10/13/ipv6-in-docker-containers .

Beachten Sie, dass nur sehr wenige IPv6-fähige IaaS-Anbieter a / 64 an eine VM weiterleiten. Die zweite Methode überwindet diese Einschränkung auf halbkludige Weise.

2) Verwenden Sie eine Teilmenge von / 64 von der LAN-Schnittstelle auf der Docker-Bridge. - Für diese Methode ist kein / 64 erforderlich, das an Ihren Docker-Host weitergeleitet wird. Ein kleineres Netzwerk im / 64 (z. B. / 112) im LAN ist Docker0 zugewiesen. NDP ist so konfiguriert, dass NDP von der Docker-Bridge zu Ihrer LAN-Schnittstelle (wahrscheinlich eth0) übertragen wird.

Ich habe eine detaillierte Beschreibung dieser Methode unter http://jeffloughridge.wordpress.com/2014/07/22/ipv6-in-docker-containers-on-digitalocean/ geschrieben .

Ich habe keine Docker-Versionen größer als 1.0 verwendet. Es ist möglich, dass sich die Dinge in neueren Versionen geändert haben.

Jeff Loughridge
quelle
0

Per RFC befinden sich alle Adressen in einem Subnetz innerhalb von / 64. Zuweisungen in diesem Bereich verwenden eine oder mehrere IPv6-Adressen.

Sie denken, IPv6 ist wie IPv4, aber größere Adressen. Ich bin hier, um Ihnen zu sagen, wenn Sie Ihre Systeme so entwerfen, Ihre Einrichtungskosten erhöhen, Wartung Sicherheit ist!

JoeKlein
quelle
1
Welcher RFC schränkt Ihrer Meinung nach alle IPv6-Subnetzmasken ein /64?
MadHatter