linux服务端口只在tcp6下开放

1 案例

开启httpd服务

systemctl start httpd 

查看端口开放情况

netstat -nlt

在这里插入图片描述发现80端口只在tcp6下开放,关闭ipv6。

vim /etc/sysctl.conf 
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

立即生效

/sbin/sysctl -p

重启httpd服务

 systemctl restart httpd

查看

在这里插入图片描述

2 分析

可以看到,netstat 显示httpd只监听在 ipv6 的地址。但是,通过 ipv4 的地址明明是可以访问访问的。

httpd 的源码中,在代码 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.

 * ... 省略 ...

 */

上面提到,当 V6ONLY 没有开启的时候,ipv6 实际上是可以处理 ipv4 的。反之不然; 那么 V6ONLY 是在什么时候开启呢?继续 follow 代码到 make_sock() 函数,可以发现如下代码:

#if APR_HAVE_IPV6

#ifdef AP_ENABLE_V4_MAPPED

    int v6only_setting = 0;

#else

    int v6only_setting = 1;

#endif

#endif

在这个函数中,可以看到如果监听的地址是 ipv6,那么会去设置 IPV6_V6ONLY 这个 socket 选项, 现在,关键是看 AP_ENABLE_V4_MAPPED 是怎么定义的。

扫描二维码关注公众号,回复: 15953222 查看本文章

在 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_MAPPED 是 1,那么 httpd 就会直接监听 ipv6, 因为此时 ipv6 的 socket 能够处理 ipv4 的请求;另外,bind() 系统调用会对用户空间的进程透明处理 ipv6 没有开启的情况,此时会监听到 ipv4。

而如果在编译 httpd 的时候使用 --disable-v4-mapped 参数禁止 ipv4 mapped,那么默认情况下, httpd 会分别监听在 ipv4 和 ipv6,而非只监听 ipv6,如下所示:

# 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 设置为只监听 ipv6 地址,如下:

Listen :::80

那么,将可以看到 netstat 只显示 tcp6 的监听:

# systemctl restart httpd

# netstat -tlnp | grep :80

tcp6       0      0 :::80                   :::*                    LISTEN      40980/httpd

并且现在不能通过 ipv4 地址访问 httpd 了。

# telnet 192.168.1.100 80

Trying 192.168.1.100...

telnet: Unable to connect to remote host: Connection refused

所以,netstat 只是很真实的显示监听的端口而已,但是需要注意 ipv6 实际上在 Linux 上也支持 ipv4。

猜你喜欢

转载自blog.csdn.net/ygq13572549874/article/details/131819616