2022
我们一起努力

udp不通怎么解决(解决udp端口不可达)

本文目录:

  • 1、Udp网络不通 超融合
  • 2、udp跨网段无法访问,tcp可以
  • 3、【udp】关于docker 容器网络下使用 UDP 协议无法通讯问题的分析和处理
  • 4、小度显示网络udp被禁用无法通话
  • 5、UDP连接失败怎么办?
  • 6、udp偶发数据发送不出去怎么回事

Udp网络不通 超融合

换两台机器又可以通信。

Internet协议集支持一个无连接的传输协议,该协议称为用户数据报协议。UDP为应用程序提供了一种无需建立连接就可以发送封装的IP数据报的方法。RFC768描述了UDP。Internet的传输层有两个主要协议,互为补充。

udp跨网段无法访问,tcp可以

。可以从以下几个方面判断解决:1 、检查无线网卡设置是否正确:ip,掩码,网关,dns 一般自动获取即可。 能否成功连接到路由器,获取到正确的ip,dns等。2、登录进路由器,看路由器状态外网连接是否成功。 不成功的话看wan设置,上网方式设置:动态IP,静态IP,PPPoE。如果是PPPoE 检查账号密码是否正确,帐号重复上线。3、如果外网连接已成功,还是无法上网。Ping DNS 服务器看通不通 (允许ping的情况下)。如果不通,检查路由器dhcp网关设置 ,如果通,还是打不开网页,检查路由器DNS有没有被篡改过,以防万一可以把本机无线网卡的dns手动设置为运营商的dns。4、检查路由器其他上网限制等设置,实在找不到那就恢复默认设置吧。如果直连网线可以上网,所以排除外部网络问题,电脑端 lsp协议,代理,系统故障造成的无法上网

【udp】关于docker 容器网络下使用 UDP 协议无法通讯问题的分析和处理

工作中遇到一个 docker 容器下 UDP 协议网络不通的问题,困扰了很久,也比较有意思,所以想写下来和大家分享。

我们有个应用是基于 UDP 协议的,部署上去发现无法工作,但是换成 TCP 协议是可以的(应用同时支持 UDP、TCP 协议,切换成 TCP 模式发现一切正常)。

虽然换成 TCP 能解决问题,但是我们还是想知道到底 UDP 协议在容器网络模式下为什么会出现这个问题,以防止后面其他 UDP 应用会有异常。

这个问题抽象出来是这样的:如果有 UDP 服务运行在宿主机上(或者运行在网络模型为 host 的容器里),并且监听在 0.0.0.0 地址(也就是所有的 ip 地址),从运行在 docker bridge(网桥为 docker0) 网络的容器运行客户端访问服务,两者通信有问题。

注意以上的的限制条件,通过测试,我们发现下来几种情况都是正常的:

这个问题在 docker 上也有 issue 记录,但是目前并没有合理的解决方案。

这篇文章就分析一下出现这个问题的原因,希望给同样遇到这个问题的读者提供些帮助。

这个问题很容易重现,我的实验是在 ubuntu16.04 下用 netcat 命令完成的,其他系统应该类似。

在宿主机上通过 nc 监听 56789 端口,然后使用 bridge 网络模式,run 一个容器,在容器里面使用 nc 发数据。

第一个报文是能发送出去的,但是以后的报文虽然在网络上能看到,但是对方无法接收。

在宿主机运行 nc UDP 服务器(-u 表示 UDP 协议,-l 表示监听的端口)

注:默认没有指定绑定ip,就是监听在0.0.0.0上。

然后在同一宿主机上,启动一个容器,运行客户端:

nc 的通信是双方的,不管对方输入什么字符,回车后对方就能立即收到。

但是在这个模式下,客户端第一次输入对方能够收到,后续的报文对方都收不到。

在这个实验中,容器使用的是 docker 的默认网络,容器的 ip 是 172.17.0.3,通过 veth pair(图中没有显示)连接到虚拟网桥 docker0(ip 地址为 172.17.0.1),宿主机本身的网络为 eth0,其 ip 地址为 172.16.13.13。

遇到这种疑难杂症,第一个想到的抓包。

我们需要在 docker0 上抓包,因为这是报文必经过的地方。

通过过滤容器的 ip 地址,很容器找到感兴趣的报文:

为了模拟多数应用一问一答的通信方式,我们一共发送三个报文,并用 tcpdump 抓取 docker0 接口上的报文:

抓包的结果如下,可以发现第一个报文发送出去没有任何问题。

UDP 是没有 ACK 报文的,所以客户端无法知道对方有没有收到,这里说的没有问题没有看到对应的 ICMP 差错报文。

但是第二个报文从服务端发送的报文,对方会返回一个 ICMP 告诉端口 38908 不可达;第三个报文从客户端发送的报文也是如此。以后的报文情况类似,双方再也无法进行通信了。

而此时主机上 UDP nc 服务器并没有退出,使用 ss -uan | grep 56789 可能看到它仍然在监听着该端口。

从网络报文的分析中可以看到服务端返回的报文源地址不是我们预想的 eth0 地址,而是 docker0 的地址,而客户端直接认为该报文是非法的,返回了 ICMP 的报文给对方。

那么问题的原因也可以分为两个部分:

第一个问题的关键词是:UDP 和多网络接口。

因为如果主机上只有一个网络接口,发出去的报文源地址一定不会有错;而我们也测试过 TCP 协议是能够处理这个问题的。

通过搜索,发现这确实是个已知的问题。

这个问题可以归结为一句话:UDP 在多网卡的情况下,可能会发生【服务器端】【源地址】不对的情况,这是内核选路的结果。

为什么 UDP 和 TCP 有不同的选路逻辑呢?

因为 UDP 是无状态的协议,内核不会保存连接双方的信息,因此每次发送的报文都认为是独立的,socket 层每次发送报文默认情况不会指明要使用的源地址,只是说明对方地址。

因此,内核会为要发出去的报文选择一个 ip,这通常都是报文路由要经过的设备 ip 地址。

那么,为什么 dnsmasq 服务没有这个问题呢?

于是我使用 strace 工具抓取了 dnsmasq 和出问题应用的网络 socket 系统调用,来查看它们两个到底有什么区别。

dnsmasq 在启动阶段监听了 UDP 和 TCP 的 54 端口

因为是在本地机器上测试的,为了防止和本地 DNS 监听的DNS端口冲突,我选择了 54 而不是标准的 53 端口:

比起 TCP,UDP 部分少了 listen,但是多个 setsockopt(4, SOL_IP, IP_PKTINFO, [1], 4) 这句。

到底这两点和我们的问题是否有关,先暂时放着,继续看传输报文的部分。

dnsmasq 收包和发包的系统调用,直接使用 recvmsg 和 sendmsg 系统调用:

而出问题的 UDP 应用 strace 结果如下:

其对应的逻辑是这样的:使用 ipv6 绑定在 0.0.0.0 和 6088 端口,调用 getsockname 获取当前 socket 绑定的端口信息,数据传输过程使用的是 recvfrom 和 sendto。

对比下来,两者的不同有几点:

因为是在传输数据的时候出错的,因此第一个疑点是 sendmsg 和 sendto 的某些区别导致选择源地址有不同,通过 man sendto 可以知道 sendmsg 包含了更多的控制信息在 msghdr。

一个合理的猜测是 msghdr 中包含了内核选择源地址的信息!

通过查找,发现 IP_PKTINFO 这个选项就是让内核在 socket 中保存 IP 报文的信息,当然也包括了报文的源地址和目的地址。 IP_PKTINFO 和 msghdr 的关系可以在这个 stackoverflow 中找到:

而 man 7 ip 文档中也说明了 IP_PKTINFO 是怎么控制源地址选择的:

如果 ipi_spec_dst 和 ipi_ifindex 不为空,它们都能作为源地址选择的依据,而不是让内核通过路由决定。

也就是说,通过设置 IP_PKTINFO socket 选项为 1,然后使用 recvmsg 和 sendmsg 传输数据就能保证源地址选择符合我们的期望。

这也是 dnsmasq 使用的方案,而出问题的应用是因为使用了默认的 recvfrom 和 sendto。

为什么内核会把源地址和之前不同的报文丢弃,认为它是非法的?

因为我们前面已经说过,UDP 协议是无连接的,默认情况下 socket 也不会保存双方连接的信息。即使服务端发送报文的源地址有误,只要对方能正常接收并处理,也不会导致网络不通。

但是 conntrack 不是这样,内核的 netfilter 模块会保存连接的状态,并作为防火墙设置的依据。

它保存的 UDP 连接,只是简单记录了主机上本地 ip 和端口,和对端 ip 和端口,并不会保存更多的内容。

关于 这块可参考 intables info 网站的文章:

在找到根源之前,我们曾经尝试过用 SNAT 来修改服务端应答报文的源地址,期望能够修复该问题,但是却发现这种方法行不通,为什么呢?

因为 SNAT 是在 netfilter 最后做的,在之前 netfilter 的 conntrack 因为不认识该 connection,直接丢弃了,所以即使添加了 SNAT 也是无法工作的。

那能不能把 conntrack 功能去掉呢?比如解决方案:

答案也是否定的,因为 NAT 需要 conntrack 来做翻译工作,如果去掉 conntrack 等于 SNAT 完全没用。

知道了问题的原因,解决方案也就很容易找到。

nc 可以跟两个参数,分别代表 ip 和 端口,表示服务端监听在某个特定 ip 上。

如果接收到的报文目的地址不是 172.16.13.13,也会被内核直接丢弃,这种情况下,服务端和客户端也能正常通信。

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

Setting the source IP for a UDP socket

LinuxC下获取UDP包中的路由目的IP地址和头标识目的地址

Source IP address selection

UDP recvmsg 返回目的地址和目的接口信息

告知你不为人知的 UDP:连接性和负载均衡

告知你不为人知的 UDP:疑难杂症和使用

小度显示网络udp被禁用无法通话

小度显示网络udp被禁用无法通话解决方法:

网络udp被禁用,出现这个情况可能有两种原因:

1、你使用的代理服务器上网,代理服务器把你的UDP端口封掉了;解决办法是你需要找代理商帮助解封你的udp端口;

2、你自己电脑上的防火墙将UDP端口封掉了,解决方法,关掉防火墙(包括windows自带的)。

UDP连接失败怎么办?

【我家也有这个问题,现在好了,按我说的跟定搞定】

你应该是和别人家一起连的网吧【宽带】

应该有一个路由器,所以办法在下面

(1.你先把路由器的后面有一个小窟窿,用牙签通一通,为的就是

吧路由器重启一下子,再把把你的电脑重启一下子,就可以了

【如上面方法无效,请选择线面的方法,】

(2.把修电脑的叫来,让他把路由器的服务代码重设置一下子,

(因为DNF在你不好使的最后一次更新中,不能接受你选择的路由气服务端口

所以改一下下就好了)

如果再不好使就,换一个路由器就好了

【谢谢采纳】~~

udp偶发数据发送不出去怎么回事

tcp/ip

解决c++udp组播通信由于多网口造成无法发送数据包的问题

赖东东_

原创

关注

1点赞·1182人阅读

一、分析

什么叫做多网口?

使用ifconfig命令查看接口信息,如果只有eth0,说明你只有一个接口,那么udp无法发送数据包就不是因为多网口的问题了,那你就要去找其他原因

如果除了eth0还有eth1等接口时,就说明你的设备是多网口的

怎么判断是因为多个网口造成无法发送数据包?

1.首先,确定其他客户端能发送数据包到组播

通过打印数据和抓包就可以确定

2.本端能确定发送成功数据,但是通过组播地址抓包却无法抓到

通过在 发送数据函数接口内 打印发送的数据发现数据成功打印

在设备端(一般为开发板)检查网络状态,输出指令netstat -napu

 可以看到 本地地址 local adress的ip地址为0.0.0.0

因为存在多个网口,每个网口都有它的ip地址和路由,所以当你查看你的设备网络状态的时候,就会发现你的地址是0.0.0.0

这个0.0.0.0地址是本地所有ip地址的一种表示地址。

所以,出现 确定发送了数据,无法抓包,网络状态显示ip为0.0.0.0,基本可以确定为是因为多网口的原因造成了数据包无法到达,因为一般的代码而言,都是固定一个从一个ip地址去到组播地址。而多网口的时候,路由会自动帮你选个最佳ip地址去往组播地址,但这个最佳的ip地址和你代码中设定的本地地址不一定一样,故你无法抓包,但却实是发送了数据

二、解决办法

根据以上总结,你大概就有了思路,既然我无法确定默认路由给的是哪条路去往组播地址,那我只要把所有的本地地址都发送一遍,总有一个被默认路由选中的路径去往组播地址

以下是让数据在所有本地地址都发送的一个例子,大家可以根据实际情况,只要向着上面的思路去写代码就可以解决这个问题

/

udp不通怎么解决】的内容来源于互联网,如引用不当,请联系我们修改。

赞(0)
文章名称:《udp不通怎么解决(解决udp端口不可达)》
文章链接:https://www.fzvps.com/28582.html
本站文章来源于互联网,如有侵权,请联系管理删除,本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
图片版权归属各自创作者所有,图片水印出于防止被无耻之徒盗取劳动成果的目的。

评论 抢沙发

评论前必须登录!