毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。
0. multipass使ってますか?
multipassは、仮想マシン管理ツールです。
Linuxでqemuを使いやすくしてくれる仮想化ツールです。
(WindowsだとHyper-V、Macだとhyperkitを使います)
コマンド一つ(multipass launch)で仮想マシンを簡単に動かすことができます。
簡単にLinuxの仮想マシンを使うことができるので、テストしたり練習したりCIに使ったりするのに便利です。
今はDockerなどのコンテナもあるし、いまさら仮想マシンという意見もあると思いますが、k3sを動かす時に使ったり、microk8sを動かしたり、なかなか便利なんです。
途中経過を見ないで結論に飛ぶには、7. まとめ
を見てください
1. しかし、困ったことが....
multipass launch した仮想マシンに接続できるのはmultipassのホストからしか接続できなくて困っていました。
198.51.100.89
は、multipass内だけで利用できる内部ネットワークです。
2. んな訳ないはず
Ubuntu OSのNICからMultipass仮想マシン(QEMU)へ接続できるんだから、以下のようにルーティングを追加すれば外からのパケットだって通るはず!
(正確には外部のNICとMultipassのネットワークをOSが知っていればルーティング可能)
3. Googleで調べた
しかし、つながらないので調べてみました。
Googleで検索したら、いくつかの記事が見つかりました。
multipassでOSX上にmicro-k8sを立てる。 - nがひとつ多い。
https://nnao45.hatenadiary.com/entry/2018/12/20/085706
multipassでつくるmacOS向けのDockerd & K8s環境 - Qiita
https://qiita.com/mumoshu/items/6ff56badcfabe5ab1f49
これらによると、multipassで起動した仮想マシン内でFORWARD ACCEPT
すれば良いようですが、
sudo iptables -P FORWARD ACCEPT
残念ながらこれでは外部から接続することができませんでした。
4. Ubuntu OS内でパケットをルーティング出来るようにする
そもそも、Ubuntu OS内でルーティングできるようにしてないとよくありません。
/etc/sysctl.d/99-sysctl.confファイルに以下を追記しました。
net.ipv4.ip_forward=1
それでも接続できませんでした。
5. iptableを確認する
wiresharkでパケットの流れをチェックしてみるとパケットは転送されているようですが、途中でパケットがどこかに落っこちているようです。そこでmultipassのホスト側のiptablesのフィルタールールを見てみます。
$ sudo iptables -nvL
Chain INPUT (policy ACCEPT 5310 packets, 1486K bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- mpqemubr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 /* generated for Multipass network mpqemubr0 */
2 144 ACCEPT udp -- mpqemubr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 /* generated for Multipass network mpqemubr0 */
0 0 ACCEPT udp -- mpqemubr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67 /* generated for Multipass network mpqemubr0 */
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- mpqemubr0 mpqemubr0 0.0.0.0/0 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */
35 3186 ACCEPT all -- mpqemubr0 * 198.51.100.0/24 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */
31 6005 ACCEPT all -- * mpqemubr0 0.0.0.0/0 198.51.100.0/24 ctstate RELATED,ESTABLISHED /* generated for Multipass network mpqemubr0 */
0 0 REJECT all -- mpqemubr0 * 0.0.0.0/0 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */ reject-with icmp-port-unreachable
90 4680 REJECT all -- * mpqemubr0 0.0.0.0/0 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */ reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 2655 packets, 210K bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * mpqemubr0 0.0.0.0/0 0.0.0.0/0 tcp spt:53 /* generated for Multipass network mpqemubr0 */
2 232 ACCEPT udp -- * mpqemubr0 0.0.0.0/0 0.0.0.0/0 udp spt:53 /* generated for Multipass network mpqemubr0 */
0 0 ACCEPT udp -- * mpqemubr0 0.0.0.0/0 0.0.0.0/0 udp spt:67 /* generated for Multipass network mpqemubr0 */
一見正しく転送されているように見えますが、以下の行がREJECTされていて仮想マシンのIPアドレスに接続しようとするとREJECTの数値が上がります。
0 0 REJECT all -- mpqemubr0 * 0.0.0.0/0 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */ reject-with icmp-port-unreachable
90 4680 REJECT all -- * mpqemubr0 0.0.0.0/0 0.0.0.0/0 /* generated for Multipass network mpqemubr0 */ reject-with icmp-port-unreachable
どうも、このルールがパケットを落っことしているようです。
6. iptablesのルールを削除する
sudo iptables -D FORWARD -o mpqemubr0 -m comment --comment "generated for Multipass network mpqemubr0" -j REJECT --reject-with icmp-port-unreachable
これで繋がるようになりました。
このままだとマシンを再起動するとiptablesが元に戻ってしまいます。
以下のコマンドでiptablesを保存しておきましょう。
sudo apt install iptables-persistent
sudo netfilter-persistent save
7.まとめ
7-1. iptablesのルールを削除する
sudo iptables -D FORWARD -o mpqemubr0 -m comment --comment "generated for Multipass network mpqemubr0" -j REJECT --reject-with icmp-port-unreachable
7-2. OS内でルーティングを有効化
(最近のUbuntuではデフォルトで有効になっているかも)
net.ipv4.ip_forward=1
7-3. Multipassの仮想マシン内でFORWARD ACCEPTする
(仮想マシンによる、不要なものもある)
sudo iptables -P FORWARD ACCEPT
8. 注意事項
このiptablesのルールを削除しても問題ないと思いますが、何か理由があってルールが存在する可能性もあるので変更には注意してください。