Recipiente de linux IPv6 publicamente roteável

7

Meu objetivo é ter um endereço IPv6 público roteável para cada um dos contêineres do Docker. Eu quero ser capaz de se conectar e sair de meus contêineres usando o protocolo IPv6.

Estou usando o Linode e recebi um pool IPv6 público:

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

Esse endereço "encaminhado para" foi configurado automaticamente por dhcp:

# 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

Eu configurei um registro AAAA para ipv6.daaku.org para facilitar o trabalho com:

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

Para testar, eu designei esse endereço manualmente:

# 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

Agora posso pingar isso da minha rede doméstica com IPv6:

# 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

Eu removi o endereço porque quero apenas no contêiner e voltei ao estado original:

# 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

Eu iniciei um contêiner docker sem uma rede em outro terminal:

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

Preso é pid em uma variável para facilidade de uso:

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

Configure os netns para esse pid:

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

Criado um novo dispositivo, atribuído a ele o IP:

# 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

De volta ao outro terminal em que iniciei o contêiner:

# 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

Isso não funciona e não consigo me conectar a partir do contêiner (usando ping6 ipv6.google.com como meu teste) nem posso fazer o ping do contêiner pela internet da minha rede doméstica (usando ping6 ipv6.daaku.org como meu teste) .

Atualização: consegui fazer com que o envio IPv6 funcionasse assim:

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

Rotas IPv6 no 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

Rotas IPv6 no contêiner:

# 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

Ainda não consigo fazer o ping na minha máquina doméstica.

    
por daaku 22.11.2014 / 02:51

3 respostas

2

Acho que seu problema é relacionado ao roteamento. O problema é que você foi atribuído a /64 , mas decidiu sub-sub-rede em /112 . Isso é bom para o tráfego de saída, porque seu host de contêiner sabe sobre todas as sub-sub-redes individuais, mas quando seu ISP trata os pacotes de retorno, eles não sabem que você sub-selecionou 2600:3c01:e000:e2::1111:0/112 e que isso deve ser roteado via 2600:3c01:e000:00e2::1 . Eles só esperam que a totalidade do 2600:3c01:e000:00e2::/64 esteja lá, conectada diretamente e acessível via unicast.

O problema é que não existe nenhum mecanismo para informar ao seu ISP que você decidiu iniciar sub-sub-redes (na verdade, isso é uma mentira, existem várias maneiras - mas todas elas requerem cooperação do seu ISP). A sua aposta mais simples é provavelmente parar o encaminhamento do tráfego para os contentores e começar a fazer a ponte .

Eu não posso te dizer exatamente como fazer isso. Eu tentei, e várias pessoas gentilmente apontaram que eu estava errado. Espero que alguém possa esclarecer. Mas o problema continua sendo que você precisa conectar seus contêineres à sua rota de próximo salto, e vice-versa, em vez de rotea-los.

    
por 22.11.2014 / 14:51
1

No Docker 1.0, há duas opções para habilitar a conectividade IPv6 para contêineres docker. Eu tive que usar o driver lxc em vez de libcontainer para obter esses dois métodos para o trabalho. Você poderá usar o RADVD. Eu não tentei isso.

1) Faça com que o provedor direcione o / 64 para o host do docker . Esta é uma opção mais fácil. Ative o encaminhamento IPv6 e atribua o / 64 ao docker0. Você não precisa dividir essa rede em redes menores (por exemplo, / 112), a menos que tenha várias pontes docker ou vários hosts docker.

Este método é discutido em profundidade no post do blog de Andreas Neuhaus "IPv6 in Docker Containers". Consulte o link .

Observe que muito poucos provedores de IaaS habilitados para IPv6 rotearão um / 64 para uma VM. O segundo método supera essa limitação de maneira semi-claudicante.

2) Use um subconjunto de / 64 da interface de rede local na ponte de encaixe - esse método não requer um / 64 roteado para o host de encaixe. Uma rede menor no / 64 (por exemplo, / 112) na LAN é atribuída ao docker0. O NDP é configurado para fazer proxy do NDP da ponte do docker para a sua interface de LAN (provavelmente eth0).

Eu escrevi uma descrição detalhada desse método em link .

Eu não usei versões do docker maiores que 1.0. É possível que as coisas tenham mudado em versões mais recentes.

    
por 24.11.2014 / 15:05
0

Por RFC, todos os endereços em uma sub-rede estão dentro de um / 64. Atribuições dentro deste espaço usam um ou mais endereços IPv6.

Você está pensando que o IPv6 é como o IPv4, mas endereços maiores. Eu estou aqui para lhe dizer se você projetar seus sistemas dessa maneira, espere aumentar seus custos de configuração, manutenção é segurança!

    
por 22.12.2014 / 15:02