Netstatのtcp 4/6
3802 ワード
Netstatが傍受するサービスポートを表示すると、tcp 6の監視しか表示されませんが、サービスはtcp 4のipv 4アドレスでアクセスできるのに、なぜtcp 4の傍受が表示されないのでしょうか.
sshdが傍受する22ポートを例に挙げると、
# netstat -tlnp | grep :22
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1444/sshd
tcp6 0 0 :::22 :::* LISTEN 1444/sshd
netstatは、sshdがipv 4のアドレスを傍受するとともに、ipv 6のアドレスを傍受することを示す.
httpdプロセスを見てみましょう
# netstat -tlnp | grep :80
tcp6 0 0 :::80 :::* LISTEN 19837/httpd
しかし、ipv 6に傍受されているアドレスのみが表示されていることに気づいたが、ipv 4を介したアドレスはアクセス可能であるのに.
この現象をどう説明するかを見てみましょう.
まず、ipv 6を閉じてhttpdを再起動します.
# sysctl net.ipv6.conf.all.disable_ipv6=1
# systemctl restart httpd
httpの傍受先を見てみましょう.
# netstat -tlnp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 33697/httpd
IPv 4アドレスのみが傍受されていることがわかります.
では、なぜipv 6がオンになったとき、netstatはsshdのようにtcpとtcp 6の両方を表示するのではなく、tcp 6の傍受のみを表示したのでしょうか.
httpのソースコードをダウンロードしてみましょう.コード
server/listen.c
のopen_Listeners()関数には、関連するコメントがあります./* If we have the unspecified IPv4 address (0.0.0.0) and
* the unspecified IPv6 address (::) is next, we need to
* swap the order of these in the list. We always try to
* bind to IPv6 first, then IPv4, since an IPv6 socket
* might be able to receive IPv4 packets if V6ONLY is not
* enabled, but never the other way around.
* ... ...
*/
上述したように、ipv 6は、実際にはipv 4の要求を処理することができ、V 6 ONLYがオンになっていない場合、逆にそうではない.では、V 6 ONLYはいつオープンしますか?
followコードをmake_に続行sock()関数では、次のコードが見つかります.
#if APR_HAVE_IPV6
#ifdef AP_ENABLE_V4_MAPPED
int v6only_setting = 0;
#else
int v6only_setting = 1;
#endif
#endif
この関数では、リスニングされたアドレスがipv 6である場合、IPV 6_が設定されることがわかります.V 6 ONLYというsocketオプション、今、肝心なのはAP_を見ることですENABLE_V4_MAPPEEDはどのように定義されていますか.
configure(コード数で直接取得した場合、このファイルはなく、configure.ac/inファイルのみ)ファイルでは、次のことがわかります.
# Check whether --enable-v4-mapped was given.
if test "${enable_v4_mapped+set}" = set; then :
enableval=$enable_v4_mapped;
v4mapped=$enableval
else
case $host in
*freebsd5*|*netbsd*|*openbsd*)
v4mapped=no
;;
*)
v4mapped=yes
;;
esac
if ap_mpm_is_enabled winnt; then
v4mapped=no
fi
fi
if test $v4mapped = "yes" -a $ac_cv_define_APR_HAVE_IPV6 = "yes"; then
$as_echo "#define AP_ENABLE_V4_MAPPED 1" >>confdefs.h
したがって、Linuxでは、デフォルトでは、AP_ENABLE_V4_MAPPEEDが1であると、httpdはipv 6を直接傍受します.このとき、ipv 6のsocketはipv 4の要求を処理することができるからです.またbind()システム呼び出しは、ユーザ空間のプロセスに対してipv 6がオンになっていない場合を透過的に処理し、ipv 4が傍受される.
一方、httpdをコンパイルするときに
--disable-v4-mapped
パラメータを使用してipv 4 mappedを禁止すると、デフォルトでは、ipv 6のみを傍受するのではなく、ipv 4とipv 6でそれぞれ傍受されます.以下に示します.# netstat -tlnp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 40576/httpd
tcp6 0 0 :::80 :::* LISTEN 40576/httpd
一方、
/etc/httpd/conf/httpd.conf
においてListen
がipv 6アドレスのみを傍受するように設定されている場合、以下のようにする.Listen :::80
では、netstatはtcp 6のリスニングのみを表示することがわかります.
# systemctl restart httpd
# netstat -tlnp | grep :80
tcp6 0 0 :::80 :::* LISTEN 40980/httpd
そして、ipv 4アドレスでhttpにアクセスできないことに気づきます.
# telnet 192.168.1.100 80
Trying 192.168.1.100...
telnet: Unable to connect to remote host: Connection refused
したがって、netstatはリスニングされたポートをリアルに表示するだけですが、ipv 6は実際にLinuxでもipv 4をサポートしていることに注意してください.