为什么 netstat 对某些服务只显示了 tcp6 监听端口

tags: linux

最近偶尔发现一个比较奇怪的现象,netstat 查看监听的服务端口时,却只显示了 tcp6 的监控, 但是服务明明是可以通过 tcp4 的 ipv4 地址访问的,那为什么没有显示 tcp4 的监听呢?

以 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 既监听在 ipv4 的地址,又监听在 ipv6 的地址。

而再看看 httpd 进程:

# netstat -tlnp | grep :80
tcp6 0 0 :::80 :::* LISTEN 19837/httpd

却发现只显示了监听在 ipv6 的地址上 ,但是,通过 ipv4 的地址明明是可以访问访问的。

下面来看下怎样解释这个现象。

首先,关闭 ipv6 并且重启 httpd:

# sysctl net.ipv6.conf.all.disable_ipv6=1
# systemctl restart httpd

现在,看下 httpd 监听的地址:

# netstat -tlnp | grep :80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 33697/httpd

可以看到,已经只监听到 ipv4 地址了。

那为什么在 ipv6 开启的时候,netstat 只显示了 tcp6 的监听而非像 sshd 那样既显示 tcp 又显示 tcp6 的监听呢?

我们下载 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.
* ... 省略 ...
*/

上面提到,ipv6 实际上是可以处理 ipv4 的请求的当 V6ONLY 没有开启的时候,反之不然; 那么 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 是怎么定义的。

在 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。

只有tcp6的更多相关文章

  1. NFS启动时报错Linux NFS:could not open connection for tcp6

    1.1 启动时出现的错误 [root@znix ~]#/etc/init.d/nfs start Shutting down NFS daemon:                          ...

  2. centos7下关闭sshd的tcp6

    问题现象 不算问题,就是偶然发现新装好的系统默认的sshd服务启动后的监听项有2个,如下图: 想着自己已经明明关闭了ipv6,竟然还起这tcp6...,强迫症犯了,尝试关闭它,百度一眼几乎没有,记录一 ...

  3. docker发现端口是tcp6的 导致无法访问前端

    最近偶尔发现一个比较奇怪的现象,netstat 查看监听的服务端口时,却只显示了 tcp6 的监控, 但是服务明明是可以通过 tcp4 的 ipv4 地址访问的,那为什么没有显示 tcp4 的监听呢? ...

  4. nfs 客户端启动报错rpc.mountd: svc_tli_create: could not open connection for tcp6

    # /etc/init.d/nfs start Starting NFS services: [ OK ] Starting NFS mountd: rpc.mountd: svc_tli_creat ...

  5. 为什么 netstat 对某些服务只显示了 tcp6 监听端口

    最近偶尔发现一个比较奇怪的现象,netstat 查看监听的服务端口时,却只显示了 tcp6 的监控, 但是服务明明是可以通过 tcp4 的 ipv4 地址访问的,那为什么没有显示 tcp4 的监听呢? ...

  6. Docker容器映射到宿主机只有tcp6没有tcp问题

    问题描述: Docker容器映射到宿主机后,查询端口连接只有tcp6没有tcp,通过ipv4地址连接时无法连接成功. 处理方法: 1.检查是否开启ipv4端口转发 sysctl net.ipv4.ip ...

  7. [自翻]fasthttp中文文档(持续更新)

    fasthttp是由valyala编写的声称快于Go官方标准库net/http包十倍的快速HTTP实现.从各方的性能测试结果来看(评测一.评测二),fasthttp作为当下最快的http Go语言包当 ...

  8. Linux网络属性配置

    目录 IP地址分类 如何将Linux主机接入到网络中 网络接口的命名方式 ifcfg系列命令 如何配置主机名 如何配置DNS服务器指向 iproute2系列命令 Linux管理网络服务 永久生效配置路 ...

  9. 完整部署CentOS7.2+OpenStack+kvm 云平台环境(1)--基础环境搭建

    公司在IDC机房有两台很高配置的服务器,计划在上面部署openstack云平台虚拟化环境,用于承载后期开发测试和其他的一些对内业务.以下对openstack的部署过程及其使用做一详细介绍,仅仅依据本人 ...

随机推荐

  1. Java线程 : 线程同步与锁

    一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public ...

  2. 四、Spring中使用@Conditional按照条件注册Bean

    以前其实是写过@Condtional注解的笔记的,这里附上链接: Spring中的@conditional注解 但已经忘记的差不多了,所以今天再重新学习下,可以互补着学习 @Contional:按照一 ...

  3. SQL——JOIN(连接)

    JOIN基于多个表之间的共同字段,把多个表的行结合起来. 一.INNER JOIN 关键字 INNER JOIN关键字:在表中存在至少一个匹配时返回行. 语法如下: SELECT 列名1,列名2... ...

  4. Pycharm专业版配置远程服务器并自动同步代码

    一.使用场景 如果每次都在本机上面写代码,然后传到服务器上面,在服务器上面运行就太麻烦了.这样的方式十分繁琐,效率很低. 因此,希望可以像下面一样操作: 可以直接在本机上码代码 自动将代码同步到远程服 ...

  5. Luogu4240 毒瘤之神的考验 莫比乌斯反演、根号分治

    传送门 首先有\(\varphi(ij) = \frac{\varphi(i) \varphi(j) \gcd(i,j)}{\varphi(\gcd(i,j))}\),把欧拉函数的定义式代入即可证明 ...

  6. 在jenkins中使用shell命令推送当前主机上的docker镜像到远程的Harbor私有仓库

    1.jenkins主机上的docker配置 先在Jenkins主机的docke上配置上Harbor私有仓库地址 cat /etc/docker/daemon.json { "insecure ...

  7. twbsPagination.js分页插件

    分页插件在使用时注意,如果页面中存在其他异步加载的数据,在运行分页方法第一次后,页面上的分页样式与分页中的data数据就是第一次的数据,如果异步加载重新在页面上录入数据,并希望分页继续在新的数据上实现 ...

  8. 创建Core项目使用IdentityServer4

    本文主要参照https://www.bilibili.com/video/av42364337/?p=4 英文帮助文档:https://identityserver4.readthedocs.io/e ...

  9. top 命令 详解

    VIRT:virtual memory usage 虚拟内存 1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等 2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m ...

  10. isolate sqflite demo

    main.dart import 'package:flutter/material.dart'; import 'demo_isolates.dart'; import 'package:rxdar ...