Raspberry Pi3でWPA2-EAP(PEAP)なWi-Fiに接続する

Raspberry Piは個人が使うもので、自分以外の人がアクセスする事は想定しないものです。

しかし大学などでグループで1台を共有するといった事をする場合には、IDやパスワードの取り扱いには配慮が必要です。

今回は、Wi-Fiに接続する方法は他にもまとめられている方が大勢いますが、この点を配慮してWPA2-EAP(PEAP)に接続する方法をまとめました。

> 2020/02/21追記
> この文書の当初の想定は、Raspbian with desktopだけでしたが、Raspberry Pi4 4GBを入手したので、Ubuntu Server 19.10を利用した際の対応方法についても追記しています。

# 対象とする読者

1. 大学・企業などで個人毎のID・パスワードを利用してWi-Fiに接続している (WPA2-EAP(PEAP)を想定)
2. Raspberry Pi3に内蔵されているWi-Fiを利用したい
3. **パスワードをファイルに記述したくない**

とはいえ、設定ファイル全体をコピーされれば、他の機器がWi-Fiに接続することは防げません。
パスワード自体がWi-Fi接続以外の目的で利用される可能性を低くするための方法です。

# パスワードの取り扱い上の注意

パスワードをRaspberry Piのような小型デバイスに入力する際には、**SDカードからパスワードを窃取される可能性**に注意が必要です。例えば、~/.bash_historyファイルには、bashが実行したコマンドのリストが記録されています。

そのため次のような点に注意してください。

* コマンド引数にパスワードを含めない (e.g. $ echo -n "my password")
* ファイル上に読める状態でパスワードを書き残さない

<details><summary>もしbashのコマンドライン上でパスワードを入力してしまった場合</summary>
<blockquote>
<div>パスワードを入力してしまった端末上で <em>$ history -a</em> コマンドを実行して、メモリ上の履歴を書き出してから、<em>$ rm ~/.bash_history</em> のように、~/.bash_historyファイルを削除してください。
</div>
<br />
<div>続いて、<em>$ history</em> コマンドを実行して、画面に表示された履歴にパスワードが出力されていない事を確認してください。
</div>
<br />
<div>
【すぐに.bash_historyファイルを削除しない理由】~/.bash_historyファイルに記録されるタイミングは、通常はshellが終了するタイミングです。history -aでメモリ上の履歴を書き出させています。
他には一度再起動してから~/.bash_historyファイルを削除するといった方法もあります。</div></blockquote></details>

これらの点に注意することで、パスワード自身が漏洩する可能性はかなり低くなります。しかし、設定ファイルに記述するハッシュ化した文字列とIDが漏洩した場合は、第三者がWi-Fiに接続することは可能なため、SDカードの管理は厳重に行なってください。

# 作業の流れ

上記を踏まえて、次のような流れで作業を進めていきます。

1. 設定ファイルの雛形の入手
2. パスワードのハッシュ化
3. 設定ファイルの編集
4. 設定ファイルの/etc以下へのコピー (要: root権限)
5. 再起動 + 確認

## 設定ファイルの雛形の入手

端末ウィンドウを開き、ホームディレクトリ等の書き込み権限のある任意のディレクトリで、任意の名前のファイルを作成します。
(ここから先では、カレントディレクトリに wpa_supplicant.conf ファイルを作成したものとして説明していきます)

```conf:wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
  ssid=""
  priority=1
  proto=RSN
  key_mgmt=WPA-EAP
  pairwise=CCMP
  auth_alg=OPEN
  eap=PEAP
  identity=""
  password=hash:
  phase1="peaplabel=0"
  phase2="auth=MSCHAPV2"
}
```

キーボードを使って手動で入力すると間違いが入り込みやすくなります。
USBメモリなどでCopy&Pasteなどして作成したファイルをコピーしてください。

次の次で説明する[設定ファイルの編集](#設定ファイルの編集)に書かれたで、次の3行を編集すれば、(私のいる大学の環境では)接続できます。

* ssid=
* identity=
* password=hash:

## パスワードのハッシュ化

パスワードを入力するため、手元を盗み見られないように注意してください。
失敗してもやり直せるため、自分のペースで操作をしてください。

```bash
$ read -s pass
********
$ echo -n "$pass" | iconv -t utf16le | openssl md4
$ unset pass
```

```********``` の部分はパスワードを入力しますが、出力されないため、画面上は2行になります。
イメージしずらいと思うので、asciinemaの動画を確認してください。

<script id="asciicast-321876" src="https://asciinema.org/a/321876.js" async></script>

``` ******* ``` の部分がパスワードで、、コマンド履歴(history)にも残りません。

最後の"utf16le"は、"ユー/ティー/エフ/いち/ろく/エル/イー"(英数小文字と数字)です。いち(1)とエル(l)を間違わないようにしてください。

3行目のコマンドを実行結果は、```(stdin)= bd5e04d88e5bb1744a27c78570da12ef```のように画面に出力されます。

この(stdin)=から続く右側の文字列をハッシュ値と呼びます。
このハッシュ値を次のセクションでファイルに記入します。

<details><summary>入力するコマンドの解説</summary><div>
```read -s pass``` に続いてエンターキーを入力して実行すると、入力待ち状態になり、入力された文字をpass変数に入力します。内容は$記号を付けて```$pass```として参照することができますので、```$ echo $pass```によって内容を画面に出力し確認することができます。
</div>
<div>
引数に"-s"オプションを指定することで、画面に入力内容を表示しないよう、指示をしています。
</div>
<div>最終行の```iconv -t utf16le```では、入力された文字列を1文字を16bitで表現する形式に変換しています。端末上はiconvの有無で変化はないように見えますが、実際にはゼロが追加され1文字の長さは16bitになっています。</div>
</details>

<details><summary>ハッシュ値は他人に知られても大丈夫ですか?</summary>
<div>パスワードからハッシュ値は簡単に計算できますが、ハッシュ値からパスワードを特定することはできません。
しかし、予測したパスワードを無数に準備し、同様に計算したハッシュ値との比較から、元のパスワードを推測することはできます。</div>
</details>

## 設定ファイルの編集

wpa_supplicant.conf ファイルを開き、ssid=、 identity=、 password=hash:、で始まる3行を編集します。

```conf:wpa_supplicant.confを編集した例
...
network={
  ssid="xxxx-wifi"
...
  identity="xxxxxxxx"
  password=hash:bd5e04d88e5bb1744a27c78570da12ef
...
}
```

1. ssidは各組織で利用できるものを指定してください。
2. identityはユーザーIDです。
3. password=hash:の後ろはスペースを空けずに先ほど出力したハッシュ値の文字列をコピーします。

## 設定ファイルの/etc以下へのコピー (要: root権限)

作成したファイルを /etc/wpa_supplicant/wpa_supplicant.conf ファイルの名前でコピーします。

```bash
$ sudo cp wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf
```

自分でwpa_supplicant.conf以外の名前のファイルを作成した場合でも、コピー先のファイル名は変更せずwpa_supplicant.confの名称を利用してください。

## 再起動 + 確認

再起動は、GUIでもCUIでも、好きな方法で行なってください。

```bash:CLIからの再起動
$ sudo shutdown -r now
```

再起動後に、画面右上のWi-Fiアイコンから動作状況を確認できます。


# 参考文献
* [Raspberry Pi 3でWifi接続(PEAP, MSCHAPv2)](https://qiita.com/hiroto-yamashita/items/a18bfeb3a71b7c44697d)

# 2020/02/21 追記 - Ubuntu Server 19.10 for Raspberry Pi 3/4 について

Raspberry Pi4を入手したので、4GBバグが修正されたUbuntu Serverを利用しています。

```bash
$ uname -a
Linux ubuntu 5.3.0-1018-raspi2 #20-Ubuntu SMP Mon Feb 3 19:45:46 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 19.10
Release:        19.10
Codename:       eoan
```

改めてこの手順を確認したところ、次のような問題がありました。

1. wpa_supplicantは導入されているものの、iBus(+NetowrkManager)と(-uオプションの指定により)連携するようになっていて、Desktopを想定したと思われる設定になっている点
2. AP(アクセスポイント)に接続した後、dhclient(DHCPクライアント)が自動的には起動しない点

単純な解決方法は次のとおりです。

0. あらかじめ wpa_supplicant.service を停止、無効化させておく
1. このページに記述した方法で /etc/wpa_supplicant/wpa_supplicant.conf を配置する
2. 手動で、wpa_supplicantを起動する (配置したwpa_supplicant.confファイルを指定する)
3. wlan0がUPステータスになった後(```$ ip addr```で確認)、dhclientを手動で起動する 

```bash
$ sudo systemctl stop wpa_supplicant.service
$ sudo systemctl disable wpa_supplicant.service
$ sudo /sbin/wpa_supplicant -B -s -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan0
$ sudo dhclient wlan0
```

これは少し乱暴な方法で、検索すると、systemctlを利用して/lib/systemd配下のwpa_supplicant.serviceファイルを編集したり、dhclient.confを編集するなどして、有効化している例はいくつかみつかると思います。

ただ、そういった方法が良いのか、最終的な解決策は少し検討が必要だと感じました。

以上