いきなり対処法
update-alternatives --config iptables
で,iptables-legacy
を使うよう変更する.
$ sudo update-alternatives --config iptables
alternative iptables (/usr/sbin/iptables を提供) には 2 個の選択肢があります。
選択肢 パス 優先度 状態
------------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 自動モード
1 /usr/sbin/iptables-legacy 10 手動モード
2 /usr/sbin/iptables-nft 20 手動モード
現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 1
update-alternatives: /usr/sbin/iptables (iptables) を提供するためにマニュアルモードで /usr/sbin/iptables-legacy を使います
$ sudo reboot
いきなり結論
- Debian 10はiptables v1.8系を採用.nftables APIを使う
iptables-nft
と旧来のiptables-legacy
が用意されている. - デフォルトは
iptables-nft
だが,Dockerはiptables-legacy
を使う. - この状態で,
ufw
などを使ってiptables-nft
で定義を設定すると,iptables-legacy
の定義は無視される(ようだ).その結果,外部との通信ができない. - そこで,
iptables-legacy
をデフォルトに変更し,定義をlegacy側に寄せて対処する.
詳細
ufwとiptables
ufw - Uncomplicated Firewall は, ufw allow 22/tcp
などと書くだけでポート開放ができる,お手軽なファイアウォール管理ツールです.
内部的には iptables
(Netfilter) のラッパーのような位置づけで, iptables
の忘れやすいコマンド体系を忘れたままにしておけます.もともとUbuntu向けのツールだったように思いますが,かなり前からDebianでも利用が可能です.
iptables v1.8 - nftables APIサポート
現時点で testing である Debian GNU/Linux 10 (buster) では,iptablesが1.6から1.8にバージョンアップされています.
iptables 1.8では,新たに nftables
Kernel API1を用いたiptables-nft
ツールが提供され,旧来のツールはiptables-legacy
で使用することが出来るようになっています.
iptables
はというと,Debian 10はデフォルトでiptables-nft
へのシンボリックリンクが張られています.ufw
等はこのデフォルトを使用します.
$ ls -l /usr/sbin/iptables
lrwxrwxrwx 1 root root 26 2月 17 11:44 /usr/sbin/iptables -> /etc/alternatives/iptables
$ ls -l /etc/alternatives/iptables
lrwxrwxrwx 1 root root 22 2月 18 22:53 /etc/alternatives/iptables -> /usr/sbin/iptables-nft
Dockerは iptables-legacy
を使う
一方,Dockerはiptables-nft
がうまく扱えず,デフォルトがどうあれ必ずiptables-legacy
を使うように修正が加えられています2 3.
- Docker doesn't work with iptables v1.8.1 · Issue #38099 · moby/moby
- debian has iptables-legacy and iptables-nft now by myobie · Pull Request #2285 · docker/libnetwork
ufw + Docker = iptables-nft + iptables-legacy
ここで,デフォルトのままufw
とDockerを使うと,iptables-nft
とiptables-legacy
の両方の定義が存在することになります.
$ sudo iptables-nft -L
Chain INPUT (policy DROP)
target prot opt source destination
ufw-before-logging-input all -- anywhere anywhere
ufw-before-input all -- anywhere anywhere
ufw-after-input all -- anywhere anywhere
ufw-after-logging-input all -- anywhere anywhere
ufw-reject-input all -- anywhere anywhere
ufw-track-input all -- anywhere anywhere
(省略)
$ sudo iptables-legacy -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
(省略)
ここから先は推測が入りますが,この状態になると iptables-nft
の定義のみが有効となるようです.そのため,Dockerがせっかく書き換えてくれた定義が効かず,コンテナが外部と通信できなくなってしまいます.
ping
でIPアドレスを指定すると通るが,ホスト名を指定するとDNSが引けない,という状況です.
$ sudo docker run -it --rm busybox
/ # ping github.com
ping: bad address 'github.com'
/ # ping 192.30.255.112
PING 192.30.255.112 (192.30.255.112): 56 data bytes
64 bytes from 192.30.255.112: seq=0 ttl=49 time=133.961 ms
64 bytes from 192.30.255.112: seq=1 ttl=49 time=134.677 ms
対処: iptables-legacy
をデフォルトにする
さて,対処法ですが,ufw
も含めてみんなiptables-legacy
を使うようにします.
Docker doesn't work with iptables v1.8.1 · Issue #38099 · moby/mobyのIssue commentにもあるように,デフォルトのiptables
は選べるようになっています.そこで,iptables-legacy
をデフォルトに変更します.
$ sudo update-alternatives --config iptables
alternative iptables (/usr/sbin/iptables を提供) には 2 個の選択肢があります。
選択肢 パス 優先度 状態
------------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 自動モード
1 /usr/sbin/iptables-legacy 10 手動モード
2 /usr/sbin/iptables-nft 20 手動モード
現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 1
update-alternatives: /usr/sbin/iptables (iptables) を提供するためにマニュアルモードで /usr/sbin/iptables-legacy を使います
あとは再起動すれば完了です.
iptables-nft
での定義が残っていても,iptables-legacy
をデフォルトとしていると,legacyが優先されるようです.
参考
- Debian -- buster の iptables パッケージに関する詳細
- iptables 1.8.0 release [LWN.net]
- Docker doesn't work with iptables v1.8.1 · Issue #38099 · moby/moby
- debian has iptables-legacy and iptables-nft now by myobie · Pull Request #2285 · docker/libnetwork
-
API自体は2014年1月にリリースされたLinux Kernel 3.13から提供されている ↩
-
本来
iptables-nft
でも同じコマンドで通るはずなのですが,謎.Pull requestには『トランスレータのバグかもね? 追っかけきれてないけど😅』みたいなコメントが見られる. ↩ -
nftablesサポートについてはかなり前からIssueが上がっている様子([feature request] nftables support · Issue #26824 · moby/moby). ↩