ND Proxy設定
IPv6ですが、なぜか無線LANで接続したWindows10だけが不安定で、IPv6通信ができたりできなかったりしました。どうもいちどIPv6通信ができなくなると1分くらいそのまま通信不能で、しばらく待っているとIPv6接続が復活したりします。
同じく無線LANで接続しているAndroidではそのような現象はありません。また有線LANで接続されているLinuxマシンも安定して通信できていました。
理由を調査したところ、通信不能のときはDefault GatewyであるNGNルータのlink localアドレスが解決(Neighbor Discovery)しようとして失敗していることがわかりました。
どうも、NTT東日本のフレッツ網(NGN)のルータは、RS(Route Solicitation)にたいしてRA(Route Advertisement)はくれるがNS(Neighbour Solicitation)にたいしてNA(Neighbour Advertisementは返してくれないようです。
Windows10マシンが保持するNeighborキャッシュがタイムアウトした場合、Windows10はRS(Route Solicit)ではなくNS(Neighbor Solicit)を発行します。しかしNGNルータはRSには返事するけれどもNSには反応しないので、Neighbor解決ができないまま、次に何かのきっかけでRAが送信されるのをただ待つだけという状態になります。
無線環境がよくなくてたまにパケットロストする環境だと、RAがロストしたら再送されないまま長時間待ちぼうけをくらってしまいます。
これはあまりにも不便なので、対策を考えました。いちばん安易な対策は NSにたいして誰かが代理でNAを返してあげる方法です。つまり Neighbor Discovery Proxy、IPv4で言うARP Proxyです。
ndppdというND Proxy専用のユーザランドアプリもあるのですが、ただ1つのアドレスだけをproxyしたいだけならLinux Kernelの設定だけでOKです。
設定対象は VDSLルータに一番近いbrouterが動いているLinuxマシンです。具体的には以下のように設定しました。
1. カーネルパラメータ設定
/etc/sysctl.confを編集して以下を追加する (要 root権限)
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.proxy_ndp = 1
net.ipv6.conf.br0.proxy_ndp = 1
net.ipv6.conf.default.proxy_ndp = 1
net.ipv6.conf.enp3s0.proxy_ndp = 1
以下のコマンドでカーネルパラメータを設定する。
$ sudo sysctl -p |
/etc/sysctl.confに追加しておけば、次の起動時には自動的にカーネルパラメータ設定される。
2. ND Proxyの設定
以下のコマンドでND Proxy設定します
$ su ip -6 neigh add proxy (ルータ link local address fe80::xxxx) dev br0 nud permanent |
Windowsの管理者権限で起動したコマンドプロンプトから、Neighborキャッシュを消去してから pingします
C:> netsh interface ipv6 delete neighbors C:> ping -6 xxxxxxxx |
正しく pingで通信できていることを確認してください。
このままだと次の起動時には設定が消えてしまうので、スクリプトを追加します。
/etc/sysconfig/network の中で シェル変数 IPV6_DEFAULTGW と IPV6_DEFAULTDEVが設定されている前提として、以前に追加した /etc/sysconfig/network-scripts/init.passthru-brouter に追加します。
## read setting of IPV6_DEFAULTGW and IPV6_DEFAULTDEV
. /etc/sysconfig/network
ip -6 neigh add proxy ${IPV6_DEFAULTGW} dev ${IPV6_DEFAULTDEV} nud permanent