楽天モバイル(MNO)網内でNAT64/DNS64が利用できる？

追記: iPhoneが正式に楽天モバイルの対応製品になりましたので、iOSとキャリア設定をアップデートして確認したところ、デフォルトでIPv6 onlyおよび464XLAT(CLAT)が有効になったようです。

```console
$ plistutil -i ./Rakuten_jp.bundle/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>CFBundleShortVersionString</key>
        <string>46.1</string>
        <key>CFBundleDeviceFamily</key>
        <string>iPhone</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.Rakuten_jp</string>
        <key>CFBundleName</key>
        <string>Rakuten_jp</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>English</string>
        <key>CFBundleExecutable</key>
        <string>Rakuten_jp</string>
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleVersion</key>
        <string>46.1</string>
</dict>
</plist>

$ plistutil -i ./Rakuten_jp.bundle/carrier.plist
...
        <key>apns</key>
        <array>
                <dict>
                        <key>DefaultProtocolMask</key>
                        <integer>2</integer>
                        <key>password</key>
                        <string></string>
                        <key>type-mask</key>
                        <integer>1081393</integer>
                        <key>AllowedProtocolMaskInRoaming</key>
                        <integer>3</integer>
                        <key>enableXLAT464</key>
                        <true/>
                        <key>username</key>
                        <string></string>
                        <key>apn</key>
                        <string>v6.rakuten.jp</string>
                        <key>AllowedProtocolMask</key>
                        <integer>2</integer>
                </dict>
                <dict>
                        <key>DefaultProtocolMask</key>
                        <integer>2</integer>
                        <key>password</key>
                        <string></string>
                        <key>type-mask</key>
                        <integer>131072</integer>
                        <key>AllowedProtocolMaskInRoaming</key>
                        <integer>3</integer>
                        <key>username</key>
                        <string></string>
                        <key>apn</key>
                        <string>ims</string>
                        <key>AllowedProtocolMask</key>
                        <integer>2</integer>
                </dict>
                <dict>
                        <key>DefaultProtocolMask</key>
                        <integer>2</integer>
                        <key>password</key>
                        <string></string>
                        <key>type-mask</key>
                        <integer>262144</integer>
                        <key>AllowedProtocolMaskInRoaming</key>
                        <integer>3</integer>
                        <key>username</key>
                        <string></string>
                        <key>apn</key>
                        <string></string>
                        <key>AllowedProtocolMask</key>
                        <integer>2</integer>
                </dict>
        </array>
...
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/35c53a60-5ef4-7950-4c07-144e78e62ef3.png" width="300" height="533"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/8a9bbec9-a900-b90e-dc78-33c2e780232c.png" width="300" height="533">
- - -

`ipv4only.arpa`を楽天モバイルのDNSサーバに問い合わせると、AAAAレコード(64:ff9b::c000:aaと64:ff9b::c000:ab)が返ってくるので、コアネットワーク内のCGNAT[^1]はNAT64/DNS64をサポートしているようです。

これを利用してIPv4への接続性を確保しつつ、PDP/PDN TypeをIPv6に指定してIPv6 onlyで使うこともできそうです。

iOSでは、APN構成プロファイルの`DefaultProtocolMask`と`AllowedProtocolMask`の値を2にすることでIPv6 onlyにできるようなので、iPhoneを使ってテストしてみることにしました。

# 動作環境

- OS: iOS 14.4.2
- SIM: Rakuten UN-LIMIT VI

# 構成プロファイル

楽天モバイル(MNO)ではAPN構成プロファイルは提供されていないので、[楽天モバイル(MVNO)の構成プロファイル](https://mobile.rakuten.co.jp/support/apn_setting/rmobile_jp/)を以下のように変更して使用しました。

```diff
--- B_voice.mobileconfig        2021-04-01 17:10:37.698385700 +0900
+++ un_limit.mobileconfig       2021-04-01 17:10:19.541479100 +0900
@@ -5,7 +5,7 @@
        <key>ConsentText</key>
        <dict>
                <key>default</key>
-               <string>楽天モバイルB　通話SIM　APN設定用プロファイル</string>
+               <string>Rakuten UN-LIMIT APN設定用プロファイル</string>
        </dict>
         <key>PayloadContent</key>
         <array>
@@ -13,25 +13,25 @@
                        <key>AttachAPN</key>
                        <dict>
                           <key>Name</key>
-                          <string>rmobile.jp</string>
+                          <string>rakuten.jp</string>
                           <key>AuthenticationType</key>
                           <string>CHAP</string>
-                          <key>Username</key>
-                          <string>rm</string>
-                          <key>Password</key>
-                          <string>0000</string>
+                          <key>DefaultProtocolMask</key>
+                          <integer>2</integer>
+                          <key>AllowedProtocolMask</key>
+                          <integer>2</integer>
                         </dict>
                         <key>APNs</key>
                         <array>
                             <dict>
                                 <key>Name</key>
-                                <string>rmobile.jp</string>
+                                <string>rakuten.jp</string>
                                 <key>AuthenticationType</key>
                                 <string>CHAP</string>
-                                <key>Username</key>
-                                <string>rm</string>
-                                <key>Password</key>
-                                <string>0000</string>
+                                <key>DefaultProtocolMask</key>
+                                <integer>2</integer>
+                                <key>AllowedProtocolMask</key>
+                                <integer>2</integer>
                             </dict>
                         </array>
                 <key>PayloadDescription</key>
@@ -39,29 +39,29 @@
                 <key>PayloadDisplayName</key>
                 <string>Advanced Settings</string>
                 <key>PayloadIdentifier</key>
-                <string>jp.rmobile.cellular</string>
+                <string>jp.rakuten.cellular</string>
                 <key>PayloadOrganization</key>
                 <string>Rakuten, Inc.</string>
                 <key>PayloadType</key>
                 <string>com.apple.cellular</string>
                 <key>PayloadUUID</key>
-                <string>A86FF611-23E7-4B7F-B933-BED09868FAEA</string>
+                <string>EC39D937-4A95-4EC4-A6D5-40D191DA65B4</string>
                 <key>PayloadVersion</key>
                 <integer>1</integer>
             </dict>
         </array>
         <key>PayloadDescription</key>
-        <string>楽天モバイルB　通話SIM　APN設定用プロファイル</string>
+        <string>Rakuten UN-LIMIT APN設定用プロファイル</string>
         <key>PayloadDisplayName</key>
         <string>楽天モバイル</string>
         <key>PayloadIdentifier</key>
-        <string>jp.rmobile</string>
+        <string>jp.rakuten</string>
         <key>PayloadOrganization</key>
         <string>Rakuten, Inc.</string>
         <key>PayloadType</key>
         <string>Configuration</string>
         <key>PayloadUUID</key>
-        <string>D4A0C943-36CB-4773-8D2E-BA3F784743E8</string>
+        <string>C02FCFAB-A3D9-49F2-B9D2-4AA6BD54F3A2</string>
         <key>PayloadVersion</key>
         <integer>1</integer>
 </dict>
```

構成プロファイルで使用されているパラメータについては、[Configuration Profile Reference - Apple Developer](https://developer.apple.com/business/documentation/Configuration-Profile-Reference.pdf)に詳細な説明がありますので、そちらを参照してください。

# インターフェースに付与されたアドレスを確認する

[HE.NET Network Tool‪s](https://networktools.he.net/)を使いました。

- PDP_IP0: WWANインターフェース
- PDP_IP1, IPSEC0, IPSEC1: VoLTE用インターフェース
- BRIDGE100: インターネット共有(テザリング)用インターフェース

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/c9a0d9e1-303a-ae36-4a18-6f729eed45ac.png" width="300" height="533"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/bff6141c-d30d-d03c-b8ac-4e83a8d89d0c.png" width="300" height="533"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/59bb45c2-2664-1030-c04e-64e3f353bf9c.png" width="300" height="533">

# IPv4/IPv6の接続性をテストする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/affcfaa5-1dea-99ee-22d9-7770ee22e244.png" width="300" height="533"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/fdf1dbeb-dd7e-c84d-fe74-683e10a4d108.png" width="300" height="533">

# インターネット共有(テザリング)をテストする

BRIDGE100(fe80::420:6257:731b:b594)から全ノード(ff02::1)宛に送信されたRAを見てみます。
![Screenshot from 2021-04-03 15-18-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73089/df8960f9-81d0-2b68-9c6d-60da84b4391e.png)
iOSのインターネット共有は、IPv4ではNAT/NAPTを利用していますが、IPv6ではアップストリームインターフェース(PDP_IP0)とダウンストリームインターフェース(BRIDGE100)との間でND Proxy[^2]を行って同じプレフィックスを共有しています。

```console
$ nmcli device show wlp1s0
GENERAL.DEVICE:                         wlp1s0
GENERAL.TYPE:                           wifi
GENERAL.HWADDR:                         A4:34:D9:36:A5:2E
GENERAL.MTU:                            1500
GENERAL.STATE:                          100 (connected)
GENERAL.CONNECTION:                     iPhone
GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/2
IP4.GATEWAY:                            --
IP6.ADDRESS[1]:                         240b:c010:421:707:7030:2cd6:27e1:d611/64
IP6.ADDRESS[2]:                         240b:c010:421:707:dad6:512c:67e6:a0f/64
IP6.ADDRESS[3]:                         fe80::a653:e0f5:dfbc:79b5/64
IP6.GATEWAY:                            fe80::420:6257:731b:b594
IP6.ROUTE[1]:                           dst = 240b:c010:421:707::/64, nh = ::, mt = 600
IP6.ROUTE[2]:                           dst = ::/0, nh = fe80::420:6257:731b:b594, mt = 600
IP6.ROUTE[3]:                           dst = ff00::/8, nh = ::, mt = 256, table=255
IP6.ROUTE[4]:                           dst = fe80::/64, nh = ::, mt = 600
IP6.DNS[1]:                             fe80::420:6257:731b:b594

# traceroute -I6 ipv4.google.com
traceroute to ipv4.google.com (64:ff9b::acd9:af2e), 30 hops max, 80 byte packets
 1  240b:c010:421:707:a953:4ccc:4340:a426 (240b:c010:421:707:a953:4ccc:4340:a426)  17.381 ms  17.230 ms  20.311 ms
 2  240b:c010:102:1b58::4 (240b:c010:102:1b58::4)  44.065 ms  55.276 ms  55.187 ms
 3  240b:c010:102:1b58::4 (240b:c010:102:1b58::4)  55.386 ms  55.294 ms  55.204 ms
 4  64:ff9b::ac1d:2fb (64:ff9b::ac1d:2fb)  60.705 ms  60.617 ms  60.679 ms
 5  64:ff9b::677c:3a3 (64:ff9b::677c:3a3)  60.926 ms 64:ff9b::677c:3b1 (64:ff9b::677c:3b1)  60.483 ms  60.741 ms
 6  64:ff9b::677c:3a2 (64:ff9b::677c:3a2)  68.180 ms  55.412 ms  63.909 ms
 7  64:ff9b::677c:30c (64:ff9b::677c:30c)  25.686 ms  36.585 ms  53.889 ms
 8  64:ff9b::4a7d:7634 (64:ff9b::4a7d:7634)  47.875 ms  47.809 ms  48.000 ms
 9  64:ff9b::d155:f445 (64:ff9b::d155:f445)  54.473 ms  54.451 ms  54.664 ms
10  64:ff9b::acfd:42cb (64:ff9b::acfd:42cb)  53.910 ms  53.889 ms  54.366 ms
11  nrt20s19-in-f14.1e100.net (64:ff9b::acd9:af2e)  53.508 ms  53.742 ms  59.398 ms

# traceroute -I ipv6.google.com
traceroute to ipv6.google.com (2404:6800:4004:811::200e), 30 hops max, 80 byte packets
 1  240b:c010:421:707:a953:4ccc:4340:a426 (240b:c010:421:707:a953:4ccc:4340:a426)  5.952 ms  5.868 ms  9.572 ms
 2  240b:c010:102:1b58::4 (240b:c010:102:1b58::4)  54.870 ms  63.850 ms  63.819 ms
 3  240b:c010:102:1b58::4 (240b:c010:102:1b58::4)  64.914 ms  69.564 ms  69.533 ms
 4  240b:c010:102:15e5:0:4:0:598 (240b:c010:102:15e5:0:4:0:598)  69.835 ms  69.804 ms  69.775 ms
 5  240b:c010:105::7225:0:9 (240b:c010:105::7225:0:9)  70.048 ms  80.084 ms  80.052 ms
 6  * * *
 7  240b:c010:125::8123:0:0 (240b:c010:125::8123:0:0)  67.927 ms * *
 8  2001:4860:1:1::14b6 (2001:4860:1:1::14b6)  39.262 ms  39.667 ms  44.520 ms
 9  2001:4860:0:1000::1 (2001:4860:0:1000::1)  39.145 ms  50.849 ms  56.548 ms
10  2001:4860:0:1::42f3 (2001:4860:0:1::42f3)  62.451 ms * *
11  nrt12s29-in-x0e.1e100.net (2404:6800:4004:811::200e)  68.483 ms  74.765 ms  35.871 ms
```

iOS12以降でインターネット共有のために464XLAT(CLAT)が[実装されているらしい](https://www.ietf.org/mail-archive/web/v6ops/current/msg30153.html)のですが、有効にする方法が分かりませんでした。
代わりに[clatd](https://github.com/toreanderson/clatd)を使用して464XLATをテストしました。

```console
# clatd &
Starting clatd v1.5 by Tore Anderson <tore@fud.no>
Performing DNS64-based PLAT prefix discovery (cf. RFC 7050)
Using PLAT (NAT64) prefix: 64:ff9b::/96
Device facing the PLAT: wlp1s0
Attempting to derive a CLAT IPv6 address from an IPv6 address on 'wlp1s0'
Using CLAT IPv4 address: 192.0.0.1
Using CLAT IPv6 address: 240b:c010:421:707:246b:982:6378:0
Checking if this system already has IPv4 connectivity in 10 sec(s)
Enabling IPv6 forwarding
Enabling Proxy-ND for 240b:c010:421:707:246b:982:6378:0 on wlp1s0
Creating and configuring up CLAT device 'clat'
Created persistent tun device clat
Adding IPv4 default route via the CLAT
Starting up TAYGA, using config file '/tmp/cczTe7R0A8'

$ ping -c4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=112 time=36.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=112 time=34.0 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=112 time=52.1 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=112 time=40.2 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 33.966/40.610/52.063/6.983 ms
```

ついでに自宅の回線から上記のホストに対して、内向きの通信(80/tcpとICMPv6 Echo Request)が通るかテストしてみます。

```console
$ nmap -6 240b:c010:421:707:dad6:512c:67e6:a0f
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-03 07:20 JST
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 3.18 seconds

# traceroute -I 240b:c010:421:707:dad6:512c:67e6:a0f
traceroute to 240b:c010:421:707:dad6:512c:67e6:a0f (240b:c010:421:707:dad6:512c:67e6:a0f), 30 hops max, 80 byte packets
 1  240d:1a:****:****:****:****:****:**** (240d:1a:****:****:****:****:****:****)  4.811 ms  5.209 ms  5.162 ms
 2  240d:10:ffff::1 (240d:10:ffff::1)  14.689 ms  14.650 ms  14.611 ms
 3  240d:10:2:107::1 (240d:10:2:107::1)  9.663 ms  9.625 ms  9.584 ms
 4  240d:10:2:559:39:110:252:253 (240d:10:2:559:39:110:252:253)  9.539 ms  9.501 ms  9.462 ms
 5  2001:3b8:102:27:202:213:194:52 (2001:3b8:102:27:202:213:194:52)  14.319 ms  14.279 ms  14.315 ms
 6  2001:7fa:7:1:0:13:8384:1 (2001:7fa:7:1:0:13:8384:1)  10.481 ms  5.879 ms *
 7  240b:c010:115::8223:0:1 (240b:c010:115::8223:0:1)  9.056 ms  9.565 ms  9.432 ms
 8  240b:c010:105::7225:0:3 (240b:c010:105::7225:0:3)  9.319 ms  9.514 ms  9.448 ms
 9  240b:c010:102:15e5:0:4:0:598 (240b:c010:102:15e5:0:4:0:598)  9.105 ms  9.056 ms  9.007 ms
10  * * *
...
30  * * *
```

残念ながら楽天モバイルのコアネットワーク内のどこかでブロックされているようです。

# 参考

- [iPhone/iPad＋IIJmio SIMでIPv6 onlyなモバイル接続環境を作って動作をテストする - Qiita](https://qiita.com/kazinoue/items/e497db84d9b1c6327c50)
- [Revisiting Apple and IPv6 | APNIC Blog](https://blog.apnic.net/2015/07/15/revisiting-apple-and-ipv6/)

[^1]: https://www.soumu.go.jp/main_content/000633425.pdf

[^2]: [darwin-xnu/nd6_prproxy.c at xnu-7195.60.75 · apple/darwin-xnu · GitHub](https://github.com/apple/darwin-xnu/blob/xnu-7195.60.75/bsd/netinet6/nd6_prproxy.c)