USBポートに差し込むだけ!! VPNで保護されたWi-Fi APの作り方 (RaspberryPi Zero Wを使って)

<img width="910" alt="zeroVPN.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/930ca026-03ee-4e1a-9143-0c5075711dd9.png">

# はじめに
RaspberryPi Zero WをVPNネットワークを利用した手軽で安全なWi-Fiアクセスポイントにする方法を紹介します。完成するとクラウドもしくはオンプレミスのプライベートなネットワークに対して安全に接続することができます。ルーティングテーブルをいじれば、全ての通信をVPN経由にすることももちろん可能です。
またキットを使えば、冒頭の写真のようにUSBポートに差し込むだけで簡単に使うことが出来ます。非常にかっこいいですね。
セキュリティ警察の方々を初め、USBを接続することにセキュリティ上の不安がある方も多いと思いますが、本システムはPCからは電源供給を受けているだけです。また、Raspberry Pi ZeroとPCの接続はタイトルの通りWi-Fiを経由しています。USB経由でのデータのやり取りは一切ありません。
よって、PCからUSB機器への給電すらも禁止されているような場合でも、USB充電器やモバイルバッテリーを繋げて使うこともできます。


![IMG_4498.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/36cce5f2-6851-2834-d773-6d12f4ad04b5.jpeg)
といことで、iPad Proにつなげることも出来ます。
これは強い。可能性は無限大です。



VPNのソフトウェアにはSoftetherVPNを利用します。
そして、SoftetherVPNなどのクラウドサーバー側の諸々の設定には、ROS/IoT向けネットワーク/コンピューティング基盤である[RDBOX](https://github.com/rdbox-intec/rdbox)を使います。いくつかのスクリプトを実行するだけで非常に簡単にクラウド側のサーバを構築できます。デフォルトでは、VPNサーバー、Kubernetes Master、Kubernetes Nodeの3つのサーバーがクラウド上には構築されます。

![GARIBAN_PV_Short.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/d6527718-d034-c30d-fab3-b199856b285a.gif)

Wi-Fiのアクセスポイントとなる、RaspberryPi Zero W用のSDカードへの書き込み及び、各種設定は[RDBOX](https://github.com/rdbox-intec/rdbox)が提供しているSDカードライター[rdboxGARIBAN](https://github.com/rdbox-intec/rdboxGARIBAN)を使うことでWindows/Mac等のGUIで簡単に行なえます。設定された内容を受けてRaspberryPi Zero Wは電源を入れるだけで自動的に構築され、一切SSH等でログインすること無く本機能を使い始めることが出来ます。

# 構成
## 全般
<img width="924" alt="zeroVPN_all_view.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/4a98d8bc-f812-1d33-420e-f40d06fbe56e.png">

こんな感じで繋がってます。RaspberryPi Zero WのAPはNATを噛ませているので、それだけでも少し安全性が高まっています。Raspberry Pi Zero Wから先はVPNで保護された通信が使用されますので安心です。

## 無線LANについて詳細を解説
- RaspberryPi Zero W から インターネットへ
   - wpa_supplicantで既存のWi-Fiに接続します。（既存のWi-Fiは、公衆無線LAN、テザリング、モバイルルータなどを想定。(wlan0)）
- RaspberryPi Zero W と PC
   - hostapdを使ってWi-Fiアクセスポイントを立ち上げます。(awlan1)
   - PCは、立ち上げたWi-Fiアクセスポイントに接続します。

RaspberryPi Zero Wは物理的なWi-Fiのネットワークアダプタ(Broadcom BCM43143)は一つしかありません。しかしこのネットワークアダプタはvirtual wireless interface追加することが可能です。それによって、wpa_supplicantとhostapdの同時使用が可能です。なお、追加可能なインターフェースの種類や数は`/sbin/iw list`コマンドで確認できます。

```bash
	valid interface combinations:
		 * #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
		   total <= 3, #channels <= 2
		 * #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
		   total <= 4, #channels <= 1
```


# 手順
## ハードウェアの組み立て手順
1. ケース兼、電源供給を発注。
   - このキットを使いました。米アマゾンだけでなく、日本でも買えるんですがよく売り切れてます。
      - [Raspberry Pi Zero W USB-A Addon Board - Geekworm](http://raspberrypiwiki.com/Raspberry_Pi_Zero_W_USB-A_Addon_Board)
      - [Amazon.com: Raspberry Pi Zero W USB-A Addon Board V1.1](https://www.amazon.com/dp/B07BK2BR6C)
2. 開封します。内容物はこんな感じです。（RaspberryPi Zero Wは別売りです。）
![IMG_4487.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/189a4b97-cac4-5416-4492-644ab0f2a148.jpeg)
3. 組み立てます。このキット元々はUSB攻撃も出来るよというちょっと物騒な物で、USB通信にも対応しています。しかし今回はそのような機能は全く必要なく、念には念を入れて物理的に接点を塞いでしまいます。あくまでも電源供給ONLYで使用します。
<img width="3024" alt="IMG_4488.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/27a3e975-920c-812e-95aa-04107503bc80.jpeg">
4. 出来上がり。お好みでUSB-C変換アダプターと組み合わせるとApple商品との相性がばっちりです。
![IMG_4489.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/c503729c-aff1-038e-2592-1d13def462aa.jpeg)

## 構築手順
### サーバー側
0. まず、VPNサーバなどを構築します。私達が公開している[チュートリアル](https://github.com/rdbox-intec/rdbox/wiki/tutorials-ja)を参考に構築します。[RDBOX-HQ 構築編の第4章、各サーバの構築](https://github.com/rdbox-intec/rdbox/wiki/setup-rdbox-hq-1-5-servers-step1-ja)のうち、少なくともVPNサーバの構築を完了して下さい。なお、クラウドサービスのブートストラップはAWS、Azure、GCPのメジャーなものに対応しています。**また、VPNに関する各種設定はRaspberryPi Zero Wのセットアップ時に必要になるので忘れないようにしてください。**
   - [AWS](https://github.com/rdbox-intec/rdbox/wiki/setup-rdbox-hq-aws-1-overview-ja)
   - [Azure](https://github.com/rdbox-intec/rdbox/wiki/setup-rdbox-hq-azure-1-overview-ja)
   - [GCP（Google Cloud Platform）](https://github.com/rdbox-intec/rdbox/wiki/setup-rdbox-hq-gcp-1-overview-ja)

### エッジ端末側
#### rdboxGARIBAN導入
1. [rdboxGARIBAN](https://github.com/rdbox-intec/rdboxGARIBAN/releases/latest)をダウンロードandインストールします。
   - Windows版とMac版があります。適切なものを選択して下さい。
2. RDBOXエッジ端末用のSDカードイメージを予めダウンロードしておきます。
   - [ダウンロードリンク](https://github.com/rdbox-intec/rdbox/releases/latest)
   - RaspberryPi版、x86_64レガシーブート版、x86_64uefiブート版がありますが、今回はRaspberryPi Zero W用のSDカードを作るのでRaspberryPi版をダウンロードしてください。
3. rdboxGARIBANを起動します。
<img width="1112" alt="スクリーンショット 2020-07-09 9.13.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/50a1253a-866b-aef6-704d-c2a55cbf2db8.png">

4. 一番左のSelect imageボタンをクリックして、先ほどダウンロードしたRaspberryPi版SDカードイメージファイルを選択します。

5. お使いのPCにSDカードを挿入します。左から2番目のSelect targetボタンをクリックして挿入したSDカードを選択します。なお、この項目はSDカード挿入時に自動的に選択されることもあります。その場合は内容が正しい事を確認して下さい。

#### Set user-dataについての詳細な解説
Set user-dataボタンをクリックして、ホスト名やユーザー名をはじめ、VPNクライアント設定やWi-Fiの接続設定を行います。

1. Create Newをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.16.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/ab56875d-98ac-0147-4357-c65064bfc2f4.png">
2. Enter the cluster name画面では、今回作成するクラスタについての情報を入力します。ここでは適当にnameをrdbox、コメントは何でもいいので適当に入力してNextをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.18.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/4eba1e73-05ed-9e2e-a2a2-554205c09449.png">
3. Select Hardware configuration of this RDBOX画面では、RDBOXエッジ端末のセットアップモードを指定します。今回は`Plan1: APOnly(No Mesh)`を選択して下さい。選択後Nextボタンをクリックします。
<img width="500" alt="スクリーンショット 2020-07-09 9.24.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/53daed45-004b-2cdd-3fa8-8bb979f1de89.png">
4. Select Role of this RDBOX画面では、RDBOXエッジ端末の役割を指定します。今回は`Branch Master`を選択して下さい。選択後Nextボタンをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.26.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/755f8558-4e9a-f3cf-fd61-319463f64b99.png">
5. Enter and Check the installation location画面では、RDBOXエッジ端末の設置場所を指定します。今回は適当にmobile1としてNextボタンをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.28.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/58eeac36-02f2-af73-42cf-158526f1f371.png">
6. Check hostname画面で、再度ホスト名について確認します。問題なければNextボタンをクリックします。
7. Enter User info画面で、ユーザ名やパスワード、ログインに関する情報を入力します。RDBOXではHDMIを繋いで画面経由でログインすること、SSHでパスワードログインすることを全て禁止しているので、鍵ファイルの指定は慎重に行わないと二度とログインできない端末が完成します。全て入力してNextボタンをクリックします。  
<img width="500" alt="スクリーンショット_2020-07-09_9_33_34.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/2820dc2c-6691-72e3-f14b-989ab130eab8.jpeg">
8. Enter environment info画面では、タイムゾーンやロケール、NTPに関する設定を入力します。全て入力してNextボタンをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.35.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/3f55bdc5-0f63-8eb6-42f8-9b3d6ae4b344.png">
9. Slect the connection method from RDBOX to the existing network画面では、RaspberryPi Zero WからルータへのWi-Fi接続方法を指定します。connection methodラジオボタンは、`Wi-Fi`を選択し、SSID、パスフレーズ、国コードを入力します。全て入力してNextボタンをクリックします。  
<img width="500" alt="スクリーンショット_2020-07-09_9_37_16.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/3a3bc118-af8a-72ee-bc3a-c67321e99176.jpeg">
10. Set the HTTP proxy if necessary画面では、プロキシ環境の場合の設定が出来ます。ただし、今回はRDBOXのサポート対象外であるRaspberryPi Zero Wを使っているのでテストが未実施です。問題がない場合はNextボタンをクリックします。  
11. Enter the Wi-Fi setting for the Mesh Network画面では、RDBOXエッジ端末が対応しているメッシュWi-Fi機能についての設定を入力します。ただし、今回のRaspberryPi Zero WでのAPOnlyモードでの構築では未対応な機能になりますので、何でもいいので適当に入力してNextボタンをクリックします。
12. Enter the Wi-Fi setting for the Access Point画面では、PCから接続する、RaspberryPi W ZeroのWi-Fiアクセスポイントに関する情報を入力します。セットアップ後に、ここで指定した情報が必要になります必ず忘れないようにしてください。問題がない場合はNextボタンをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.46.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/09be4097-b24e-6b44-2e36-0f12b1e9bdca.png">
13. Enter VPN infomation画面ではVPNサーバーへの接続方法を入力します。この情報はVPNサーバーセットアップ時に指定したものを使用します。再度確認して下さい。全て入力してNextボタンをクリックします。  
<img width="500" alt="スクリーンショット 2020-07-09 9.52.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/a4eff10b-cc9e-bd6e-2fc5-e6a9b6cd0fb2.png">
14. You join k8s cluster画面では、RDBOXエッジ端末が利用するKubernetesクラスタに参加するためのTokenを入力します。しかし、RaspberryPi Zero Wでは動作不安定であるため動かさないことにします。よってこの項目は適当に何か文字列を入力してNextボタンをクリックします。   
<img width="500" alt="スクリーンショット 2020-07-09 9.53.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/7c12fc65-0404-6fe5-6385-e8d1b5c613c3.png">
15. **一番重要なポイント。**ここまで入力した内容を元に、RDBOXの初期セットアップに必要な情報が全てYAML形式で出力されます。このテキストのうち、`runcmd`以後の項目を次の文字列に置き換えてください。置き換えたらCompliteボタンをクリックしてuser-dataの設定を終了します。  
<img width="500" alt="スクリーンショット 2020-07-09 10.01.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/c51b711b-3339-2884-e879-a44bf12b5283.png">

```bash
  - content: | 
      --- org.rdbox-boot_sub.bash     2020-07-08 09:45:46.033693833 +0900
      +++ rdbox-boot_sub.bash 2020-07-08 09:45:33.773928083 +0900
      @@ -136,7 +136,6 @@ check_batman () {
       check_device_simple () {
         if ! ifconfig eth0 > /dev/null 2>&1; then
           echo "Device named 'eth0' not found."
      -    return 8
         fi
         if ! iwconfig wlan0 > /dev/null 2>&1; then
           echo "Device named 'wlan0' not found. (Error.....)"
    path: /home/ubuntu/sample.patch
runcmd:
  - '/usr/bin/patch /opt/rdbox/boot/rdbox-boot_sub.bash < /home/ubuntu/sample.patch'
  - '/opt/rdbox/boot/rdbox-first_session.bash '
```

- 上記置き換えに関する補足
   - RDBOXは本来、Raspberry Pi Zero Wをサポート対象外としています。それを判定するロジックとして有線LAN（eth0）がない場合に失敗するようにしていますが、今回はパッチファイルで失敗しないように書き換えています。
   - 合わせて、Kubernetesクラスタへの参加をサポートするヘルパー関数`to_run_kubeadm_join_after_communicating_with`の呼び出しも削除しています。


#### 書き込み
1. メイン画面に戻ります。Flash!ボタンをクリックして、SDカードへの書き込みを実施します。  
<img width="500" alt="スクリーンショット 2020-07-09 10.10.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/e82cf4be-d710-ecf3-6c3f-c3e3db1a076e.png">
2. 書き込みが始まります。3分ぐらいお待ち下さい。  
<img width="500" alt="スクリーンショット 2020-07-09 10.11.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/61f8de69-aac4-599f-c311-91a66f58f912.png">
3. 完成です。完成後は本アプリケーションを閉じて、OSに応じた安全な取り外し方法でSDカードを取り外します。   
<img width="600" alt="スクリーンショット 2020-07-09 10.15.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/ec8b3321-98eb-741c-9876-06384d71dcb6.png">


#### 起動
1. SDカードをRaspberryPi Zero Wに挿入します。
2. RaspberryPi ZeroをPCのUSBポートに差し込み通電します。
3. 5〜10分待っていると、Wi-Fiネットワークの一覧に先程指定したWi-FiアクセスポイントのSSIDが表示されます。クリックして接続して下さい。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/7356b5b9-828e-075c-5b43-b7dfcdce8efc.png)

# 使用感
そんなに早くはないです。ただ、デバッグやちょっとしたデモを見せる用途であればなんら問題はないと思います。

# 応用例
今回セットアップしたRaspberryPi Zero Wのルーティングテーブルは、デフォルトではローカルネットワーク宛のパケット以外は既設のWi-Fiに流すようにしてます（速度対策のためです）。これを、全てVPN経由の信頼できる出口からインターネットに出れるように変更することも可能です。速度はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96992/545ef637-c3ff-be23-99f0-b3c652c8baee.png)
（参考までに、計測した場所でルーター直結だと120Mbpsぐらいは出てます。）

- Before

```bash
ubuntu@rdbox-master-mobile1:~$ /sbin/route 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.16.0.1      0.0.0.0         UG    0      0        0 wlan0
172.16.0.0      0.0.0.0         255.255.255.0   U     0      0        0 wlan0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.252.0   U     0      0        0 vpn_rdbox
192.168.170.0   0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.179.0   rdbox-master-00 255.255.255.0   UG    0      0        0 vpn_rdbox
```

- ルーティング変更

```bash
$ sudo /sbin/route delete default
$ sudo /sbin/route add default gw 192.168.0.1
```

- After

```bash
ubuntu@rdbox-master-mobile1:~$ /sbin/route 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         rdbox-vpnserver 0.0.0.0         UG    0      0        0 vpn_rdbox
172.16.0.0      0.0.0.0         255.255.255.0   U     0      0        0 wlan0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.0.0     0.0.0.0         255.255.252.0   U     0      0        0 vpn_rdbox
192.168.170.0   0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.179.0   rdbox-master-00 255.255.255.0   UG    0      0        0 vpn_rdbox
```


# おわりに
OS標準のVPNクライアントは、IPSecやL2TPには対応していますがそれ以外のVPNソフトを使いたいという場合に、本手法は有効な接続手段の一つかと思います。また、ChromebookやiPadなどそもそもVPNアプリの追加インストールが困難な端末にもおすすめです。
いくつものパソコンを使い分けている場合、他のPCやロボットIoT機器も接続したい場合なども、クライアントソフトをインストールせずとも手軽にVPN接続の恩恵を得ることが出来ます。
あとは、
RaspberryPi Zero Wの次期バージョンでの大幅スペックアップを熱望しつつ、この投稿を締めさせて頂きます。