地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Linux】IPv6で待ち受けてるっぽいportの正体

netstatでLISTEN状態のportを確認した時に以下のように表示されることがある

# netstat -antu | grep LISTEN
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1084/sshd
tcp6        0      0 :::80                       :::*                        LISTEN      2316/httpd

(httpdをサンプルとしてる)

httpdのLISTENが:::80でプロトコルがtcp6って形で表示されている。

https://bugs.launchpad.net/ubuntu/+source/net-tools/+bug/657270

https://serverfault.com/questions/755765/httpd-listening-in-ipv6-according-netstat-but-reacheable-in-ipv4

↑でも同じような質問があって回答を見るとどうやらnetstatの仕様らしい。

Linuxで認識してるネットワーク情報にIPv6も有効化されてる場合は仮にIPv4でもバインドされていてもIPv6を優先的に表示するらしい。

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0    172 192.168.1.15:22         192.168.1.38:59862      ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN
udp        0      0 192.168.1.15:68         0.0.0.0:*
udp        0      0 127.0.0.1:323           0.0.0.0:*
udp6       0      0 ::1:323                 :::*

逆に言うとIPv6での接続を待ち受けないプログラム(↑の例でいうとsshdが該当)はこれまで通りtcpっていう表示でIPv4のみで通信が可能。

IPv6ソケットでlistenするとIPv4でも接続可能に:Geekなぺーじ

IPv6に対応させるソケットの生成はとても簡単で通常のIPv4と同様でai_familiyへ"AF_INET6"を指定するだけ。これだけで上記のような現象が起きるサーバプロセスが出来る。

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;    // AF_INET6は、IPv4/IPv6両方を受け付ける。
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;   // bind()する場合は指定する。

当然O_NONBLOCKなりでノンブロッキングIOなんかも変わらずに実現できる。