docker修改服务器防火墙,docker宿主机iptables配置

背景

以前服务器都是直接配置LNMP环境,最近手头正好有一台需要重新配置,想尝试使用docker来配置多PHP版本环境。docker配置十分顺利,感谢有明大佬的小册,和DNMP项目。

待解决

服务器配置好后,在几天的试用过程中,发现如下两个问题:

NGINX PHP容器中无法获取request的真实IP

PHP容器中无法访问公网

过程

无法访问公网,无法获取真实IP,首先想到了防火墙的问题;关闭iptables,问题解决。可是iptables不能关呀,虽说现在云服务器都有安全组过滤,但防火墙是最后一道防线,不能在云厂商的怀抱里裸奔啊……

查看了docker的网络部分,docker暴露容器端口是由docker-proxy来实现的,至于docker-proxy是什么略过不表。肯定是iptables影响了docker-proxy导致数据包的源ip发生了改变,无法获取真实IP;无法访问公网,则是数据包找不到出口,被iptables拦截掉了,在内网转圈圈

既然docker的各容器处于内网中,于是我想到了iptables的转发功能。

解决

假设我的公网IP为 117.25.140.71

NGINX容器内网IP为 172.18.0.2

PHP容器内网IP为 172.18.0.3 172.19.0.3

把公网来的数据包直接转发给NGINX容器,跳过docker-proxy

添加如下规则

-A PREROUTING -d 117.25.140.71 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80

-A PREROUTING -d 117.25.140.71 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.18.0.2:443

复制代码

重启iptables 无法获取真实IP问题解决

将内网的数据包转发到公网

我的PHP容器访问公网,需求大抵是发送短信之类(无邮件发送),用的都是http协议,所以这里我没有选择全部转发,而是只转发目的端口为80和443的数据包

添加如下规则

-A POSTROUTING -s 172.19.0.3 -p tcp -m tcp --dport 80 -j SNAT --to 117.25.140.71

-A POSTROUTING -s 172.19.0.3 -p tcp -m tcp --dport 443 -j SNAT --to 117.25.140.71

复制代码

重启iptables发现仍然无法访问公网,是不是落下了什么。。

对了,既然http协议访问其他域名提供的api服务,怎么能少了DNS解析呢?添加DNS的支持(注意:DNS解析使用的是udp协议)

补充如下规则

-A POSTROUTING -s 172.19.0.3 -p udp -m udp --dport 53 -j SNAT --to 117.25.140.71

复制代码

重启iptables,大功告成!

最后总结几点:

之所以能用宿主机iptables实现转发,是因为宿主机是内网的网关

我限制了PHP容器访问公网的目的端口,如果需要发送邮件或者访问8080等其他端口,仍需单独添加规则或者不限制具体端口号

转发内网数据包到公网,不要使用地址伪装(MASQUERADE),否则会影响本文中添加的PREROUTING规则,仍然无法获取request的真实IP(使用其他方法除外)

如果直接service iptables stop,这篇文章就不用看了。。。

##2020.3.31更新

docker19.03版本解决了这个问题,不再需要自己手动配置啦

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值