Raspberry Pi Zero WをUSB一本でiPhoneとかからいじれるようにする

Twitterに載せたら思ったより検索&拡散されたようなので、初めてQiitaに書いてみる。
#概要
## Raspberry Pi Zero W を入手するまで
長らく技適関係が完全でないとして日本で入手しづらかった、Raspberry Pi Zero W。
先週(7月17日)から順次スイッチサイエンスやKSYなどで取扱が始まっている。

自分は結局日本の代理店の解禁タイミングで確保できず、PIMORONIから購入。10日ほどで届いた。
ちゃんと技適表記も更新されていた。

## Raspberry Pi Zero Wの特徴
Raspberry Pi Zero/Zero Wは他のRaspberry Piにはない特徴として、起動設定をいじることでUSBネットワークカードとして振る舞い、通信をすることができる。

iPhoneにUSBアダプタ経由でLANアダプタをつなぐと有線LAN接続できるところから
「Raspberry Pi Zero系とiPhoneをつないだら認識されるんじゃね？」
って思ってやってみたら動いた。

※注意点として、iPhoneにUSB-LANアダプタを繋いだ場合、基本的にiPhoneの全ての通信がそちらを経由するようになる。
なので、今回はZero WのWiFiで予めインターネットに繋がるようにしておき、
```iPhone -> [USB] -> RPi -> [WiFi] -> インターネット```
と通信できるように設定した。

今回はメインで使用してないiPhone 5sで検証。
よく考えたらミニマムにまとめたわりにiPhone1台で外で使おうとすると…

#ステップ
- WiFiなどの初期設定を済ませる
- USBで通信できるように設定。
- USB側に出現するインターフェイスを固定IPにし、DHCPサーバーを動かす
- USB側から来た通信をWiFi側に流すようルーティングする

#用意するもの
- Raspberry Pi Zero W
 - 無印Zeroでも一応できるはずだが、iPhoneと繋いだときにインターネットに出れないのでWを推奨
- Lightningコネクタを搭載したiPhone/iPadなど
 - iPhone 5sで動作確認
- Apple [Lightning - USB 3カメラアダプタ](https://www.apple.com/jp/shop/product/MK0W2AM/A/lightning-usb-3%E3%82%AB%E3%83%A1%E3%83%A9%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF)
 - 電源供給もできるタイプのカメラアダプタ。DTM用に持ってた。
- 初期設定用のPC、ディスプレイetc.
- USB電源、MicroUSBケーブルなど

# 設定
まずは普通にHDMIモニタとUSBキーボード等を使ってRaspberry Pi Zero W(以下RPi)の初期設定をした。
今回はRaspbian Jessie Liteを使用。

RPi自身がWiFiでインターネットに繋がるようにしておくのと、Avahiが動作するようにしておく。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Raspberry Pi Zero W、十分な速度出てる😇 <a href="https://t.co/0Qlp6Cqssw">pic.twitter.com/0Qlp6Cqssw</a></p>&mdash; しょうポチ@IT系垢 (@jre209harrison) <a href="https://twitter.com/jre209harrison/status/890883509396447232">2017年7月28日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

## 起動オプション設定
続いて、RPiがUSBネットワークとして振る舞うように設定をする。

/boot/config.txtに

```text:/boot/config.txt
dtoverlay=dwc2
```

/boot/cmdline.txtの末尾、rootwaitの後に

```text:/boot/cmdline.txt
modules-load=dwc2,g_ether
```

を追記。

これで起動すると、USBケーブルで接続するだけでネットワークインターフェイスとして認識される。
接続の際は、電源供給用 **ではなく** 、USB機器接続用のMicro USBコネクタとPCを普通のMicro USBケーブルで接続する。
*(Windows 10などでシリアルデバイスとして認識される時があるので、その場合はドライバをあてる)*

## ネットワークインターフェイスの設定
この状態でRPiを起動すると、 **usb0** という名前のネットワークインターフェイスが現れる。
まずはusb0のIPアドレスを固定IPにする。

設定例:

```text:/etc/network/interfaces
auto usb0
iface usb0 inet static
address 192.168.39.1
netmask 255.255.255.0
pre-up iptables-restore < /etc/iptables.ipv4.nat
```
pre-upの行については後述。

## DHCPサーバーの設定
続いて、DHCPサーバーをインストールする。
今回はisc-dhcp-serverを使用。
```$ sudo apt-get install isc-dhcp-server```

DHCPサーバーの設定に関しては調べると出てくるのでそれを参考に…
インターフェイス **usb0** に対してアドレスを振ってくれるように設定。
設定例:

```text:/etc/dhcp/dhcpd.conf
(略)
authorative # コメントアウトを外す
(略)
subnet 192.168.39.0 netmask 255.255.255.0 {
        option routers 192.168.39.1;
        option broadcast-address 192.168.39.255;
        option subnet-mask 255.255.255.0;
        option domain-name "localdomain";
        option domain-name-servers 8.8.8.8;
        default-lease-time 600;
        max-lease-time 7200;
        range 192.168.39.10 192.168.39.20;
}
```

```text:/etc/default/isc-dhcp-server
(略)
#INTERFACE=""
INTERFACE="usb0"
```

## ルーティングの設定
このあたりは調べて出てきたサイトを参考しました。→[Raspberry Piルーター化2](http://akkagi.info/20160628_web/)

まずはパケットフォワーディングの設定。

```text:/etc/sysctl.conf
(略)
net.ipv4.ip_forward=1 #コメントアウトされているので修正
(略)
```

続いてルーティング設定。 usb0の通信をwlan0に中継。

```
$ sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
$ sudo iptables -A FORWARD -i wlan0 -o usb0 -m state --state RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A FORWARD -i usb0 -o wlan0 -j ACCEPT
```

ルーティング設定内容を保存
```$ sudo sh -c 'iptables-save > /etc/iptables.ipv4.nat'```


ネットワーク初期化時にルーティング内容を復元するため、/etc/network/interfacesのusb0の設定の最後に

```text:/etc/network/interfaces
pre-up iptables-restore < /etc/iptables.ipv4.nat
```
のような形で設定。

ここまで来たらほぼ準備完了。再起動またはシャットダウンします。

# 動作確認
## PC
まずはWindows PCで動作確認をした。
予めPCのWiFiなど他のネットワーク接続は切っておく。

上にも書いたとおり、Raspberry Pi Zero Wの電源供給用ではなく、USB機器をつなぐ方のMicro USB端子とPCをMicro USBケーブルで接続。

**USB Ethernet/RNDIS Gadget** というネットワークインターフェイスが現れるので、IPアドレスがDHCPで設定した通りに割り振られ、インターネットにも繋がることを確認。

## iPhone (iPad)
iPhoneにUSB Adaptorを接続、Lightningケーブルで電源を供給し、USBホスト端子にRPiを接続。
設定アプリにEthernetという項目が出現し、 **RNDIS/Ethernet Gadget** の設定からIPアドレスが確認できれば準備完了。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Raspberry Pi ZeroがUSB接続NICになることを利用してiPhone(iPad)とつなぐだけの超ミニマルな開発環境できた…<br>ちゃんと認識してくれた…ロマンあふれる…😇 <a href="https://t.co/YrIx0pguu2">pic.twitter.com/YrIx0pguu2</a></p>&mdash; しょうポチ@IT系垢 (@jre209harrison) <a href="https://twitter.com/jre209harrison/status/890911064145010688">2017年7月28日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

あとはSSH接続ソフト(Termius等)や設定次第ではVNCクライアントなどをiPhoneに入れておけばPCもモニタも不要でやりたい放題！
RPiのIPアドレスは固定したIPアドレス(```192.168.XX.1```など)またはBonjour```[ホスト名].local```でアクセス可能。

~~ちなみにiPhoneのインターネットへの通信を中継する形になるのでtcpdumpなどでiPhoneからの通信を覗いたりもできる…~~