Apple TVから流れてくる変なRAをRaspberry PI + FreeBSDで何とかする話

# 謎のIPv6アドレス

PCのIPアドレス設定を見たところ、見覚えのないIPv6アドレスがついていることに気が付きました。
家のネットワークはOCN光で、IPoEによるIPv6グローバルアドレスが割り当てられるようにRA(Router Advertisement)がルーターから流れています。
ここではそのPrefixを2400:xxxx:yyyy:zzzz::/64とします。
このRAを元に割り振られたIPアドレスはもちろんインターネット接続OKです。

それとは別に
fd76:9f:4fe9:4f39::/64
のアドレスがつけられています。fd**で始まるアドレスはユニークローカルユニキャストアドレスのようです。
しかも、FreeBSDでみると、

<pre>
# ifconfig bridge0
...
inet6 fd76:9f:4fe9:4f39:5a9c:fcff:fe00:5d46 prefixlen 64 detached autoconf
...
</pre>

となってます。detachedだけではなく、deprecatedとついていることもあります。
使えないアドレスっぽいですが、これがついている間はmdnsで名前解決したときに
こちらが優先されてしまって、ちょっと困りものです。

ping XXXX.local などとするとfd*のアドレスが優先されてfd76:9f:4fe9:4f39::/64に向かってpingするのですが、fd76:9f:4fe9:4f39::/64のルーティング情報がないせいもあって、本来のIPv6アドレスからこのサイトローカルアドレスに対してpingしてしまうなんてことになります。pingでこの調子なので、sshなども同じように繋がりません。
$ ping XXXX.local
PING6(56=40+8+8 bytes) 2400:xxxx:yyyy:zzzz:WWWW:XXXX:YYYY:ZZZZ -->
fd76:9f:4fe9:4f39:WWWW:XXXX:YYYY:ZZZZ

せっかくmdnsで名前を引けるようにしているのに、困ったものです。

# Router Advertisementの送信源は一体？

ndp -p を使って、RAの情報を見てみます。

<pre>% ndp -p
fd76:9f:4fe9:4f39::/64 if=bridge0
flags=LAD vltime=1799, pltime=300, expire=17m17s, ref=1
  No advertising router
2400:xxxx:yyyy:zzzz::/64 if=bridge0
flags=LAO vltime=2592000, pltime=604800, expire=29d23h58m9s, ref=1
  advertised by
    fe80::ae44:f2ff:fe91:f9c2%bridge0 (reachable)
fe80::%bridge0/64 if=bridge0
flags=LAO vltime=infinity, pltime=infinity, expire=Never, ref=1
  No advertising router
fe80::%lo0/64 if=lo0
flags=LAO vltime=infinity, pltime=infinity, expire=Never, ref=1
  No advertising router</pre>

>  No advertising router

って、何だそれ...

これでは分からず。
他に何かうまい方法はないかなと思ったところLinuxにndptoolというのがあることを知り、そちらを試してみることに。(FreeBSDのBhyveのゲストとしてRHELを動かしてます。)

<pre># ndptool -i enp0s5 -t ra monitor

NDP payload len 64, from addr: fe80::ae44:f2ff:fe91:f9c2, iface: enp0s5  Type: RA
  Hop limit: 64
  Managed address configuration: no
  Other configuration: yes
  Default router preference: medium
  Router lifetime: 1800s
  Reachable time: 300000ms
  Retransmit time: 10000ms
  Source linkaddr: ac:44:f2:xx:xx:xx
  Prefix: 2400:xxxx:yyyy:zzzz::/64, valid_time: 2592000s, preferred_time: 604800s, on_link: yes, autonomous_addr_conf: yes, router_addr: no
  MTU: 1500
</pre>
→ このSource linkaddr:はルーターのMACアドレスで、Prefixもプロバイダから割り当てられているものなので問題なし。


<pre>NDP payload len 72, from addr: fe80::1834:9cfb:121:c5de, iface: enp0s5
  Type: RA
  Hop limit: 0
  Managed address configuration: no
  Other configuration: no
  Default router preference: medium
  Router lifetime: 0s
  Reachable time: unspecified
  Retransmit time: unspecified
  Source linkaddr: 1c:b3:c9:xx:yy:zz
  Prefix: fd76:9f:4fe9:4f39::/64, valid_time: 1800s, preferred_time: 1800s, on_link: yes, autonomous_addr_conf: yes, router_addr: no
  Route: fdb3:3ab2:7a78::/64, lifetime: 1800s, preference: medium
</pre>

こいつだ！
lifetimeが1800sとずいぶん短いし、routerの情報も入ってません。
Source linkaddrのMACアドレスをこの辺で調べてみます。
https://uic.jp/mac/address/1cb3c9/

> Vendor name: Apple, Inc.

Appleかよ...
我が家のAppleの機械と言えば...
- iPhone 13Pro
- iPhone SE(会社用)
- iPad Pro
- Apple TV (4K版第1世代)

この中でRA出しそうなのは...と調べてみたらApple TVでビンゴ。
というわけで被疑箇所が分かりました。

そういえば、うちはゲーム機のXbox Series X(以下Xbox SX)を持っていますがXbox SXはIPv6に対応していて、ゲームのダウンロードなどに対応していますが、いつの頃からかIPv6使えなくなっているのに気付きました。で、ここで妖しいApple TVを外すとIPv6復活し、Apple TVを繋いだ状態だとIPv6が無効になってしまいます。おそらくApple TVが出しているこのRAが原因ではないかと思いますが、詳しくはエラーなどの表示がないので不明です。

# Appleの見解は？

ネットのフォーラム検索してみると、同じ現象について報告されていました。
しかし、このRAをOFFにする方法は見つからず。
https://discussions.apple.com/thread/252841861
ただ、こちらの海外の報告にあるのは去年なのですが、私が発生に気付いたのは今年の10月位なので、tvOSが16にアップデートされてから発生しているように思います。

ここまで分かったところで、Appleのサポートに問い合わせしてみました。
こんな話しても取り合ってもらえないかなと思いましたが、意外とちゃんと聞いてくれました。

- Apple TVから不審なRAパケットが出ていること、
- RAが出ているとLAN内のIPv6機器に影響を与えて迷惑なこと
- 何のために出ているか分からないので、OFFにしたいこと
を伝えました。

で、パケットのデータ送ったりして、エンジニアにエスカレーションして調査していると連絡もらって、1ヶ月位待ったところ結論は**仕様**でした。
何か意図してこういう動作だと言われたが、結局なんのための機能かは分からず。(面倒なので、あまり詳しく聞かなかったですが)

Apple TV内の問題ではなくて、ネットワーク内の機器に影響与えて迷惑なんだけど、という話をしたら製品フィードバックに入れてくれとのこと。当然のことながら必ず聞いてもらえる訳ではないですが。
というわけで、Apple TV持っててこの現象にあっている人がいたら是非ともフィードバックをw
https://www.apple.com/jp/feedback/

# じゃあ自分でなんとかしよう！

Apple TVから出るRAだけブロックしちゃうパケットフィルタマシンを作ることにします。
省電力で、立ち上げっぱなしでも気にならないものということでここはRaspberry Piを使うことにします。

購入したもの
- Raspberry Pi 4 Type B (8GB)
- BUFFALO LUA4-U3-AGTE-BK (USB3.0 NIC)

メモリ8GBもいらんやろと思いますが、この用途に使わなくなったときやサーバ機として何かしら使えないかなということでリッチなスペックの方を購入しました。

USBのNICを接続して内蔵NICとbridgeを作成、ファイヤウォールの設定をやってRAをブロックするけど、他のパケットはそのままスルーさせることにします。

## OSインストール

Raspberry PIは初めて使うので、検索に頼ります。
このあたりを参考にインストール。といっても、付属のSDカードに入っていたNOOBS使って一旦Raspbianをインストールします。これでEEPROMも更新されるらしいので。

https://gadget.ichmy.0t0.jp/intro/raspi/freebsd/
https://wiki.freebsd.org/arm/Raspberry%20Pi

一旦Raspbianのインストールとアップデートが完了したところで、以下のイメージを書き込んだSDカードを入れて起動します。
https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/13.1/FreeBSD-13.1-RELEASE-arm64-aarch64-RPI.img.xz
で、あっさり起動しました。起動してしまえばFreeBSD/amd64とそう大差ないので、色々設定します。

## ネットワークIFの設定
ネットワーク以外の設定は本題と関係ないので、割愛します。

内蔵NICはgenet0、USB NICはue0で認識するので、この2つでbridgeを作成します。

/etc/rc.conf:
<pre>cloned_interfaces="bridge0"
ifconfig_genet0="up"
ifconfig_ue0="up"
ifconfig_bridge0="addm genet0 addm ue0 up"
ifconfig_bridge0_alias0="inet 192.168.0.15 netmask 255.255.255.0"
ifconfig_bridge0_ipv6="inet6 auto_linklocal accept_rtadv"
defaultrouter="192.168.0.1"
</pre>

でいいかなと思ったところ、ue0を認識するのが遅いのか、起動時に自動でbridgeに追加されないので、以下も追加します。

<pre>autobridge_interfaces="bridge0"
autobridge_bridge0="genet0 ue0"
</pre>

genet0側はルーター側のネットワークに、ue0にはApple TVを接続します。

## IPFWの設定

Firewallは今まではpfを使っていましたが、manを見るとbridgeでフィルタリングするのはipfwの方が良さそうなのでipfwを使うことにします。

/etc/rc.conf:
<pre>firewall_enable="YES"
firewall_type="open"
firewall_logdeny="YES"
</pre>

BridgeでIPFWを使うので、以下も設定します。
(多分net.link.bridge.ipfw=1だけでいいけど、切り分けが面倒なので、色々まとめてonにした...)

/etc/sysctl.conf:
<pre>net.link.ether.ipfw=1
net.link.bridge.ipfw=1
net.link.bridge.ipfw_arp=1
net.link.bridge.pfil_bridge=1
</pre>

ここまで設定したら再起動してipfwが動いていることを確認します。

<pre># ipfw -a list
00100    1134     130520 allow ip from any to any via lo0
00200       0          0 deny ip from any to 127.0.0.0/8
00300       0          0 deny ip from 127.0.0.0/8 to any
00400       0          0 deny ip from any to ::1
00500       0          0 deny ip from ::1 to any
00600    1262      91200 allow ipv6-icmp from :: to ff02::/16
00700    6687     467632 allow ipv6-icmp from fe80::/10 to fe80::/10
00800   43030    4008760 allow ipv6-icmp from fe80::/10 to ff02::/16
00900    1761     177192 allow ipv6-icmp from any to any icmp6types 1
01000   10387     718232 allow ipv6-icmp from any to any icmp6types 2,135,136
65000 8033459 8728192596 allow ip from any to any
65535       3        522 deny ip from any to any
</pre>

さらにApple TV側でネットワークが使えること確認します。
この時点では全く問題なし。

ここでApple TVからのRAのみをブロックするルールを追加します。
RAはICMPv6でtype 134になります。

まずは、MACアドレスベースでできないかなと思って以下のルールを入れてみました。
<pre>ipfw add 590 deny ipv6-icmp from any to any mac 1c:b3:c9:XX:XX:XX any icmp6type 134
</pre>
しかし、これは失敗。

そこでリンクローカルアドレス指定すればいいのではと思って以下を入れてみました。
<pre># ipfw add 690 deny ipv6-icmp from fe80::18d1:c949:e9b5:98e0 to any icmp6type 134
</pre>

<pre># ipfw -a list              
00100    1134     130520 allow ip from any to any via lo0
00200       0          0 deny ip from any to 127.0.0.0/8
00300       0          0 deny ip from 127.0.0.0/8 to any
00400       0          0 deny ip from any to ::1
00500       0          0 deny ip from ::1 to any
00600    1406     101568 allow ipv6-icmp from :: to ff02::/16
00690    1405     122016 deny ipv6-icmp from fe80::18d1:c949:e9b5:98e0 to any icmp6types 134
00700    6933     484792 allow ipv6-icmp from fe80::/10 to fe80::/10
00800   45154    4222480 allow ipv6-icmp from fe80::/10 to ff02::/16
00900    1833     184392 allow ipv6-icmp from any to any icmp6types 1
01000   10817     747904 allow ipv6-icmp from any to any icmp6types 2,135,136
65000 8395144 9160774258 allow ip from any to any
65535       3        522 deny ip from any to any
</pre>

ちゃんとブロックされるようになりました。
そしてネットワーク内の他の機器にfd*のユニークローカルアドレスがつかなくなることも確認できました。

ここまできたら、自動的に設定されるように/etc/rc.confに設定します。

/etc/rc.conf:
<pre>firewall_script="/etc/rc.firewall.local"</pre>

/etc/rc.firewall.local:
``` shell
#!/bin/sh

. /etc/rc.firewall
${fwcmd} add 690 deny ipv6-icmp from fe80::18d1:c949:e9b5:98e0 to any icmp6type 134
```

とりあえずの設置状態。(床置き)
![IMG_2160.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373056/b6626241-529d-813f-0533-6de783b326b5.jpeg)

# 最後に

これでApple TVは普通に使用でき、変なRAがネットワークに流れないようにすることができました。
ただ、何故かしばらく使っているとRasPiでIPv4アドレスが使えなくなります。(IPv6はOK)
こちらは理由が全く分からず困っていましたが、IPアドレスを設定し直すと改善することが分かったので、以下の様なスクリプトを作ってcronで定期的に動かしています。

```shell
#!/bin/sh

ROUTER_ADDR=192.168.0.1
IF_NAME=bridge0

ping -q -c 3 ${ROUTER_ADDR} > /dev/null
if [ $? -eq 0 ]; then
    exit 0
fi

logger 'Reset IP address'
IFCFG_CMDLINE=$(ifconfig ${IF_NAME} | grep 'inet ')
ifconfig ${IF_NAME} ${IFCFG_CMDLINE}
```

これで完成。これでしばらく運用してみようと思います。