RaspberryPi 2B を使って Ethernet Converter を作る

#背景
ある機器のWi-Fiが悪いという事実が発覚しました。
というのも、わが家にはインターネットに接続してdアニメ○トアやひかりTVをTVに出力する機器があります。しかし、TV横にあるその機器からルータまでは距離があるため、無線通信を使う必要がありました。そこでWi-Fi接続したところ、通信が安定しない。機器の設定を見直したり、再起動してみたりなどのトラブルシューティングを経て、とても長いLANケーブルでルータに直接接続したところ上手くいった。という経緯です。

この記事はこの問題を解決するべく、より通信の安定する（性能の良い）RaspberryPiを使用して、有線<->無線 の通信を変換（中継）する機能を実現するために戦った備忘録です。
*注）この記事のような事をしなくてもルータや中継機を購入すると解決すると考えられます。

#環境
* RaspberryPi 2B
* I-O DATAのWi-Fiドングル
* Wi-Fiの調子は悪いが、有線の調子はいい機器（以下 機器A）
* Wi-FiはDHCPを使用

```bash
$ uname -a
Linux raspberrypi 5.4.47-v7+ #1322 SMP Wed Jun 17 17:52:39 BST 2020 armv7l GNU/Linux
```

#理想
1. 機器Aは有線で通信している（と認識させたい）
2. RaspberryPiには有線と無線の通信の変換をさせたい（bridgingしたい）
2. DHCPで機器Aにipアドレスを振りたい
3. IPv4 と IPv6 の両方が使いたい

つまり，![EthernetConverter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230044/1fc3b500-2d90-5335-02be-3fca249bb9ec.png)
機器AにDHCPサーバから``192.168.xx.100``のようにIPアドレスを割り当てたい。そしてインターネットにつながるようにしたい。

#初期設定
はじめにWi-Fiに接続したいとおもいます。
予め、電波を拾えているか確認します。
以下のコマンドは利用可能なすべてのWiFiネットワークとその他の有用な情報を表示します。

```bash
$ sudo iwlist wlan0 scan
```

いっぱい出てくるので `| grep 'SSID'` でフィルタリングすると良いかもしれません。

CLIを使用して、RaspberryPiでAPに接続するには以下のようにするのが一般的です。

```bash
$ sudo sh -c "wpa_passphrase '<SSID>' '<password>' >> /etc/wpa_supplicant/wpa_supplicant.conf"
```

\<SSID\>と\<password\>は自分のネットワークのものに置き換えてください。
(詳細な設定も可能ですが多くはこれで大丈夫です)

先程リダイレクトしたファイルの中を見ると、以下のような部分があると思うので指定した部分を消してください。

```:/etc/wpa_supplicant/wpa_supplicant.conf
network={
	ssid="<SSID>"
	#psk="<password>" <-password丸見えなのでこの行を消す
	psk=e7f18aefb9e3004af49cb5a6418a4e54c6bb80ef2f69b95cd1324a5e3ced7cfd
}
```

次にinterfaceの設定です。(あらかじめ`ifconfig`などでRaspberryPiのinterfaceの名前を確認しておいて下さい)
以下に私の設定ファイルの必要な部分を載せるので、必要ならばCopy&Pasteして下さい。

```:/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
allow-hotplug eth0
iface eth0 inet manual

auto wlan0
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
```

設定を反映させるために再起動．

```
$ sudo reboot
```

次にパッケージの update と upgrade をしましょう

```bash
$ sudo apt update -y && sudo apt upgrade -y
```

###*ここから本番 いろいろ試行錯誤していきます*
#作戦1（失敗）
RaspberryPiにはbridge-utilというものがあります。これを使うとかんたんに Ethernet Converter が作れるとネットに書いてありました。

```bash
$ sudo apt install bridge-util #インストール
$ sudo brctl addbr br0
$ sudo brctl addif br0 eth0
$ sudo brctl addif br0 wlan0
can't add wlan0 to bridge br0: Operation not supported
```

wlanとeth間のbridgingは昔はサポートされていたけど、どうにもセキュリティの関係で（？）最近はサポートされていないようです。

#作戦2（半分成功）
Proxy arp と DHCP relay を使用して、同一ネットワークにいるように見せかける。
結論から言うと、IPv4だけ成功します。

先ず、要るものをまとめてインストールします。

```bash
$ sudo apt install dhcp-helper parprouted -y
```

次に、`dhcp-helper` の設定をします。
以下のように設定することで、wlan0を使用して dhcp request をリレーする事ができます。

```:/etc/default/dhcp-helper
# Option flags used to start dhcp-helper.
#
# You will need at least "-s <DHCP server>" or
# "-b <interface> so that dhcp-helper knows where 
# to relay DHCP requests. 
#
# See "man 8 dhcp-helper" for more details.  

DHCPHELPER_OPTS="-b wlan0"
```

次に、最終的には起動時に自動で開始する設定をするのですが、実行タイミングの問題で失敗するので以下の設定を行っておきます。

```bash
$ sudo systemctl disable dhcp-helper
```

最後に、起動時に自動で開始できるように設定します。

```:/etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

## adding bellow ##
ip addr add 192.168.0.203 dev eth0
parprouted wlan0 eth0
sudo systemctl start dhcp-helper
## done ##

exit 0
```

最後の`exit 0`の直上3行を追記しました。
`ip addr add 192.168.0.203 dev eth0`では`eth0`に`192.168.0.203`というアドレスを割り振っています。ここで固定IPを振ることだけが、この手法の心残りです。ここで、アドレス割り振っているのは`parprouted`がサブネットマスク/32に対するルーティングを自動的に作るためです。
`parprouted wlan0 eth0`は`parprouted`の起動です。
`sudo systemctl start dhcp-helper`は`dhcp-helper`の起動です。

**追記**
ipv4のルーティングをONにする旨を書き忘れていました。
`sysctl.conf`のだいたい30行目くらいにある以下の部分のコメントを外します。

```:/etc/sysctl.conf
 Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1 #<- ここのコメントを外す
```

その後， `ip_forward` というファイルに1を書き込みます．

```:/proc/sys/net/ipv4/ip_forward
1 #<- 初期設定では0
```

#作戦3（失敗）
まだ終わってません。IPv4は作戦2で十分だとおもいます。
しかし、IPv6も使いたい…。(以下はまだ成功していません。ほぼメモのようなものです。)

いろいろ試しました
###案1
今回想定している状況では有線LANで接続する機器は1台(数台でもいい)だけなので、IPv6だけでも手動でルーティングテーブルを作れば？(デフォルトゲートウェイは自分の家にあって分かるし)
→失敗。なぜならそもそもルーティングをしようとした時点でサブネットを切る必要がある。家に割り振られているIPv6アドレスは半固定とはいえ、いつ変わるかわからない代物なので決め打ちしてサブネットを切るのには抵抗がある。（抵抗がなければおそらくこれで成功する。）
###案2
Router Advertisement を発行する。
→案1とほぼ同じ理由で失敗。なぜなら、RAを発行するにはサブネットを切る必要があるから。
###案3
DHCPv6-PD で Router Advertisement を発行する。
→失敗。家のルータはBaffaloの家庭用ルータなので、そんな機能は持ち合わせていない。
###案4
IPv4の時にbridge-utilで失敗したが、Open vSwitch ならまだ可能性があるのでは無いだろうか。
→失敗。RaspberryPi にssh接続しているため、wlan0をbridgeの構成に組み込んだ時点で通信が途絶する。bridgeにipアドレスを割り振ったりしたがそれでも通信途絶した。しかし、成功した場合には今までで一番理想に近いので、今後はこの方針で考える。

#参考
[作戦１(bridge-uril)で参考にさせていただいたサイト](http://www.soramimi.jp/raspberrypi/etherconv/)
[作戦2(proxy arp + dhcp relay)で参考にさせていただいたサイト](http://rufas.manyoldmoon.com/blog/1604)