SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|

2024-08-14(Wed) ブリッジ難しくてわかんな~い

  という成果を受けて、同じような要領で1階の書斎まで呼び線を引こうと試したのだが引けなかった。紐を割かなかったのが原因かもしれん。

  DIYが好きな自分は、こういう状況はむしろ楽しみでもあるし「自前でウマいことやったった」感を味わいたいので、業者さんに頼む気にはならないのだが、ウマくいかなければ、それはそれでそれが心労となる面倒な性格である。なんだろうな、関西人の「高ければウマいのは当たり前」「ウマくても安くなきゃ不満」みたいな気持ちだろうか。知らんけど。

  要するに本当はこうしたいのだが、ケーブルが1本しか敷かれてないので、現状ではこうなっている、ということだ。

  画像の説明  画像の説明

  だが、そこで思いついた。別に2台同時に高速通信する必要はないし、仕事PCを使う時は、必ず主力PCも立ち上げている。その条件なら、ケーブルを追加しなくても、こういうテがあるではないか。

  画像の説明

  主力PCにイーサネットポートを追加し、ブリッジ(≒スイッチ、≠ルータ)の役割をさせ、仕事PCの通信を中継をさせればいい。手元には100MbpsのUSBイーサしかないが、ちょっと調べたらイマドキはUSB3.0の1Gbpsのモノも千円チョイで買えるようだ。普通に思考すればギガビットのスイッチに置き換えるのが普通の思考であることはわかっているが、上記の方法ならば必要のない時には電源が切れるという利点がある。まぁ、普通に置き換えるだけじゃ面白くないってのもあるんだが。

  で、ここからが本題。USBイーサを挿したら、主力PC内に仮想ブリッジを設定するのであるが、以前からこのブリッジの設定について、納得のいっていない点があるのだ。なんでブリッジデバイスにIPアドレス付いちゃってんの?

  画像の説明

  ブリッジの設定自体は、GUIからチョイチョイとできてしまい、この状態になる。

# brctl show
bridge name     bridge id               STP enabled     interfaces
bridge0         8000.e86a64573438       no              enp3s0f0     ※本体のイーサポート
                                                        enp4s0f3u4u4 ※USBのイーサポート
 
# ip addr show
enp3s0f0:     <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master bridge0 state UP group default qlen 1000
enp4s0f3u4u4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master bridge0 state UP group default qlen 1000
bridge0:      <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 172.28.0.99/16 brd 172.28.255.255 scope global dynamic noprefixroute bridge0

  んが、ネットワークの基本ではあるが、ブリッジつうのはレイヤ2であるから、それ自体にIPアドレスは付かないはずなのだ。同じ理屈でスイッチングハブにもIPアドレスは付かない。スマートスイッチだと管理用のIPアドレスが付くかもしれないが、それは意味が違う。なのに、現状を絵に描くとこう。

  画像の説明

  自分のイメージ的にはこう、もしくは、こう、だと思えるのだが。

  画像の説明  画像の説明

  動いてんだから問題ないじゃん、という考え方もあろうが、サポートでメシ食っている人間としては、その指向はあまりよろしくないので、少し突き詰めてみる。んが、現状の物理デバイスをネタに突き詰めてもいいのだが、実はdockerのコンテナ環境もブリッジを使い倒している。なので、そっちの方面から深堀りしてみることにする。

  ネタはこないだ導入したミニPCの上の、Fedora40のdocker(podman)環境だ。常々、コンテナを起動するとifconfigってやたら賑やかになるよなぁ、と思ってはいたが、あまり中身を意識したことはなかった。

# ip addr show
podman1:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.89.0.1/24 brd 10.89.0.255 scope global podman1
veth0@if2:  mtu 1500 qdisc noqueue master podman1 state UP group default qlen 1000
podman2:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.89.1.1/24 brd 10.89.1.255 scope global podman2
veth1@if2:  mtu 1500 qdisc noqueue master podman2 state UP group default qlen 1000

  コンテナを立ち上げるとpodmanX, vethXが対で増える。vethXってナニよ? 試しに母艦とコンテナ両方でtcpdumpを採りながら、母艦からコンテナAにpingを打ったら理解できた。基本tcpdumpに-i anyの指定はご法度だが、最近はI/F名も出るようになって便利なんだよな。

# tcpdump -tt -nn -i any icmp
.220946 podman1 Out IP 10.89.0.1 > 10.89.0.2: ICMP echo request, id 174, seq 1, length 64
.220958 veth0   Out IP 10.89.0.1 > 10.89.0.2: ICMP echo request, id 174, seq 1, length 64
.220973 eth0    In  IP 10.89.0.1 > 10.89.0.2: ICMP echo request, id 174, seq 1, length 64
.221012 eth0    Out IP 10.89.0.2 > 10.89.0.1: ICMP echo reply, id 174, seq 1, length 64
.221016 veth0   P   IP 10.89.0.2 > 10.89.0.1: ICMP echo reply, id 174, seq 1, length 64
.221020 podman1 In  IP 10.89.0.2 > 10.89.0.1: ICMP echo reply, id 174, seq 1, length 64

  わかりやすい。行きはpodman1 veth0, eth0の順、帰りはその逆順。veth0て、内部にある外向け(?)の仮想のイーサポートってことだったんだな。Virtual-ETHer。つまり、図にするとこうだ。

  画像の説明

  コンテナ間通信を行う場合は、コンテナの所属するネットワーク名を合わせる。つまり、図にするとこうだ。

  画像の説明

  コンテナBからコンテナAにpingを打ってみる。

$ sudo ping 10.89.0.2
# tcpdump -tt -nn -i any icmp
.724550 eth0  Out IP 10.89.0.3 > 10.89.0.2: ICMP echo request, id 175, seq 1, length 64
.724553 veth1 P   IP 10.89.0.3 > 10.89.0.2: ICMP echo request, id 175, seq 1, length 64
.724554 veth0 Out IP 10.89.0.3 > 10.89.0.2: ICMP echo request, id 175, seq 1, length 64
.724570 veth0 P   IP 10.89.0.2 > 10.89.0.3: ICMP echo reply, id 175, seq 1, length 64
.724571 veth1 Out IP 10.89.0.2 > 10.89.0.3: ICMP echo reply, id 175, seq 1, length 64
.724571 eth0  In  IP 10.89.0.2 > 10.89.0.3: ICMP echo reply, id 175, seq 1, length 64

  さっきと異なり、podman1を経由していない。いやいや、ブリッジを経由しないでパケットが届くわけないよね。逆に考えれば「podman1という名前はブリッジそのものを指しているわけではない」ということになってしまう。podman1は「ブリッジにオマケでくっついているNIC」を指している、と理解すればいいのだろうか?

  podman1のIPアドレスを外してみよう。

# ip addr show podman1
podman1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.89.0.1/24 brd 10.89.0.255 scope global podman1
# ip addr del 10.89.0.1/24 dev podman1
# ip addr show podman1
podman1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000

  こうすると、コンテナAから母艦へのpingは通らなくなるが、コンテナBからコンテナAへのpingは通る。

  今回「なんでブリッジデバイスにIPアドレス付いちゃってんの?」てのが納得のいっていない点なので、podman1にIPアドレスが付いていない状態で、母艦とコンテナ間で通信ができればなんとなく納得できる。んが、IPアドレスを付ける場所がなければどうしようもないので、仮想NICを作ってみる。

# ip link add veth101 type veth peer name veth100
# ip link show
veth100@veth101: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
veth101@veth100: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

  仮想NICはペアで互いにリンクした状態で生成されるようだ。veth101の側にIPアドレスを付け、双方をアップする。

# ip addr add 10.89.0.101/24 dev veth101
# ip link set veth100 up
# ip link set veth101 up
# ip addr show
veth100@veth101: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
veth101@veth100: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.89.0.101/24 scope global veth101

  そして、コンテナBから母艦へpingを打ってみる……が、通らない。そりゃ、veth100/veth101ペアはどこにもつながっていないからだ。veth100の方をブリッジにつなげてやる。

# brctl show
bridge name     bridge id               STP enabled     interfaces
podman1         8000.26d98dba414b       no              veth0
                                                        veth1
# brctl addif podman1 veth100
# brctl show
bridge name     bridge id               STP enabled     interfaces
podman1         8000.26d98dba414b       no              veth0
                                                        veth1
                                                        veth100

  つまり、図にするとこうだ。

  画像の説明

  で、再度コンテナBから母艦へpingを打ってみると……

$ sudo ping 10.89.0.101
# tcpdump -tt -nn -i any icmp
.923306 eth0    Out IP 10.89.0.3 > 10.89.0.101: ICMP echo request, id 173, seq 1, length 64
.923310 veth1   P   IP 10.89.0.3 > 10.89.0.101: ICMP echo request, id 173, seq 1, length 64
.923311 veth100 Out IP 10.89.0.3 > 10.89.0.101: ICMP echo request, id 173, seq 1, length 64
.923311 veth101 In  IP 10.89.0.3 > 10.89.0.101: ICMP echo request, id 173, seq 1, length 64
.923378 veth101 Out IP 10.89.0.101 > 10.89.0.3: ICMP echo reply, id 173, seq 1, length 64
.923379 veth100 P   IP 10.89.0.101 > 10.89.0.3: ICMP echo reply, id 173, seq 1, length 64
.923381 veth1   Out IP 10.89.0.101 > 10.89.0.3: ICMP echo reply, id 173, seq 1, length 64
.923381 eth0    In  IP 10.89.0.101 > 10.89.0.3: ICMP echo reply, id 173, seq 1, length 64

  通ったー!! んが、結局ここまでやってわかったことは「そんな面倒なことしなくて済むように」「ブリッジにはオマケでNICがくっついて」いて、それが「ブリッジデバイスにIPアドレス付いちゃってる」ように見える、ってことっぽい。

  ちなみに、コンテナBは、podman1のアドレスがデフォルトゲートウェイになっていて、DNSもそこを指しているので、そのIPアドレスを外してしまっている現状では、外と通信することができない。デフォルトゲートウェイをveth101にし、別のDNSを参照するようにすれば、外と通信することができるようになる。つまり、podman1のIPアドレスを外し、veth100/veth101で通信するようにした状態も、特に間違っているわけではないということだ。

$ ip route show
default via 10.89.0.1 dev eth0 proto static metric 100 
10.89.0.0/24 dev eth0 proto kernel scope link src 10.89.0.3 
$ sudo ip route delete default via 10.89.0.1
$ ip route show
10.89.0.0/24 dev eth0 proto kernel scope link src 10.89.0.3 
$ sudo ip route add default via 10.89.0.101 dev eth0
$ ip route show
default via 10.89.0.101 dev eth0 
10.89.0.0/24 dev eth0 proto kernel scope link src 10.89.0.3 
 
$ cat /etc/resolv.conf 
search dns.podman
nameserver 10.89.0.1
$ sudo vi /etc/resolv.conf
$ cat /etc/resolv.conf 
search dns.podman
nameserver 172.28.0.1
 
$ curl www.example.com
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
      :

  結局、まぁそうだろうな、というトコロに落ちたわけだが、今回の試行を通じて、コンテナネットワークに関する知見も増えたし、様々なipコマンドの使い方も身に付いた。つまるところプログラミングもネットワークも経験の積み重ねなんだよね。で、肝心の仕事PCへの中継についてもできているのだが、それはまたもう少しネタを揃えて後日まとめるとして……別の意味で「自前でウマいことやったった」状態になっちまったいま、楽しみのような苦しみのようなケーブルの増設作業はどうすんだオレ……。