自宅のネット環境を IPv6 対応したら SSH や Git でインターネットに接続できなくなって困った話。
現象
「フレッツ回線」「IPv6(※)」「SSH」でインターネットに出ようとした際に、「client_loop: send disconnect: Broken pipe」というエラーが出て接続できない。
※ DS-Lite や MAP-E による IPv4 over IPv6 を設定している場合は IPv4 での SSH 接続でも同様の問題が発生する。
原因
フレッツ網は IPv6 DSCP 値によってパケットを drop してしまうらしく、それによって SSH のパケットが届かなかったため。
DSCP とは
DSCP は IP パケットに含まれる 6bit の値で、パケットの優先度を制御する目的で使われる。1
OpenSSH の DSCP 値
OpenSSH では明示的に設定しなかった場合、対話型セッションでは af21
非対話型セッションでは cs1
が IPQoS
のデフォルト値として利用される。2
明示的に SSH パケットの DSCP 値を設定するには IPQoS
というオプションを指定する。
フレッツ回線での振る舞い
フレッツ回線の仕様では、IPv6 パケットの DSCP 値によってパケットが drop されることがあるらしい。
NTT東日本の技術参考資料 の IP通信網サービスのインタフェース 第三分冊 (第42版) には以下の記載がある。
2.4.4 帯域優先に関する仕様
契約帯域の範囲で優先クラスを利用したIPv6(IPoE)通信が可能となるサービスにて、当該サービス契約者の端末機器からIP通信網に送信されるIPv6パケットにおいて、RFC2474に規定される優先度の指定が可能です。当該サービス契約者の端末機器からIP通信網に送信されるIPv6パケット(IPoE方式)のトラヒッククラスフィールドの先頭6ビットに、DSCP値として8(001000)を指定することで、優先トラヒックとして転送します。
尚、指定された優先度以外が設定されたパケットの転送は保証しません。
どうやら cs1
(001000) 以外の DSCP 値ではパケットの転送は保証されない (= drop される可能性がある?) 模様。また、明示的に記載されていないが、おそらく default
(000000) も大丈夫であろう。
※ ちなみにこれは「フレッツ 光ネクスト編」の記述だが、なぜか「フレッツ 光クロス編」には同様の記述は存在しない。光クロスの場合は drop されないのだろうか?
対処方法
IPv6 通信をする端末ごとに対応する方法と、ルータで対応する方法がある。
端末ごとに対応
SSH の設定ファイルにて DSCP 値を cs1
と明示すればよい。
Host *
IPQoS cs1
IPQoS オプションに値をひとつだけ設定した場合は、対話型セッションと非対話型セッションの両方で設定した値が利用されるので、この場合は両方のセッションで cs1
が使用されることになる。
上述のとおり cs1
か 0
であれば drop されなさそうだが、どちらが良いのかは正直良くわからない。「cs1
は非対話型セッションのデフォルト値にも設定されている値だし」という雑な理由で自分は cs1
を指定しているが、今のところ特に困っていない。
また、類似の記事では IPQoS オプションに none
を設定しているケースが見られるが、 none
の場合は「OS のデフォルト値が使用される」らしいので、 none
よりかは 0
を明示的に指定したほうがよいのではないかと思われる。
ルータで対応
すべての端末で設定をするのは大変な場合は、ルータでパケットの DSCP 値を書き換えてしまうという方法もある。
ググったところ YAMAHA ルータ 3 や EdgeRouter 4 では書き換えができるっぽいことがわかった。