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

最近偶尔发现一个比较奇怪的现象,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 进程:

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

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

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

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

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

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

1 # netstat -tlnp | grep :80
2 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() 函数中, 有相关注释:

1 /* If we have the unspecified IPv4 address (0.0.0.0) and
2  * the unspecified IPv6 address (::) is next, we need to
3  * swap the order of these in the list. We always try to
4  * bind to IPv6 first, then IPv4, since an IPv6 socket
5  * might be able to receive IPv4 packets if V6ONLY is not
6  * enabled, but never the other way around.
7  * ... 省略 ...
8  */

上面提到,ipv6 实际上是可以处理 ipv4 的请求的当 V6ONLY 没有开启的时候,反之不然; 那么 V6ONLY 是在什么时候开启呢?

继续 follow 代码到 make_sock() 函数,可以发现如下代码:

1 #if APR_HAVE_IPV6
2 #ifdef AP_ENABLE_V4_MAPPED
3     int v6only_setting = 0;
4 #else
5     int v6only_setting = 1;
6 #endif
7 #endif

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

在 configure(注意,如果是直接通过代码数获取的,可能没有这个文件,而只有 configure.ac/in 文件)文件中, 可以找到:

 1 # Check whether --enable-v4-mapped was given.
 2 if test "${enable_v4_mapped+set}" = set; then :
 3   enableval=$enable_v4_mapped;
 4   v4mapped=$enableval
 5
 6 else
 7
 8     case $host in
 9     *freebsd5*|*netbsd*|*openbsd*)
10         v4mapped=no
11         ;;
12     *)
13         v4mapped=yes
14         ;;
15     esac
16     if ap_mpm_is_enabled winnt; then
17                 v4mapped=no
18     fi
19
20 fi
21
22
23 if test $v4mapped = "yes" -a $ac_cv_define_APR_HAVE_IPV6 = "yes"; then
24
25 $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,如下所示:

1 # netstat -tlnp | grep :80
2 tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      40576/httpd
3 tcp6       0      0 :::80                   :::*                    LISTEN      40576/httpd

而,如果在 /etc/httpd/conf/httpd.conf 中将 Listen 设置为只监听 ipv6 地址,如下:

1 Listen :::80

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

1 # systemctl restart httpd
2 # netstat -tlnp | grep :80
3 tcp6       0      0 :::80                   :::*                    LISTEN      40980/httpd

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

1 # telnet 192.168.1.100 80
2 Trying 192.168.1.100...
3 telnet: Unable to connect to remote host: Connection refused

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

转自:http://www.chengweiyang.cn/2017/03/05/why-netstat-not-showup-tcp4-socket/

原文地址:https://www.cnblogs.com/sevensd/p/9475976.html

时间: 2024-11-09 20:57:25

为什么 netstat 对某些服务只显示了 tcp6 监听端口的相关文章

Linux对外提供服务 网络连接 端口操作 1.开启服务监听端口 2.设置防火墙,放行访问端口的包 iptables&netfilter 四表五链和通堵策略

应用举例: Linux上安装Tomcat后,客户端要能够访问服务器上的Tomcat 操作: 1.网络操作 本机必须能够ping通目标主机(本地虚拟机或者远程主机) 2.端口操作 1.开启服务监听端口 2.设置防火墙,放行访问该端口的数据包 关键iptables和netfilter: iptables中的四表五链和堵通策略 CentOS6.7端口操作最佳实践: 查看iptables命令的帮助: iptables --help 不详细 man iptables 一般详细 手册页 info iptab

Android项目:输入法软键盘显示/隐藏的监听和控制,InputMethodManager用法研究

在项目开发中,用到编辑框的地方经常涉及到要监听或者控制软键盘的显示/隐藏状态.本以为这是很容易解决的一个小问题,没想到当初碰到这个问题才明白还得花点小心思才能整好.现将针对软键盘的显示/隐藏状态的监听/监控方法做一些总结,以备后用. 一.点击空白处隐藏软键盘 这是具有编辑框焦点的页面对输入法软键盘状态监听的一般需求和解决方法. 首先获得InputMethodManager:        InputMethodManager manager = (InputMethodManager) getS

4.基础知识,“服务端监听端口”应用,实现功能

%a.启动一个监听端口 %b.客户端可以向服务端的这个接口发送数据 %c.服务端接受到数据,执行相应的操作,操作完成后把结果发回给客户端 %d.客戶端關閉連接,服務端清理數據 %server_manager.erl 模块,代码文件,放在网站:GitHub 1.启动后监听端口 2.客户端连接服务端 3.客户端发送的数据不同,服务端的对应操作也不同 4.服务端逻辑出现问题,客户端发送其他的数据导致服务端无法继续使用

linux上使用netstat查看当前服务和监听端口

netstat这个命令常用在网络监控方面.利用这个命令,可以查看当前系统监听的服务和已经建立的服务,以及相应的端口.协议等信息. netstat参数说明 netstat参数虽然很多,但是常用的不多,主要是下面几个参数: netstat -[atunlp] -a :all,表示列出所有的连接,服务监听,Socket资料 -t :tcp,列出tcp协议的服务 -u :udp,列出udp协议的服务 -n :port number, 用端口号来显示 -l :listening,列出当前监听服务 -p :

CentOS上使用netstat查看当前服务和监听端口

原文 http://www.80vps.com/new8955.htm netstat这个命令常用在网络监控方面.利用这个命令,可以查看当前系统监听的服务和已经建立的服务,以及相应的端口.协议等信息. netstat参数说明 netstat参数虽然很多,但是常用的不多,主要是下面几个参数: netstat -[atunlp] -a :all,表示列出所有的连接,服务监听,Socket资料 -t :tcp,列出tcp协议的服务 -u :udp,列出udp协议的服务 -n :port number,

服务中电话状态的监听

public class AddressService extends Service { public static final String tag = "AddressService"; private TelephonyManager mTM; private MyPhoneStateListener mPhoneStateListener; private final WindowManager.LayoutParams mParams = new WindowManager

Android Edittext 显示光标 获取焦点 监听焦点

Edittext java 代码控制获取焦点 EditText mEditText = (EditText) findViewById(R.id.et); mEditText.setFocusable(true); mEditText.setFocusableInTouchMode(true); 显示光标 mEditText.requestFocus();//获取焦点 光标出现 监听EditText焦点变化 当获取焦点后 hasFocus 为true mEditText.setOnFocusCh

java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中

1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试代码.这里须有一个需要提到的是,我在实现接收json文件的同时,而且还需将数据写到hbase中.写入到hbase当中采用的是批量插入的方式,即一次插入多条记录. 好了,有了前面的说明,下面来简单的说一下我实现的服务端的小程序把. 2.为了实现服务端能够监听客户端的行为,因此我在服务端采用多线程的技术

Android 监听开机广播启动服务 动态注册时间变化监听广播

开机广播权限 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 开机广播 注册 <receiver android:name="com.stone.receiver.BootedReceiver"> <intent-filter> <action android:name="android.intent.acti