即使无法获取足够数量的IPv6地址,也可以通过容器内进行IPv6通信
首先
IPv6已到来!我要在容器中使用IPv6!咦,不能获得/48的地址吗?太抠门了…orz
基本上是將以下網站上的內容拼湊而成,感謝。
-
- robbertkl/docker-ipv6nat: Extend Docker with IPv6 NAT, similar to IPv4
- Ubuntu18.04でDockerコンテナのIPv6を有効にする方法
尽管是IPv6,为什么还要使用NAPT呢?
尽管废除NAPT是IPv6的一个目标,但目前阶段,对于在Docker中使用有限数量的IPv6地址,NAPT仍然是最便捷的解决方案。
我认为IPv6上的NAPT也很令我不舒服,也不是一个理智的做法,但光有美好的想法并不能顺利解决问题。有时候也需要以毒攻毒……真的,请给我一个正常的/64…
只能使用一个IPv6地址的情况下
- ホストで使えるIPv6は 2001:db8:1234:abcd:111:222:333:444/128 のみとします
准备
-
- まずホストでちゃんとipv6が通ることを確認
ping6 -n -c 4 www.google.com
dockerdをipv6有効で起動
必要箇所のみ抜粋
{
"ipv6": true,
"fixed-cidr-v6": "fd00::/80"
}
- ip6tablesで-t natする
ip6tables -t nat -A POSTROUTING -s fd00::/80 ! -o docker0 -j MASQUERADE
ip6tables -t nat -A POSTROUTING -s fd00:1::/80 ! -o docker0 -j MASQUERADE
从容器内部到外部的IPv6访问
-
- ping6をしてみる
daemon.jsonに書いてあるfd00::/80から割り当てられる
docker run –rm -t busybox sh -c “ip addr ; ping6 -n -c 4 www.google.com”
docker-composeでnetworks:を指定する場合の例
たとえばfd00:1::/80を明示的に指定する場合
networks:
default:
enable_ipv6: true
ipam:
config:
- subnet: fd00:1::/80
-
- いずれもip6tablesのMASQUERADEで出ていく
- うまくいかないときは、docker container ls, docker network ls等でゴミが残っていないことを確認
从外部到容器内的IPv6访问
- docker-ipv6natの起動
docker run -d --name ipv6nat \
--privileged \
--network host \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /lib/modules:/lib/modules:ro \
robbertkl/ipv6nat
-
- コマンドラインの場合: 省略
- docker-composeの場合:
services:
httpd6:
image: busybox
container_name: httpd6
ports:
- 8080:80
command:
- sh
- -c
- 'echo Hello world > index.html && httpd -f -v'
-
- テスト
curl -v [2001:db8:1234:abcd:111:222:333:444]:8080
docker logs test でアクセス元が見える
如果能够使用不太多但可以指定的大量IPv6地址
例子
2001:db8:1234:abcd:111:222:333:444/128 がホストのIPv6アドレス
2001:db8:1234:abcd:a111:222:333:444{0,1,2,3…f}/128 が使用可能で、これをコンテナで使いたい
2001:db8:1234:abcd:a111:222:333::/112 をダミーのsubnetとする
要するに美雲このはちゃん
IPv6をVPSへ設定する|ConoHa VPSサポート
docker网络连接版本
-
- ip -6つなげる
ip -6 addr add 2001:db8:1234:abcd:a111:222:333:4440/128 dev eth0
daemon.json, MASQUERADE, docker-ipv6natは前節と同じ
network作成
docker network create –ipv6 –subnet=2001:db8:1234:abcd:a111:222:333::/112 –gateway=2001:db8:1234:abcd:a111:222:333:4440 ipv6_exposed_hosts
gatewayで指定したのが外に露出する
2001:db8:1234:abcd:a111:222:333:dead をダミーとして使う
これはダミーなので、外からの経路はなくてもいい
コマンドラインの場合:
docker network connect –ip6 2001:db8:1234:abcd:a111:222:333:dead ipv6_exposed_hosts httpd6
docker-composeの場合:
networks:
ipv6_exposed_hosts:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 2001:db8:1234:abcd:a111:222:333::/112
gateway: 2001:db8:1234:abcd:a111:222:333:4440
services:
httpd6:
image: busybox
container_name: httpd6
ports:
- 8080:80
command:
- sh
- -c
- 'echo "Hello world!" > index.html && httpd -f -v'
networks:
ipv6_exposed_hosts:
ipv6_address: 2001:db8:1234:abcd:a111:222:333:dead
-
- テスト
curl -6 [2001:db8:1234:abcd:a111:222:333:4440]:8080
ip6tables -t nat -j 使用 DNAT 规则
-
- ip -6つなげる
ip -6 addr add 2001:db8:1234:abcd:a111:222:333:4440/128 dev eth0
daemon.json, MASQUERADEは前節と同じ
コンテナを普通に立ち上げる
そのコンテナのIPv6アドレスを取得(上記でいう末尾dead、無指定ならfd00::から選ばれるので調べる)
docker container inspect httpd6 | jq .[0].NetworkSettings.Networks[].GlobalIPv6Address
ip6tables -j DNATで繋げる
ip6tables -t nat -I DOCKER -i eth0 -d 2001:db8:1234:abcd:a111:222:333:4440 -p tcp -m tcp –dport 8080 -j DNAT –to-destination [${上記アドレス}]:80
テスト
curl -6 [2001:db8:1234:abcd:a111:222:333:4440]:8080
nd 代理版
- ホストのeth0にip aliasを追加するのではなく、nd proxyを繋げる
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.eth0.proxy_ndp=1
ip -6 neigh add proxy 2001:db8:1234:abcd:a111:222:333:4441 dev eth0
- docker-composeであげる
networks:
ipv6_exposed_hosts:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: 2001:db8:1234:abcd:a111:222:333::/112
services:
httpd6:
image: busybox
container_name: httpd6
command:
- sh
- -c
- 'echo "Hello world!" > index.html && httpd -f -v'
networks:
ipv6_exposed_hosts:
ipv6_address: 2001:db8:1234:abcd:a111:222:333:4441
-
- ipv6_exposed_hostsのidを調べる
docker network ls
ufwで穴をあけて経路繋げる
ufw route allow in on eth0 out on br-${上記netowrkidの先頭}
テスト
curl -6 [2001:db8:1234:abcd:a111:222:333:4441]:80
通过ip6tables对容器地址通信进行过滤
- 通常、IPv4のコンテナ宛はFORWARD(の子のDOCKER-USER)でフィルタリングしますが、この記事のnd proxy版以外の方法の場合INPUT chainになります
最后
-
- IPv6アドレスもっとください。
- awsさん、IPv4は捨てるんで別に有償でも構わないけどEIPはIPv6対応しないんですか?
借鉴资料
-
- IPv6 Subnet Calculator – subnettingpractice.com
-
- DockerのコンテナにIPv6で接続すると接続元IPアドレスがコンテナネットワーク内のIPv4アドレスになる – Qiita
-
- robbertkl/docker-ipv6nat: Extend Docker with IPv6 NAT, similar to IPv4
-
- Ubuntu18.04でDockerコンテナのIPv6を有効にする方法
-
- docker-composeでnginxをIPv6化 | mahori ブログ 本館
- RPi4 – Docker with IPv6 and Docker Compose