読者です 読者をやめる 読者になる 読者になる

ぎじゅつめも

とある工学系学生が学んだことをメモするだけのブログです。

ApacheのIPv6/IPv4の射影仕様について

Apacheを立ち上げて、待ち受けの様子をnetstatで見たところ、IPv6アドレスしか表示されていませんでした。しかしながら、外部からIPv4アドレスを指定してもちゃんとアクセスできたので、どういう仕様になっているのかを調べてみました。

状態確認

netstat -an | grep tcpの結果は以下のとおりです。

f:id:white-hawk:20170422010656p:plain

IPP(631)とssh(22)、SMTP(25)についてはIPv4,IPv6それぞれのアドレスで待ち受けています。しかしながら、Apacheが待ち受けているはずのHTTP(80)に関してはIPv6アドレスしか表示されていません。IPv4も考慮して設定したのにもかかわらずなぜ表示されていないのでしょうか?

これを調査しました。

※ちなみに0.0.0.0,::はそれぞれIPv4,IPv6において自分自身を表すネットワークアドレスで、任意の自身のアドレスで待ち受けていることを表します。127.0.0.1,::1はローカルループバックアドレスで、自分自身から自身のサービスを利用する際に指定するアドレスです。

調査

各ノードのアドレスは以下です。

・クライアントのIPv4アドレス:192.168.11.3

・WebサーバのIPv4アドレス:192.168.11.6

アイアントからこのWebサーバにIPv4でブラウザアクセスしたところ、netstatに以下のような状態が追加されました。

f:id:white-hawk:20170422012013p:plain

今回はコネクションを3つ張ってコンテンツを得ており、それぞれIPv4アドレスを指定してもコネクションを張れていることがわかります。ブラウザでも実際のコテンテンツを取得で来ました。

ただし、netstatでのコネクションの実際のアドレスを見てみると、いわゆるIPv4-mapped IPv6アドレス/IPv4射影IPv6アドレスと呼ばれるアドレスに変換されていることがわかります。つまり、IPv4アドレスでアクセスしてもWebサーバ側のソケットではIPv6アドレスとして処理されています。IPv4射影アドレスとは、一般的に先頭80bitが0、続く16bitが1、残りがIPv4アドレスであるIPv6アドレスです。これはIPv6ノードが、IPv6をサポートしていないIPv4ノードと通信をおこなうための仕組みです。

 

Webサーバ内部での処理はIPv6アドレスで行われていたわけですが、実際にリンクへ流すパケットでは双方がIPv4アドレスを使っていました。

f:id:white-hawk:20170422022219p:plain

結論・考察など

射影アドレスを使っていることから、恐らくApacheIPv6ソケットで通信を待ち受けており、IPv6に対応していないノードからIPv4でアクセスされても処理できるように射影アドレスに変換してサーバ内ではIPv6アドレスとして処理を行うようになっているようです。

つまり、netstatなどの見掛け上はIPv6でしか待ち受けていないように見えてもちゃんと内部的にはIPv4でも処理しているみたいです。(射影がnetstatの結果にどのような形で反映されているのかがなんとなく掴めました)

関連サイト

後日同様のことを調べてらっしゃるサイト様を探したところ、以下のQiita記事が見つかりました。

qiita.com大体疑問点は同じなのですが、ちゃんとnetstatのコードを読んでいらっしゃって、射影アドレスが反映されるフラグがIPV6_V6ONLYにあることまで突き止めていらっしゃい ました。記事によるとこのフラグが真だとIPv6IPv4が分けられるようで、上記のsshやIPPはこれに当たるようです。逆に偽だと今回のように射影されて透過 的に処理できるようになるとのことでした。

 

また、海外でも同様の疑問をお持ちの方がいらっしゃったようです。

askubuntu.com今回の仕様はIPv6-IPv4フォールバック(IPv6でアクセスできなかったらIPv4でアクセスする)機構の特徴があること、それから、IPv4ノードとIPv6ノードでも互いに通信できるような互換のためにありなおかつそれぞれのソケットをもつ問題を解消するためにあると解説されていました。