IPv4のみのネットワークを勝手にIPv6対応にする実験

***この内容を自分の管理していないネットワークで行うのはやめましょう***

# 概要

IPv6の勉強中、IPv4からの移行期のための技術として、Teredoというものがあることを知った。
IPv6パケットをUDP/IPv4パケットでカプセル化してトンネルを作ることで、間にIPv4のみのネットワークが挟まっていてもIPv6でのインターネット接続を可能にするらしい。

**もしかして、IPv4でのみインターネット接続できる環境下で、Teredo接続している端末が、自分がIPv6ゲートウェイであるとRAを流してIPv6パケットを転送すれば、そのネットワークに繋がっている他の端末もIPv6でインターネット接続できるのでは？**

ものは試しにやってみた。

# 手順

## 環境

~~~
+------------+
|the Internet|
+------+-----+
       | ※インターネット接続はIPv4のみ
+------+-----+
|   IPv4 GW  |
+------+-----+
       |
       +---------------+
       |               |
+------+-----+  +------+-----+
|   Host A   |  |   Host B   |
+------------+  +------------+

~~~

* Host A:
    * 本記事の主役(いわゆる野良RA)
    * teredoクライアント
    * 勝手にRAをネットワーク内に送信
    * OSはUbuntu Server 18.04.2 (今回はLXDで作成)
* Host B:
    * 動作テスト用端末
    * Ubuntu ServerとWindows 10を用意
    * IPv4/IPv6デュアルスタック
* IPv4 GW:
    * IPv4のみに対応したルータ(今回の環境ではRTX810を使ったが、IPv6関連機能はOffにしている)

Host Aは念の為特権コンテナとして作成した。

~~~
lxc launch images:ubuntu/18.04 TEREDO -c security.privileged=true
~~~

## ネットワーク設定

netplanで設定ファイルを下記のように設定。
~~IPv6アドレスだけ固定する。~~再起動時にmiredoが起動に失敗するので、IPv4アドレスも固定。

~~~:/etc/netplan/99_config.yaml
network:
    ethernets:
        eth0:
            dhcp4: false
            dhcp6: true
            addresses:
            - 192.168.100.254/24
            - fc01:0:0:2::1/64
            gateway4: 192.168.100.1
            nameservers:
                addresses:
                    - 8.8.8.8
    version: 2
~~~

設定を反映する。

~~~
netplan apply
~~~

次にパケット転送を有効にしておく。

~~~:/etc/sysctl.conf(追記/コメントアウト)
net.ipv6.conf.all.forwarding = 1
~~~

~~~
sysctl -p
~~~

## radvdのインストール

まずradvdの設定ファイルを作成。

~~~:/etc/radvd.conf
interface eth0 {
  AdvSendAdvert on;
  MinRtrAdvInterval 3;
  MaxRtrAdvInterval 10;
  AdvOtherConfigFlag on;

  prefix fc01:0:0:2::/64 {
    AdvOnLink on;
    AdvAutonomous on;
    AdvRouterAddr on;
  };
};
~~~

radvdをインストールし、自動起動するように設定。

~~~
apt install radvd
systemctl enable radvd
~~~

## isc-dhcp-serverの設定

IPv6でDNSサーバを通知する方法は、RAに含めるRDNSSと、DHCPv6に含める方法の2つがあるが、今回はDHCPv6を採用。
(AndroidはDHCPv6に非対応で、RDNSSを使うらしい)

isc-dhcp-serverをインストールし、IPv4側のDHCPサービスを無効化。

~~~
apt install isc-dhcp-server

systemctl stop isc-dhcp-server
systemctl disable isc-dhcp-server
~~~

設定ファイルのうち、`isc-dhcp-server`の下記部分をコメントアウト/記入。

~~~:/etc/default/isc-dhcp-server
DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf
DHCPDv6_PID=/var/run/dhcpd6.pid
INTERFACESv6="eth0"
~~~

DHCPv6用設定ファイルの`dhcpd6.conf`に下記を追加。
以下で通知しているのはGoogle Public DNSのIPv6アドレス。

~~~:/etc/dhcp/dhcpd6.conf
subnet6 fc01:0:0:2::/64
{
  option dhcp6.name-servers 2001:4860:4860::8888;
}
~~~

DHCPv6サーバを起動する。

~~~
systemctl enable isc-dhcp-server6
systemctl start isc-dhcp-server6
~~~

## teredoクライアントのインストール

Ubuntuではteredoクライアントのパッケージ名はmiredo。

~~~
apt install miredo
~~~

インストール後、`ip a`で`teredo`というネットワークデバイスが追加されていることを確認。


## iptablesの設定

まずはiptablesをインストール。

~~~
apt install iptables
~~~

`eth0`に入ってきたIPv6パケットをNAPTをかけて`teredo`に転送するよう設定。

~~~
ip6tables -A FORWARD -i eth0 -o teredo -j ACCEPT
ip6tables -A FORWARD -i teredo -o eth0 -j ACCEPT
ip6tables -t nat -A POSTROUTING -s fc01:0:0:2::/64 -o teredo -j MASQUERADE
~~~

永続化のため、`iptables-persistent`をインストール。
インストール中に、「現在のIPv6設定を保存するか？」という問いが出るので、Yesと回答。

~~~
apt install iptables-persistent
~~~

## 確認

同じネットワークにいる別のマシン(Host B)から、IPv6でインターネット接続できることを確認。

~~~
$ ping6 www.google.com
PING www.google.com(nrt20s01-in-x04.1e100.net (2404:6800:4004:806::2004)) 56 data bytes
64 bytes from nrt20s01-in-x04.1e100.net (2404:6800:4004:806::2004): icmp_seq=1 ttl=57 time=508 ms
64 bytes from nrt20s01-in-x04.1e100.net (2404:6800:4004:806::2004): icmp_seq=2 ttl=57 time=9.43 ms
64 bytes from nrt20s01-in-x04.1e100.net (2404:6800:4004:806::2004): icmp_seq=3 ttl=57 time=12.2 ms
64 bytes from nrt20s01-in-x04.1e100.net (2404:6800:4004:806::2004): icmp_seq=4 ttl=57 time=5.38 ms
~~~

1回目は時間がかかるが、その後はそれなりの時間でPINGが返ってきた。

次にWindowsマシンでも確認。
ブラウザでIPv6対応サイトを正常に閲覧できることを確認できた。

IPv4とIPv6を両方有効にした場合、`ipv6-test.com`の表示は下図。
(2001::/32というTeredoのIPv6アドレスが表示されている)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/092bfcc6-0ed1-6c91-b00c-8b3ca828f904.png)

IPv6のみを有効にした場合は下図となった。このときはちゃんとKAME Projectの亀も踊っていた。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/197772/ebabb439-eab8-758b-ec6d-cf6a954e8085.png)

ちなみにSpeed testで測ってみたら、IPv4が80 Mbps程度に対し、IPv6は1 Mbpsしか出なかった。


とはいえ、実験は大成功！
めでたくIPv4のみのネットワークを、IPv6でインターネット接続できるネットワークにできた。

# セキュリティについて

さて、上記の実験で、IPv4ネットワーク内で勝手にIPv6ゲートウェイを作れてしまうことがわかった。
ということは、同じネットワークにIPv6対応端末がいた場合、それらのIPv6通信を全部横取りして盗聴できてしまう。

これは非常にまずい。

私が思いつく対策としては、HTTPSなどエンドツーエンドの暗号化以外には

* 各端末のIPv6機能を無効化する または 手動設定のみにする
    * iPhoneやAndroidでは難しい
* IPv4のルータで、外向きのUDP3544(teredoサーバの待受ポート)をブロックする
    * すべてのteredo通信ができなくなるので、正当なteredoの利用もできなくなる
* 無線LANなら、クライアント間の通信を遮断する

ぐらいしかないのだが、やはり不正RAのセキュリティ問題はすでに懸念されているようで、次のような資料が見つかった。

* [Rogue IPv6 Router Advertisement Problem Statement](https://tools.ietf.org/html/rfc6104)
* [IPv6セキュリティ ～問題点と対策～](https://www.nic.ad.jp/ja/newsletter/No54/0800.html)
* [点検! IPv6のセキュリティープロトコル挙動の観点からー](https://www.nic.ad.jp/ja/materials/iw/2009/proceedings/h5/iw2009-h5-02.pdf)

IPv4における野良DHCPサーバのときと同様、不正RAにもいくつか対策はあるようだが、普及しているものが少ないのが現状な模様。

IPv4ではDHCPリクエストがあって初めて野良DHCPサーバが通信に介入できるのに対し、
IPv6の場合はいつでも誰でもRAを送信でき、影響範囲が大きくなるのが痛い。