• 部署:端口映射相关问题


    0.达成的目标

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

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

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

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

    1.问题与解决方案

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

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

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

    1. #!/bin/bash
    2. #created by ZZ_Guide Co,.Ltd.
    3. #
    4. #Ver1.2 Nov07,2023
    5. # * ip_out add src addr modify.
    6. # * ip_in add ip addr strictly limit.
    7. #Ver1.1 Oct27,2023
    8. # + add in_station rules
    9. #Ver1.0 Oct25,2023
    10. # + the first verion based iptables.
    11. # enter maintainance net config domain.
    12. echo "start update nat mapping"
    13. container_id=$(docker ps --filter "name=monitor" --quiet)
    14. pidofdocker=$(docker inspect --format '{{.State.Pid}}' $container_id)
    15. nsenter -t $pidofdocker -n -i /bin/bash <<EOF
    16. # ip_out nat rules:
    17. # => 192.168.1.x :[remotePort:800?]
    18. # transfered to:
    19. # => 10.1.1.95:[remotePortMapping:999?], you can not change src ip & port here. because of docker used NAT too.
    20. #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.
    21. #delete private link, then rebuild it.
    22. iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9990
    23. iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9991
    24. iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9992
    25. iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9993
    26. iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9994
    27. iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9995
    28. iptables -t nat -D OUTPUT -d 192.168.1.10 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9996
    29. iptables -t nat -D OUTPUT -d 192.168.1.20 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9997
    30. #change the target addr and port.
    31. iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9990
    32. iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8001 -j DNAT --to-destination 10.1.1.95:9991
    33. iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9992
    34. iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8002 -j DNAT --to-destination 10.1.1.95:9993
    35. iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9994
    36. iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8003 -j DNAT --to-destination 10.1.1.95:9995
    37. iptables -t nat -A OUTPUT -d 192.168.1.10 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9996
    38. iptables -t nat -A OUTPUT -d 192.168.1.20 -p tcp --dport 8004 -j DNAT --to-destination 10.1.1.95:9997
    39. # ip_in nat rules:
    40. # (10.1.1.95:[remotePortMapping:999?] =>
    41. # transfered to:
    42. # (192.168.1.x:[remotePortReal:800?] =>
    43. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9990 -j SNAT --to-source 192.168.1.10:8001
    44. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9991 -j SNAT --to-source 192.168.1.20:8001
    45. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9992 -j SNAT --to-source 192.168.1.10:8002
    46. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9993 -j SNAT --to-source 192.168.1.20:8002
    47. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9994 -j SNAT --to-source 192.168.1.10:8003
    48. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9995 -j SNAT --to-source 192.168.1.20:8003
    49. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9996 -j SNAT --to-source 192.168.1.10:8004
    50. iptables -t nat -D INPUT -p tcp -s 10.1.1.95 --sport 9997 -j SNAT --to-source 192.168.1.20:8004
    51. #clear then create.
    52. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9990 -j SNAT --to-source 192.168.1.10:8001
    53. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9991 -j SNAT --to-source 192.168.1.20:8001
    54. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9992 -j SNAT --to-source 192.168.1.10:8002
    55. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9993 -j SNAT --to-source 192.168.1.20:8002
    56. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9994 -j SNAT --to-source 192.168.1.10:8003
    57. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9995 -j SNAT --to-source 192.168.1.20:8003
    58. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9996 -j SNAT --to-source 192.168.1.10:8004
    59. iptables -t nat -A INPUT -p tcp -s 10.1.1.95 --sport 9997 -j SNAT --to-source 192.168.1.20:8004
    60. EOF
    61. 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链——因为它要同时转换源和目标地址。

  • 相关阅读:
    d的dip1000,1
    Android Studio详细的安装下载教程
    回归损失和分类损失
    SpringCloud Alibaba学习
    使用 Charles 去修改响应信息(真实工作使用场景1)
    2022爱分析· 虚拟化活动厂商全景报告 | 爱分析报告
    OS--学习笔记:操作系统概述
    Leetcode 481. 神奇字符串
    【前端】JavaScript-事件高级
    C语言编程题(四)有符号数与无符号数相加
  • 原文地址:https://blog.csdn.net/twicave/article/details/134028893