Raspberry Pi 3 Model B をブリッジで使用する

手元に何台かの Raspberry Pi や Jetson Nano があり、Raspberry Pi は初期の Model B や B+、2 Model B などもあり、Raspberry Pi OS にはデフォルトでは、USB で使用するタイプの wifi のドライバが入っていないこともあるので、下図のようなネットワーク構成で使いたいなと思いました。

f:id:section27:20211112143349p:plain

こうしたブリッジの構築方法は検索すると bridge-utils を使用したものが多く見つかりますが、セキュリティ上の問題だろうと思いますが、ブリッジインターフェースに wlan0 を追加することができなかったため、他の方法で構築しているサイトを参考に試行錯誤しました。

私のところで成功したのは、以下のパッケージを使うことです。

  • dhcp-helper: Wifi ルータで IP アドレス等の割当を行えるようにします。
  • parprouted: ARP をブリッジします。
  • bcrelay: ブロードキャストをリレーします。

parprouted.service ファイルの作成

最終的には、以下のような /etc/systemd/system/parprouted.service を作成して、OS 起動時にブリッジとして機能するようにしました。

[Unit]
Description=proxy arp routing service
Before=wpa_supplicant.service
Wants=network.target

[Service]
Type=forking
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
# clone the dhcp-allocated IP to eth0 so dhcp-helper will relay for the correct subnet
ExecStartPre=/bin/bash -c '/sbin/ip addr add $(/sbin/ip -4 -br addr show wlan0 | /bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev eth0'
ExecStartPre=/sbin/ip link set dev eth0 up
ExecStartPre=/sbin/ip link set wlan0 promisc on
ExecStartPre=-/usr/sbin/bcrelay -d -i eth0 -o wlan0

# v minus sign
ExecStart=-/usr/sbin/parprouted eth0 wlan0

ExecStopPost=/sbin/ip link set wlan0 promisc off
ExecStopPost=/sbin/ip link set dev eth0 down
ExecStopPost=/bin/bash -c '/sbin/ip addr del $(/sbin/ip -4 -br addr show eth0 | /bin/grep -Po "\\d+\\.\\d+\\.\\d+\\.\\d+")/32 dev eth0'

[Install]
WantedBy=multi-user.target

必要なパッケージのインストール

上述のパッケージをインストールします。

$ sudo apt install -y dhcp-helper parprouted bcrelay 

IP Forward の有効化

/etc/sysctl.conf#net.ipv4.ip_forward=1# を消して IP Forward を有効にします。

eth0 の無効化

ブリッジで使用する eth0 インターフェースには、wifi の wlan0 と同じ IP アドレス (ただしネットマスクは /32) とするため、/etc/dhcpcd.conf の最終行に下の行を追記します。

denyinterfaces eth0

テスト

ここまで設定したら、一度 sudo reboot を実行して再起動してみます。

起動後、ip addr を実行すると、eth0 にアドレスが割り振られていないことがわかると思います。

sudo systemctl start parprouted を実行して、もう一度、ip addr を実行してみてください。今度は、eth0wlan0 と同じ IP アドレスが設定されていることがわかると思います。

有線の eth0 に、Raspberry Pi や Jetson Nano を接続 (Hub 経由で) してください。それぞれに Wifi ルータ等の DHCP サーバから割り当てられた IP アドレスになることが確認できれば成功です。

OS 起動時に parprouted.service が起動するように、sudo systemctl enable parprouted を実行して、sudo reboot で再起動します。

追記

試行錯誤の中でいくつかハマったところがあったので共有します。

wlan0 を promiscuous mode にしなければならない

デフォルトでは、wlan0 は自分宛ての通信のみを処理します。接続された他の IP アドレス宛の通信を処理できるようにするため、/sbin/ip link set wlan0 promisc onpromiscuous mode にする必要がありました。

bcrelay が必要

参考にしていた記事では、bcrelay をインストールするところは明確に記述されているものの、これを起動することについて書かれている記事は少なかったです。 試した限りでは、これは必須だと考えています。

/usr/sbin/bcrelay -d -i eth0 -o wlan0

参考