Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
49
Help us understand the problem. What is going on with this article?
@fetaro

netstatやlsofでLISTENしているアドレスポートが IPv6と表示されてもIPv4でアクセスできる罠

More than 3 years have passed since last update.

netstatやlsofでLISTENしているポートを調べることはよくあると思いますが、
LISTENしているアドレスポートが IPv6形式で表示されてもIPv4でアクセスできる罠があるので、その説明をします。

罠の説明

例えばCentOS 6.7にてhttpdをyumから入れて、httpdをスタートさせた後に、netstatを実行すると以下の様に表示されます。

# netstat -natp | grep LISTEN
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1084/sshd
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1165/master
tcp        0      0 :::80                       :::*                        LISTEN      2316/httpd
tcp        0      0 :::22                       :::*                        LISTEN      1084/sshd
tcp        0      0 ::1:25                      :::*                        LISTEN      1165/master

sshdについては0.0.0.0:22というIPv4形式の出力と、:::22というIPv6形式の出力の両方が表示されています。
それに対して、httpdは:::80というIPv6形式の出力しか表示されていません。

lsofでも、sshdはIpv4とIPv6の両方がでますが

# lsof -i:22
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1084 root    3u  IPv4  10943      0t0  TCP *:ssh (LISTEN)
sshd    1084 root    4u  IPv6  10954      0t0  TCP *:ssh (LISTEN)

httpdはIPv6のみが表示されます

# lsof -i:80
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   2316   root    4u  IPv6  30431      0t0  TCP *:http (LISTEN)

一見するとhttpdはIPv6でしかアクセスできないように見えます。

しかし!

実際には、IPv4でアクセスできます。

# telnet 192.168.1.241 80
Trying 192.168.1.241...
Connected to 192.168.1.241.
Escape character is '^]'.

パケットキャプチャしてもIPv4で接続しているのがわかります!

キャプチャ.PNG

試しに、OSの設定を変えてIPv6を無効にすると、IPv6表現の表示は消えることが分かりました。

# netstat -napt | grep LISTEN
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      1271/httpd
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      968/sshd
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1059/master

つまり、IPv6が有効な状態でしか起きない問題ということです。

これは一体なぜなのか・・・

この問題は、ググるといくつかヒットします

しかしどこにも明快な答えはないようです。

試しにnetstatのソースコードを軽く検索してみたら、すぐに発見

/*
 * Construct an Internet address representation.
 * If the nflag has been supplied, give
 * numeric value, otherwise try for symbolic name.
 */
static char *
inetname(sa)
    struct sockaddr *sa;
{
    char *cp = 0;
    static char line[NI_MAXHOST];
    struct hostent *hp;
    struct netent *np;
    struct in_addr in;

#ifdef INET6
    if (sa->sa_family == AF_INET6) {
        if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
            &in6addr_any, sizeof(in6addr_any)) == 0)
            strcpy(line, "*");
        else
            getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
                nflag ? NI_NUMERICHOST : 0);
        return (line);
    }
#endif

この部分で文字列を生成しているっぽいけど、#ifdef INET6はIPv6が有効の時のみに通るのでしょう。
そしてif (sa->sa_family == AF_INET6) {の部分は、ソケットアドレス構造体のsa_familyがIPv6のものかどうかを判定する分岐で、これが真だとIPv6の表現を計算して即リターンしているようです。

うーん、つまり、sa構造体をどのように作るかで、文字列表現が変わってるということなのでしょう。

さらに調べていくと、IPV6のmapページに決定的な内容を発見

v4-mapped-on-v6 アドレス型を用いることで、 IPv4 接続も v6 API で扱うことができる。 こうすれば、プログラムは v6 の API をサポートするだけで、 両方のプロトコルをサポートできる。 v4-mapped-on-v6 アドレス型は C ライブラリ内部のアドレスを 扱う関数によって透過的に処理される。
IPv4 と IPv6 はローカルポート空間を共有する。 IPv4 の接続 (またはパケット) を IPv6 ソケットが取得すると、 発信元アドレスが v6 にマップされ、その接続 (パケット) も v6 にマップされる。

さらに

IPV6_V6ONLY (Linux 2.4.21 以降および 2.6 以降)
このフラグを真 (0 以外) に設定すると、そのソケットは IPv6 パケットだけを 送受信するように制限される。 この場合、IPv4 アプリケーションと IPv6 アプリケーションが同時に 一つのポートをバインドできる。
このフラグを偽 (0) に設定すると、そのソケットはパケットの送受信に IPv6 アドレスと IPv4-mapped IPv6 アドレスの両方を使用できる。
引き数はブール値の入った整数へのポインターである。
このフラグのデフォルト値はファイル /proc/sys/net/ipv6/bindv6only の内容により定義される。 このファイルのデフォルト値は 0 (偽) である。

完全にわかった。

:::80というのは0.0.0.0:80IPv4-mapped IPv6アドレスであり、
sshdはIPV6_V6ONLYが偽であるため、IPv4とIPv6の両方のポートが見えたが、
httpdはIPV6_V6ONLYが真であるため、IPv6のポートしか見えないということだ。

結論

OSのIPv6設定が有効の場合で、かつデーモンがIPV6_V6ONLYフラグを真にしてソケットを作成していた場合、
netstatやlsofではIPv6の「IPv4-mapped IPv6アドレス」しか見えていなくても、IPv4でもアクセスできる

49
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
fetaro
データエンジニア

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
49
Help us understand the problem. What is going on with this article?