问题背景

docker中的redis与宿主机做了端口映射,从外网访问宿主机端口,访问不通,使用telnet,也是失败,

telnet  外网ip 宿主机端口

telnet失败意味着三次握手失败,wireshark抓包显示也是如此。

解决过程

防火墙

操作系统是CentOS7,首先查看下防火墙状态,systemctl 是查看配置系统服务的命令。

[root@xx~]$ firewall-cmd --state
not running

或者

[root@xx~]$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

防火墙是关闭的,排除防火墙的原因了,

ip转发

继续查看ip转发是否开启,通过cat /proc/sys/net/ipv4/ip_forward查看ip转发是否开启。如果为0,则需要开启转发,net.ipv4.ip_forward是内核变量。

vim /etc/sysctl.conf

添加

# ipv4 转发
net.ipv4.ip_forward = 1

这是永久生效,即使重启后也是生效的,以上是必须要做的,接下来有三种选择,以实现立刻生效。

  • 重新加载配置文件,sysctl是查看修改内核变量的命令
sysctl -p
  • 重启网络服务
systemctl restart network
  • 临时修改内存中的配置
sysctl -w net.ipv4.ip_forward=1

或者

echo 1 > /proc/sys/net/ipv4/ip_forward

总结

为什么开启ipv4转发,外网与docker通信可达了?推测是宿主机与docker分属不同网络,默认的,docker桥接到宿主机,桥接模式下宿主机与docker使用网络地址转换(NAT)通信,它们之间需要路由,开启ipv4也就是开启了路由、NAT功能,从而网络可通。还有一点,Linux中的ipv4转发默认都是关闭的,这是出于“安全最优”原则。

参考

Linux IP forwarding – How to Disable/Enable using net.ipv4.ip_forwardCentOS 7,8: How to Enable IP Forwardingdocker 容器启动成功 外部访问不到原因