部署:端口映射相关问题

0.达成的目标

现场部署时,会涉及内外网数据包的地址和端口转换问题。这个的解决方案涉及docker、NAT、 port mapping。NAT 部分考虑了双向地址转换和端口转换。最终支持原本在实验环境同处于一个独立的设备内网,在部署时,分处两地,借助广域网传输服务器程序和第三方设备仍然使用原有的Local IP彼此通讯,公网环境对用户和设备是透明的。

所涉及到的与传输相关的改造只涉及到两个集中管理设备:

1.机房服务器,众多传感器的核心数据用户,在它的设备上需要编制NAT  iptables转换规则表。

2.5G CPE,需要编制端口映射表,将传感器采集终端的服务暴露给远端的机房服务器。

1.问题与解决方案

在很多现场部署环境里,网络管理是相对严格的,设备所在的子网如果需要和办公网所在的服务器通讯,需要通过专门的中间节点,一般还有严格的防火墙配置。此时,研发环境里,服务器与设备子网各节点间的点对点连接,需要通过跨内网和办公网的中间节点中转。中间节点处因为跨越两个物理网络,一般会编制端口映射(另一种实现是VPN)。

但是这样做仍然有问题:有些三方设备的端口是写死的。怎么处理呢?看下面的脚本代码:

1.1  服务器NAT地址与端口映射表

#!/bin/bash
#created by ZZ_Guide Co,.Ltd.
#
#Ver1.2 Nov07,2023
#    * ip_out add src addr modify.
#    * ip_in add ip addr strictly limit.
#Ver1.1 Oct27,2023
#    + add in_station rules
#Ver1.0 Oct25,2023
#    + the first verion based iptables.


# enter maintainance net config domain.
echo "start update nat mapping"
container_id=$(docker ps --filter "name=monitor" --quiet)
pidofdocker=$(docker inspect --format '{{.State.Pid}}' $container_id)
nsenter -t $pidofdocker -n -i /bin/bash <<EOF

# ip_out nat rules:
#      => 192.168.1.x :[remotePort:800?]
#      transfered to:
#      => 10.1.1.95:[remotePortMapping:999?], you can not change src ip & port here. because of docker used NAT too.
#iptables -t nat -D POSTROUTING -d 192.168.1.20 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9991 --to-source 10.193.254.7 should not changed.
#delete private link, then rebuild it.
iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9990
iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9991
iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9992
iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9993
iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9994
iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9995
iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9996
iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9997
#change the target addr and port.
iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9990
iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9991
iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9992
iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9993
iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9994
iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9995
iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9996
iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9997

# ip_in nat rules:
#       (10.1.1.95:[remotePortMapping:999?] =>
#       transfered to:
#       (192.168.1.x:[remotePortReal:800?] =>
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9990 -j SNAT --to-source 192.168.1.10:8001
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9991 -j SNAT --to-source 192.168.1.20:8001
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9992 -j SNAT --to-source 192.168.1.10:8002
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9993 -j SNAT --to-source 192.168.1.20:8002
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9994 -j SNAT --to-source 192.168.1.10:8003
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9995 -j SNAT --to-source 192.168.1.20:8003
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9996 -j SNAT --to-source 192.168.1.10:8004
iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9997 -j SNAT --to-source 192.168.1.20:8004

#clear then create.
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9990 -j SNAT --to-source 192.168.1.10:8001
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9991 -j SNAT --to-source 192.168.1.20:8001
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9992 -j SNAT --to-source 192.168.1.10:8002
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9993 -j SNAT --to-source 192.168.1.20:8002
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9994 -j SNAT --to-source 192.168.1.10:8003
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9995 -j SNAT --to-source 192.168.1.20:8003
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9996 -j SNAT --to-source 192.168.1.10:8004
iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9997 -j SNAT --to-source 192.168.1.20:8004
EOF
echo "nat mapping updated yet. docker id=$pidofdocker docker id=$container_id"

1.2 NAT映射的额外说明:

1.如果你的程序直接运行在linux环境,那么直接配置iptables的那个映射关系即可。

2.如果程序在docker里面,需要执行额外的进入相应的网络配置空间的指令(头部,和EOF之后的部分)

3.注意nsenter后进入的是一个独立的应用线程。

4.上面的指令,把应用程序发起的一个指向一个private network endpoint: 192.168.1.x:800?的tcp连接,直接转向广域网地址:10.1.1.95:999?,依次类推。

5.上述代码已经现场测试过。

1.3 总原则

对于已经启用了NAT转换的docker环境:

        1.出站规则只应该转换目标地址,源地址docker如果是bridge模式会自行转换

        2.入站规则仅转换源地址,目标地址系统会自行转换。

1.4 CPE端口映射表 

(从略)

附录A 更多的关于iptables的信息

1.更复杂的iptables

如果你需要在一条语句里同时变换源地址和目标地址,不可能。SNAT 和DNAT不可以出现在同一条指令里,所以,你需要在既有的INPUT, OUTPUT链路里额外添加更多的处理链路,链路创建和销毁的语法:

iptables -D OUTPUT 1   #将当前链路里的1号扩展链路删除
iptables -X OUTPUT_STAGE1 #删除一整个链路
iptables -t nat -N OUTPUT_STAGE1 #新建一个链路

iptables -A OUTPUT -j OUTPUT_STAGE1 #将新建的链路添加在别的链路尾巴上

此外你还需要链路查看命令行:

iptables -S #这条指令可以打印所有的链路名

iptables -L -n --line-numbers #显示iptable -D所需的扩展链路行号

附录B docker对NAT转换的影响

docker的网络模式查看命令行:

docker inspect <容器名称或容器ID> --format '{{ .HostConfig.NetworkMode }}'

#如果容器的NetworkMode经过重命名:

docker network ls

#上述指令可以把网络的名称,与网络的类型关联打印出来。

注意,前面描述的解决方案,仅仅适用于采用Bridge模式的docker执行环境。docker有至少三种网络连接模式:

bridge 桥接模式:默认的网络模式,Docker 容器通过桥接网络与宿主机进行通信。
host 主机模式:Docker 容器与宿主机共享网络命名空间,直接使用宿主机的网络接口。
none 无网络模式:Docker 容器完全隔离,没有网络连接。

Host模式的内外网转换,我没有做过,有通知做过,或者看到有相关链接,可以留言。 它大概率需要用到额外的iptables链——因为它要同时转换源和目标地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值