docker发现端口是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 进程:
# 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。
docker发现端口是tcp6的 导致无法访问前端的更多相关文章
- zabbix—自动发现端口并监控
自动批量检查agent开放的端口 PS:如果服务器上的应用都是固定的,不会随机产生的都可以使用自动发现端口来监控: 如果服务器会随机出现端口且每次启动程序都会改变,可以采用第二种方法,来监控指定的端 ...
- docker iptables 端口映射 nat
docker iptables 端口映射 nat #!/bin/bash pro='tcp' NAT_Host='Host_A' NAT_Port=8080 Dst_Host='Host_B' ...
- veridata实验例(3)验证veridata发现insert操作不会导致同步
veridata实验例(3)验证veridata发现insert操作不会导致同步 续接:<veridata实验举例(2)验证表BONUS与表SALGRADE两节点同步情况>,地址:点击打开 ...
- zabbix 添加自动发现端口并监控
最近在部署zabbix监控 有些服务器上开启的服务端口非常多 如果一个个添加监控会很繁琐,于是想到了自动发现规则 自动发现服务器上的服务端口并进行监控. 在zabbix客户端服务器上进行操作 1 ...
- zabbix 自动发现端口并添加监控设置
自动发现端口并添加监控设置UserParameter=net.listen.discovery,sudo /etc/zabbix/scripts/discovery_listport.sh #!/bi ...
- 分布式监控系统Zabbix--完整安装记录-批量添加主机和自动发现端口
一.Zabbix-3.0.3批量添加主机的配置如下: 0)被监控机上要安装zabbix_agent,并配置好zabbix_agentd.conf (如下172.29.8.50是zabbix_serve ...
- zabbix的日常监控-自动发现端口并监测(服务器开启的所有端口或监控指定端口)(十三)
动批量检查agent开放的端口 注:此方法给监控磁盘IO(即十二)篇过程一样: 注释:如果服务器上的应用都是固定的,不会随机产生的都可以使用自动发现端口来监控: 如果服务器会随机出现端口且每次启动程 ...
- 聊聊docker那些端口问题
今天来系统聊一聊docker的端口,常见的有容器内程序端口.容器端口.主机端口.Dockerfile中EXPOSE端口.docker-compose和docker run中的port等. 貌似很多端口 ...
- Docker 构建网络服务后本机不能访问
Docker 构建网络服务后本机不能访问 起因 使用tornado构建了一个服务,测试都没有问题 使用docker构建镜像,使用docker run image_name启动服务 使用浏览器访问 12 ...
随机推荐
- 洛谷P2342-叠积木
Problem 洛谷P2342-叠积木 Accept: 373 Submit: 1.1k Time Limit: 1000 mSec Memory Limit : 128MB Problem ...
- Discrete Logging ZOJ - 1898 (模板题大小步算法)
就是求Ax三B(mod C)当C为素数时 #include<cstdio> #include<cstring> #include<cmath> #include&l ...
- Linux之GDB学习
Linux之GDB学习 GDB是一款优秀的调试工具,懂的人自然懂,一直以来用它都没有好好整理过使用方法,我用的也是皮毛,目前先整理一下皮毛,日后再更新 使用方法 编译C++ 从编译的角度上来说,需要在 ...
- 利用Apache AXIS 1 发布WebService
首先,AXIS 是apache的作品. 1.到apache去下载相关的包,包括axis.jar.axis-ant.jar.commons-discovery-0.2.jar等.将jar包放到WEB-I ...
- nodejs stream 手册学习
nodejs stream 手册 https://github.com/jabez128/stream-handbook 在node中,流可以帮助我们将事情的重点分为几份,因为使用流可以帮助我们将实现 ...
- metamask中的import account的代码实现
metamask-extension/app/scripts/account-import-strategies/index.js 这部分就是用户如果往metamask中import一个已有的账户调用 ...
- Linux中运行SpringBoot项目,永久运行
将写好的springboot项目打成jar包: 项目右键 -- Run As -- Maven build... ---此时出现下图 1.Goals 中填写:install 2.Skip Tests复 ...
- 深入浅出的webpack构建工具---webpack基本配置(一)
深入浅出的webpack构建工具---webpack基本配置(一) 阅读目录 一:webpack入门构建: 1. 安装webpack到全局 2. 安装webpack到本项目. 3. 如何使用webpa ...
- java 桥接模式
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 1)适配器:改变已有的两个接口,让他们相容. 2)桥接模式:分离抽象化 ...
- 提示文件过大无法复制到U盘怎么解决
1.U盘作为一个便携的移动存储工具,在我们的生活中扮演重要的角色,但 是我们经常会遇到在复制文件到U盘中的时候,U盘明显有很大的空间,却 提示文件过大无法复制,今天,我教大家一步解决这个问题!! 2. ...