ラズパイ(Zero2W)を使ってWifiルータを作る

# 経緯
ITロボットエンジニアの皆さんは、[mDNS](https://qiita.com/msrx9/items/b6ca47dd2178c3c9b536) + [VSCode Remote](https://qiita.com/kiwsdiv/items/8eefcbe805e1bf2dbf1f)の組み合わせの強力さは実感されているとは思います。
なんたって、『同じネットワーク内に接続されたロボットのIPアドレスを一々調べたうえで、SSHで接続して**viで編集**して云々』が必要なく、使い慣れたVSCodeとそのプラグインを用いた効率的な開発が可能だからです。
ところが、出先でiPhone13のテザリング環境下で同じことをしたところ、mDNSの名前解決に失敗しました(原因は現状不明)。
そこで、大切に保管しておいたRaspberry Pi Zero 2 Wを活用して、インターネットが使える持ち運び可能なローカルネットワークを構築しました。

# システム構成
## ネットワーク構成図
![ネットワーク図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/3f64a857-a603-fafb-8605-7fa0063fc20d.png)
ここで注意したいのが、設定PCをWifiで接続してしまうと途中で接続できなくなることです。
UARTか、ディスプレイ+USBキーボードなど、ネットワークに依存しない環境で設定すべきです。
また、apt等でインターネット接続が必要なので途中まではUSB-LANも必要です(図中USB(2))。テザリングが出来る状態or全てのパッケージがインストールできたら取り外します。
## ネットワーク設定

|ネットワーク名 |インターフェース名  |IPアドレス  |サブネットマスク  | デフォルトゲートウェイ | 
|---|-----|-------------------|---|---|
| WAN(?)側 | eth0 | iPhoneのDHCPで決定 | ← | ← |
| LAN側 |wlan0 |192.168.0.0~255<br>(DHCPは32～64)|255.255.255.0|192.168.0.1|

# RaspberryPiOSのセットアップ
普通にOSをインストールします。ただ、Zeroはメモリが少ないので(512MB)、LITEの方がいいでしょう。
また、RaspberryPiにSDを差す前に、[シリアルコンソールを有効化しておくと良いと思います。](https://qiita.com/Kunjyaa/items/3b0ac45e9e06ade333ed)

# USBテザリングの設定
[こちらを参照。](https://qiita.com/tetsu_koba/items/15bf748b01ee178fbd4a)
自分の環境では、ipheth-utils、libimobiledevice-utilsだけでなく、usbmuxdも必要でした。
これをしてからUSBでiPhoneに接続すると、eth1でインターネットに接続出来るはずです。

# アクセスポイントの設定
ラズパイのボードに乗っているwlan0をアクセスポイントにします。

## wlan0の固定IP化
```shell
$ sudo vim /etc/dhcpcd.conf
```
自分の環境ではこのファイルが存在しませんでした。インストールしておきます。

```shell
$ sudo apt install dhcpcd5
```

wlan0を固定IP化します。
```conf
interface wlan0
static ip_address=192.168.0.1/24
```
(もちろん、vim以外のエディタでも構いません。私は異教徒にも寛容です。)

## アクセスポイントの追加
hostapdをインストールします。
```shell
sudo sudo apt install hostapd
```
テンプレートをコピーします。
```shell
sudo cp /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf
```
自分の設定に合わせて編集します。
(2.4GHz、WPA2-PSK、CCMP)

```conf
< 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を有効化します。

```shell
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
```
daemonの起動設定をします。

```shell
sudo vim /etc/default/hostapd
```
```conf
# 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アドレスのルーティングや名前解決できないのでインターネットは使えないです。）

```shell
sudo systemctl start hostapd
```
なお、[wpa_supplicantと干渉して再起動後に立ち上がらないケースがあるらしいです。](https://www.mikan-tech.net/entry/raspi-wifi-ap)てか、実際そうなりました。
以下のファイルを編集し、hostapdの起動を遅延させる方法があるようです。
```shell
sudo vim /lib/systemd/system/hostapd.service
```
`ExecStart=`の行に`ExecStartPre=/bin/sleep 5`を追記します。
```conf
ExecStart=/usr/sbin/hostapd -B -P /run/hostapd.pid $DAEMON_OPTS ${DAEMON_CONF} ExecStartPre=/bin/sleep 5
```

# WANへのルーティング・名前解決

dnsmasq、iptablesをインストールします。

```shell
sudo apt isntall dnsmasq iptables
```

## DHCPサーバの設定
```shell
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のアドレス貸出で設定。

```conf
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は再起動すると設定が消えるので、テキストファイルへ書き込みを行っておきます。
```shell
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フォワーディングを有効化します。
```shell
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に以下の一行を追加したところ、正しく動作します。解せない。
```bash
sudo hostapd /etc/hostapd/hostapd.conf &
```

# 更に追記
こんなものを見つけてしまいました。
ぶちゃけ勉強用途以外ならこいつで十分です。
ブラウザから設定可能で、使用感は市販のルータに近いです。
しかも、WANとのルーティングも自動のようです。
（有線LANを接続中はもちろん、その状態でテザリングして有線LANを抜いてもWANに繋がった）

https://raspap.com/