作家
登录

Docker容器网络下UDP协议的一个问题

作者: 来源: 2017-08-23 09:49:41 阅读 我要评论

  • 11:20:54.503198 IP 172.17.0.3.38908 > 172.16.13.13.56789: UDP, length 3 
  • 11:20:54.503242 IP 172.16.13.13 > 172.17.0.3: ICMP 172.16.13.13 udp port 56789 unreachable, length 39 
  • 而此时主机上 UDP nc 办事器并没有退出,应用 lsof -i :56789 可能看到它仍然在监听着该端口。

    问题原因

    大年夜收集报文的分析中可以看到办事端返回的报文源地址不是我们预想的 eth0 地址,而是 docker0 的地址,而客户端直接认为该报文是不法的,返回了 ICMP 的报文给对方。

    主机多收集接口 UDP 源地址选择问题

    第一个问题的关键词是:UDP 和多收集接口。因为如不雅主机上只有一个收集接口,发出去的报文源地址必定不会有错;而我们也测试过 TCP 协定是可以或许处理这个问题的。

    经由过程搜刮,发明这确切是个已知的问题。在 UNP() 这本书中,已经描述过这个问题,下面是对应的内容:

    这篇文┞仿就分析一下出现这个问题的原因,欲望给同样碰到这个问题的读者供给些赞助。

    Docker容器收集下UDP协定的一个问题

    这个问题可以归结为一句话:UDP 在多网卡的情况下,可能会产生办事器端源地址纰谬的情况,这是内核选路的结不雅。 为什么 UDP 和 TCP 有不合的选路逻辑呢?因为 UDP 是无状况的协定,内核不会保存连接两边的信息,是以每次发送的报文都认为是自力的,socket 层每次发送报文默认情况不会指明要应用的源地址,只是解释对方地址。是以,内核会为要发出去的报文选择一个 ip,这平日都是报文路由要经由的设备 ip 地址。

    有了这个原因,还要解释一下问题: 为什么 dnsmasq 办事没有这个问题呢 ?是以我应用 strace 对象抓取了 dnsmasq 和出问题应用的收集 socket 体系调用,来查看它们两个到底有什么差别。

    dnsmasq 在启动阶段监听了 UDP 和 TCP 的 54 端口(因为是在本地机械上测试的,为了防止和本地 DNS 监听的 DNS端口才突,我选择了 54 而不是标准的 53 端口):

    1. socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4 
    2. setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 
    3. bind(4, {sa_family=AF_INET, sin_port=htons(54), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 
    4. setsockopt(4, SOL_IP, IP_PKTINFO, [1], 4) = 0 
    5.  
    6. socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 5 
    7. setsockopt(5, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 
    8. bind(5, {sa_family=AF_INET, sin_port=htons(54), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 
    9. listen(5, 5)                            = 0 

    比起 TCP,UDP 部分少了 listen ,然则多个 setsockopt(4, SOL_IP, IP_PKTINFO, [1], 4) 这句。到底这两点和我们的问题是否有关,先临时放着,持续看传输报文的部分。

    dnsmasq 收包和发包的体系调用,直接应用 recvmsg 和 sendmsg 体系调用:

    1. recvmsg(4, {msg_name(16)={sa_family=AF_INET, sin_port=htons(52072), sin_addr=inet_addr("10.111.59.4")}, msg_iov(1)=[{"\315\n\1 \0\1\0\0\0\0\0\1\fterminal19-0\5u5016\3"..., 4096}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_IP, cmsg_type=, ...}, msg_flags=0}, 0) = 67  
    2. sendmsg(4, {msg_name(16)={sa_family=AF_INET, sin_port=htons(52072), sin_addr=inet_addr("10.111.59.4")}, msg_iov(1)=[{"\315\n\201\200\0\1\0\1\0\0\0\1\fterminal19-0\5u5016\3"..., 83}], msg_controllen=28, {cmsg_len=28, cmsg_level=SOL_IP, cmsg_type=, ...}, msg_flags=0}, 0) = 83 

    而出问题的应用 strace 结不雅如下:

    谜底也是否定的,因为 NAT 须要 conntrack 来做翻译工作,如不雅去掉落 conntrack 等于 SNAT 完全没用。

    1. [pid   477] socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 124 
    2. [pid   477] setsockopt(124, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0 

        推荐阅读

        如何确定恶意软件是否在自己的电脑中执行过?

      【51CTO晃荡】8.26 带你与清华大年夜学、搜狗、京东大年夜咖们一路商量基于算法的IT运维实践 很不幸,你在本身的电脑里发清楚明了一个恶意的可履行法度榜样!那么问题来了:这个文件到底有>>>详细阅读


      本文标题:Docker容器网络下UDP协议的一个问题

      地址:http://www.17bianji.com/lsqh/36867.html

    关键词: 探索发现

    乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

    网友点评
    自媒体专栏

    评论

    热度

    精彩导读
    栏目ID=71的表不存在(操作类型=0)