経緯
ITロボットエンジニアの皆さんは、mDNS + VSCode Remoteの組み合わせの強力さは実感されているとは思います。
なんたって、『同じネットワーク内に接続されたロボットのIPアドレスを一々調べたうえで、SSHで接続してviで編集して云々』が必要なく、使い慣れたVSCodeとそのプラグインを用いた効率的な開発が可能だからです。
ところが、出先でiPhone13のテザリング環境下で同じことをしたところ、mDNSの名前解決に失敗しました(原因は現状不明)。
そこで、大切に保管しておいたRaspberry Pi Zero 2 Wを活用して、インターネットが使える持ち運び可能なローカルネットワークを構築しました。
システム構成
ネットワーク構成図
ここで注意したいのが、設定PCをWifiで接続してしまうと途中で接続できなくなることです。
UARTか、ディスプレイ+USBキーボードなど、ネットワークに依存しない環境で設定すべきです。
また、apt等でインターネット接続が必要なので途中まではUSB-LANも必要です(図中USB(2))。テザリングが出来る状態or全てのパッケージがインストールできたら取り外します。
ネットワーク設定
ネットワーク名 | インターフェース名 | IPアドレス | サブネットマスク | デフォルトゲートウェイ |
---|---|---|---|---|
WAN(?)側 | eth0 | iPhoneのDHCPで決定 | ← | ← |
LAN側 | wlan0 | 192.168.0.0~255 (DHCPは32~64) |
255.255.255.0 | 192.168.0.1 |
RaspberryPiOSのセットアップ
普通にOSをインストールします。ただ、Zeroはメモリが少ないので(512MB)、LITEの方がいいでしょう。
また、RaspberryPiにSDを差す前に、シリアルコンソールを有効化しておくと良いと思います。
USBテザリングの設定
こちらを参照。
自分の環境では、ipheth-utils、libimobiledevice-utilsだけでなく、usbmuxdも必要でした。
これをしてからUSBでiPhoneに接続すると、eth1でインターネットに接続出来るはずです。
アクセスポイントの設定
ラズパイのボードに乗っているwlan0をアクセスポイントにします。
wlan0の固定IP化
$ sudo vim /etc/dhcpcd.conf
自分の環境ではこのファイルが存在しませんでした。インストールしておきます。
$ sudo apt install dhcpcd5
wlan0を固定IP化します。
interface wlan0
static ip_address=192.168.0.1/24
(もちろん、vim以外のエディタでも構いません。私は異教徒にも寛容です。)
アクセスポイントの追加
hostapdをインストールします。
sudo sudo apt install hostapd
テンプレートをコピーします。
sudo cp /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf
自分の設定に合わせて編集します。
(2.4GHz、WPA2-PSK、CCMP)
< ssid=test
---
> # ssid=test
> ssid=My_wifi_bridge
165c166,167
< channel=1
---
> # channel=1
> channel=6
324c326,327
< auth_algs=3
---
> # auth_algs=3
> auth_algs=1
1625a1629
> wpa=2
1645a1650
> wpa_passphrase=<<好きなパスワード>>
1683a1689
> wpa_key_mgmt=WPA-PSK
1702a1709
> rsn_pairwise=CCMP
hostapdを有効化します。
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
daemonの起動設定をします。
sudo vim /etc/default/hostapd
# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration
# file and hostapd will be started during system boot. An example configuration
# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz
#
#DAEMON_CONF=""
# ⇓変更後⇓
DAEMON_CONF="/etc/hostapd/hostapd.conf"
daemonを起動します。ssid "My_wifi_bridge"が表示されるはずです。接続できるか試してみてください。
(IPアドレスのルーティングや名前解決できないのでインターネットは使えないです。)
sudo systemctl start hostapd
なお、wpa_supplicantと干渉して再起動後に立ち上がらないケースがあるらしいです。てか、実際そうなりました。
以下のファイルを編集し、hostapdの起動を遅延させる方法があるようです。
sudo vim /lib/systemd/system/hostapd.service
ExecStart=
の行にExecStartPre=/bin/sleep 5
を追記します。
ExecStart=/usr/sbin/hostapd -B -P /run/hostapd.pid $DAEMON_OPTS ${DAEMON_CONF} ExecStartPre=/bin/sleep 5
WANへのルーティング・名前解決
dnsmasq、iptablesをインストールします。
sudo apt isntall dnsmasq iptables
DHCPサーバの設定
sudo vim /etc/dnsmasq.conf
This is an example of DHCP range where ...
のくだりのとろにDHCPの設定を記載します(コメントアウトされている設定例を活用)。
wlan0にて、192.168.0.32~64(ネットマスク255.255.255.0)を12hのアドレス貸出で設定。
interface=wlan0
dhcp-range=192.168.0.32,192.168.0.64,255.255.255.0,12h
IPマスカレードの有効化設定
192.168.0.~のラズパイ配下のLANからiPhoneテザリング環境のIPアドレスに変換する設定です。iptablesは再起動すると設定が消えるので、テキストファイルへ書き込みを行っておきます。
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
sudo iptables-restore < /etc/iptables.ipv4.nat
IPv4フォワーディングの有効化
IPv4フォワーディングを有効化します。
sudo sysctl -w net.ipv4.ip_forward=1
以上で設定完了です。ローカルネットワークからインターネットへのアクセスが可能で、mDNSが有効であることを確認しました。
おわりに
そもそも、なんでiPhoneのテザリング内でmDNSが使えないのかが良くわかりません。pingは通るので、何らかのブロードキャストパケットが禁止されているとは思うのですが、いかんせんテザリングの設定が隠蔽されているので、原因がわかったとしても対策できないような気がします。
あと、これは愚痴になるんですが、ラズパイのWifi周りの設定が良くも悪くもWindowsじみている気がします。なぜなら、Raspberry Pi ImagerやGUI(もしくはraspi-config)で設定したWifi設定はwpa_supplicantではないところに仕舞われていて、どこに行けば修正・削除できるか分かりづらいからです。(どうやらネットワークマネージャで管理されており、nmtuiというウィザードを使えば良いらしい。せめて設定時になにか出してくれれば見つけるのが楽だったのに。)
その後
なぜか実運用していると繋がらないことが多い。設定等を見直したが、serviceとして実行する場合は動作しないがsudo hostapd /etc/hostapd/hostapd.conf
と入力して手動実行すると動作します。
とりあえず、同じことを自動実行するように/etc/rc.localに以下の一行を追加したところ、正しく動作します。解せない。
sudo hostapd /etc/hostapd/hostapd.conf &
更に追記
こんなものを見つけてしまいました。
ぶちゃけ勉強用途以外ならこいつで十分です。
ブラウザから設定可能で、使用感は市販のルータに近いです。
しかも、WANとのルーティングも自動のようです。
(有線LANを接続中はもちろん、その状態でテザリングして有線LANを抜いてもWANに繋がった)