AndroidのIPv6アドレス, ルーティングテーブルの確認 (モバイルがIPv6接続の時)

# やったこと

Android (SO-01J OSは7.0) のモバイル(LTE)側にIPv6アドレスが払い出されたときの端末の状態を確認してみた。インターフェイスに付与されたアドレスを表示するだけなら手軽に使えるアプリが多くあるのだが、それ以外の詳細な情報を表示するものが見当たらないため、iproute2コマンド郡を使い確認した。なおルート権限なしの範囲の確認なので、ルーティングテーブル周辺の情報取得が主となる。

# 動作環境

端末: ドコモ xperia xz (SO-01J)
OS: Android 7.0 (ビルド 39.2.B.0.256)

- WiFi Off
- モバイル通信
  - APN spmode.ne.jp (ドコモspモード) 
  - プロトコル IPv4/IPv6 ←デフォルトから変更した

以下 `# adb shell` でデバイスのシェルを開いた状態。


## インターフェイス名とIPv6アドレスの表示

```
SO-01J / $ ip -6 address show
↓インターネットアクセス用のインターフェイス
7: rmnet_data0: <UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 240a:6b:450:d426:9ed:b588:a1b7:77e8/64 scope global mngtmpaddr dynamic
       valid_lft forever preferred_lft forever
    inet6 fe80::9ed:b588:a1b7:77e8/64 scope link
       valid_lft forever preferred_lft forever

↓VoLTE用のインターフェイス
14: rmnet_data7: <UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 240a:3:4800:99fa:ad1a:888:1b23:b062/64 scope global mngtmpaddr dynamic
       valid_lft forever preferred_lft forever
    inet6 fe80::ad1a:888:1b23:b062/64 scope link
       valid_lft forever preferred_lft forever
```

インターネット、VoLTEともにIPv6でつながると、マルチインターフェイス・マルチホームの状態になる。それぞれのインターフェイスに目的別のIPv6アドレスがついている。インターネット向けの通信において、どこかのサーバとTCPセッションを張るだけなら送信元アドレスの選択をアプリが気にする必要はないが、SIPアプリのようにアプリ自身がIPアドレスを扱う必要があるものは、アドレスの選択は気をつけないといけない。

## ルーティングテーブルの表示

```
SO-01J:/ $ ip -6 route show [table main]が省略されている
何も表示なし (経路なし)
```

Linuxカーネルではポリシールーティングのため複数のルーティングテーブルを持てる。SO-01Jの実装では、通常使用されるmainテーブルにはIPv6の経路が載ってない。Androidではインターフェイスごとにルーティングテーブルを設けており、ポリシールーティングで振り分ける。例えばVPN通信にも使っており、VPNを張ると仮想インターフェイスとそれに対応するルーティングテーブルを追加する。

ルーティングテーブルの振り分けは、セッション/アプリ(プロセス)/ソケットごとに、マークをつけて区別する。なお、このマークは、IPヘッダ内のTOS, Traffic Classをいじるものでなく、Linuxカーネル内部でパケットを識別するマークとなる。


## ルーティングポリシデータベースの表示

```
SO-01J:/ $　ip rule list
   0:		from all lookup local
   10000:	from all fwmark 0xc0000/0xd0000 lookup 99
   10500:	from all oif dummy0 uidrange 0-0 lookup 1003
   10500:	from all oif rmnet_data0 uidrange 0-0 lookup 1007
   10500:	from all oif rmnet_data7 uidrange 0-0 lookup 1014
   13000:	from all fwmark 0x10063/0x1ffff lookup 97
=> 13000:	from all fwmark 0x101ae/0x1ffff lookup 1007 ← IPv6インターネット
=> 13000:	from all fwmark 0x101af/0x1ffff lookup 1014 ← VoLTE
   14000:	from all oif dummy0 lookup 1003
   14000:	from all oif rmnet_data0 lookup 1007
   14000:	from all oif rmnet_data7 lookup 1014
   15000:	from all fwmark 0x0/0x10000 lookup 99
   16000:	from all fwmark 0x0/0x10000 lookup 98
   17000:	from all fwmark 0x0/0x10000 lookup 97
=> 19000:	from all fwmark 0x1ae/0x1ffff lookup 1007 ← IPv6インターネット
=> 19000:	from all fwmark 0x1af/0x1ffff lookup 1014 ← VoLTE
   22000:	from all fwmark 0x0/0xffff lookup 1007
   23000:	from all fwmark 0x0/0xffff uidrange 0-0 lookup main
   32000:	from all unreachable
```

- IPv6インターネット向けのルーティングテーブルは 1007
- VoLTEトラフィック用のルーティングテーブルは 1014


IPv6インターネット用の1007を表示すると、デフォルト経路 (RAで通知されたP-GWのリンクローカルアドレス)が見える。

```
SO-01J:/ $ ip -6 route show table 1007
240a:6b:450:d426::/64 dev rmnet_data0  proto kernel  metric 256
fe80::/64 dev rmnet_data0  proto kernel  metric 256
default via fe80::f198:3d27:ccab:3080 dev rmnet_data0  proto ra  metric 1024 expires 63905sec hoplimit 255
            ^^^^^^^^^^^^^^^^^^^^^^^^^
```


同じようにVoLTE用のルーティングテーブル 1014 を表示すると

```
SO-01J:/ $ ip -6 route show table 1014
240a:3:4800:99fa::/64 dev rmnet_data7  proto kernel  metric 256
fe80::/64 dev rmnet_data7  proto kernel  metric 256
default via fe80::cd85:8be8:b925:5bbb dev rmnet_data7  proto ra  metric 1024 expires 65420sec hoplimit 255
            ^^^^^^^^^^^^^^^^^^^^^^^^^
```

1007とは異なるリンクローカルアドレスが見える。


なお、`# cat /proc/net/ipv6_route` で全部まとめて表示できるが、人が読むのは少々しんどい。

# 以下、まだ未確認の項目

## DNS

モバイル回線にてプロトコル上はDNS通知は、RA(RDNSS)もしくは、LTEベアラをはるときに各種パラメータをネゴる PCO (protcol confiuration option) で行われる。網から通知されているか、端末がIPv6 DNSを使うように設定されているか、いずれも確認できず。モバイル回線上で通知されたIPv4 DNSは見える。

```
SO-01J:/ $ getprop | grep dns
　[net.dns1]: [110.163.0.5]
　[net.dns2]: [110.163.0.6]
　[net.rmnet_data0.dns1]: [110.163.0.5]
　[net.rmnet_data0.dns2]: [110.163.0.6]
　[net.rmnet_data7.dns1]: []
　[net.rmnet_data7.dns2]: []
```

## テザリング

NDProxyにより rmnet_data0 に割り当てられた /64 が wlan0 側にも払い出される、はずだが、テザリングをON/OFFにするとWAN側が一度切れてしまうので、恒常的にIPv6アドレスが割り当てられるようになってから確認したい。

テザリングをONにすると、wlan0 から入ってきたトラフィックに対して1007 (インターネット接続側のルーティングテーブル)を参照するポリシルーティングルールが挿入された。

```
SO-01J:/ $　ip rule list
...
18000:	from all iif wlan0 lookup 1007
...
```

## VoLTE IMSのIPsec

UE(端末)からP-CSCF(SIPサーバ)までIPsecが張られていて、VoLTEの制御信号が守られているはずだが、racoonコマンドをはじめIPsec関係の確認にはroot権限が必要なので見れていない。