如果局域网中有多台服务器提供服务,但是只有一个公网IP地址,这时使用iptables可以创建动态Nat转发规则,在拥有公网IP地址的机器上提供服务。例如我在阿里云购买了4台云主机,属于同一个子网,内网可以互通。其中一台主机拥有一个公网IP可以访问,另外三台主机创建了一个MongoDB Cluster分片集群。如果需要在外网访问MongoDB集群服务的话,就需要在拥有公网IP的主机上创建Nat规则,将外网来的访问转发到内网主机上。
以下是一个公网IP的Nat转发拓扑图:
我们在公网IP为101.89.90.123的主机上创建以下3条Nat转发规则:
- 将端口100转发到内网IP为10.10.93.100的27016端口上
- 将端口101转发到内网IP为10.10.93.101的27016端口上
- 将端口102转发到内网IP为10.10.93.102的27016端口上
对应的iptables规则为:
# 切记:打开ip转发
cat /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_forward
# Nat转发规则
iptables -t nat -A PREROUTING -p tcp --dport 100 -j DNAT --to-destination 10.10.93.100:27016
iptables -t nat -A PREROUTING -p tcp --dport 101 -j DNAT --to-destination 10.10.93.101:27016
iptables -t nat -A PREROUTING -p tcp --dport 102 -j DNAT --to-destination 10.10.93.102:27016
以上是转发规则,但是这还不够。除了转发以外,还需要将转发后数据包的原地址转换为本机地址(当数据包返回时,会自动转换为源地址)。需要添加一下Nat规则:
# nat出口转发,这条会动态把所有的端口都转发,导致一些服务不可用
# iptables -t nat -A POSTROUTING -j MASQUERADE
# 为每个服务单独设置静态出口转发
iptables -t nat -A POSTROUTING -p tcp -d 10.10.93.100 --dport 27016 -j SNAT --to-source 10.10.93.1
iptables -t nat -A POSTROUTING -p tcp -d 10.10.93.101 --dport 27016 -j SNAT --to-source 10.10.93.1
iptables -t nat -A POSTROUTING -p tcp -d 10.10.93.102 --dport 27016 -j SNAT --to-source 10.10.93.1
开启Log日志查看转发情况:
iptables -t nat -I PREROUTING -p tcp --dport 100 -j LOG --log-prefix "DNAT: " --log-level 1
主机集群公网IP提供访问内网IP提供数据同步
很多情况下主机集群需要提供外网IP的访问支持,但是集群内部各节点通过内网地址互通的数据流转效率更高。例如在《从零搭建Redis Cluster分片集群》一文中提到使用公网IP提供服务,但是集群内网使用本地IP。此时可以设置IP的Nat规则:
iptables -t nat -A OUTPUT -d 101.96.1.150 -j DNAT --to-destination 10.16.99.100
iptables -t nat -A OUTPUT -d 101.96.1.151 -j DNAT --to-destination 10.16.99.101
iptables -t nat -A OUTPUT -d 101.96.1.152 -j DNAT --to-destination 10.16.99.102
所有去公网地址101.96.1.x的流量,统一转发到10.16.99.x,从而实现内网节点强制走内网IP的功能。
扫码联系船长