当其他协议似乎已关闭时,如何解析DNS名称解析?

Pav*_*lev 3 c sockets linux networking tcp

我们正在尝试实施基于Moxa UC-7112-LX嵌入式计算机(uClinux OS)的软件.我们使用Cinteron MC52i GSM调制解调器(常规GPRS服务)和标准pppd连接到互联网.

在连接之后,一切似乎都很好.Ping实用程序正常工作,程序中的Socket函数也正常工作.然而,经过一段时间后,ppp连接以一种非常特殊的方式破碎.这些是这种情况的症状:

  • 当我使用某个主机名作为参数调用ping实用程序时,系统能够解析它的IP并开始发送ICMP数据包但没有响应.我正在尝试不同的Web资源名称,以便系统无法缓存其地址或其他内容.无论我选择什么,系统都能正确解析IP,但无法获得任何ping响应.
  • connect()write()在我的应用功能,给没有错误回报,但,当涉及到read()的功能,并将errno设置返回ECONNRESET(连接被对方复位).该程序使用标准套接字函数(TCP协议)
  • ppp链接显示为running(ifconfig ppp0)

所以,我的情况是:链接是否足以维护DNS解析服务(UDP工作?)但不足以运行TCP连接并接收ping回声...

情况不会一直出现.有时系统可以正常工作几天而没有任何问题.无论何时出现问题,简单的重置都可以解决所有问题.

我知道我们使用的系统非常奇特,这里描述的情况可能与一些错误的tcp堆栈或pppd实现有关.考虑到系统是由制造商预先配置的,我没有任何选项来重建/更改操作系统固件.

我仍然希望有人在任何类似Linux的系统上看到类似的情况.有没有办法测试为什么DNS名称解析工作,而其他网络的东西没有?是否可以使用某些pppd设置删除此类连接状态?

编辑:

首先,我想解决本地缓存IP地址的可能性.我没有dig实用程序,我不知道如何检查哪个主机给出了结果getaddrinfo().我仍然确定地址没有被缓存,因为我试图ping完全随机的URL.另外,由于GPRS响应时间较慢,因此在开始发送数据包之前,没有必要使用时间测量实用程序来确定ping需要1-2秒或更长时间来解析IP.此外ncsd,BIND或任何DNS服务器不在本地计算机上运行.我知道您可能不会将其视为证据,但这就是我在系统上提供的实用工具集.

我想提供一些有关互联网连接操作的其他信息.

正常连接状态

rc系统加载时的脚本运行另一个脚本作为后台进程:

sh /etc/connect &
Run Code Online (Sandbox Code Playgroud)

connect脚本如下:

#!/bin/sh
echo First connect attempt > /etc/ppp/conn.info
while true
do
date >> /etc/ppp/conn.info
pppd call mts
echo Reconnecting... >> /etc/ppp/conn.info
done
Run Code Online (Sandbox Code Playgroud)

我在这里做了一个循环的原因很简单:连接持续了几个小时,然后它总是断开.不幸的是我的实现pppd不支持logfile选项(所以我不明白它为什么会被破坏).坚持似乎也不起作用,所以我来到上面的连接脚本.pppd选项是:

/dev/ttyM0 115200 crtscts
connect 'chat -f /etc/ppp/peers/mts.chat'
noauth
user mts
password mts
noipdefault
usepeerdns
defaultroute
Run Code Online (Sandbox Code Playgroud)

ifconfig ppp0 得到:

ppp0      Link encap:Point-Point Protocol  
          inet addr:172.22.22.109  P-t-P:192.168.254.254  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:34 errors:0 dropped:0 overruns:0 frame:0
          TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3 
          RX bytes:3130 (3.0 KiB)  TX bytes:2250 (2.1 KiB) 
Run Code Online (Sandbox Code Playgroud)

这就是它开始变得奇怪的地方.每当我连接时,我会变得不同inet addrP-t-p总是一样的:192.168.254.254.这与默认网关条目中显示的地址相同,如下所示netstat -rn:

Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.254.254 0.0.0.0         255.255.255.255 UH        0 0          0 ppp0
192.168.4.0     0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.15.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
192.168.0.0     192.168.15.1    255.255.0.0     UG        0 0          0 eth0
0.0.0.0         192.168.254.254 0.0.0.0         UG        0 0          0 ppp0 
Run Code Online (Sandbox Code Playgroud)

route -Cevn 在我的系统上不可用,路由提供与上面相同的信息.

但我永远无法ping 192.168.254.254,即使一切都按预期工作:tcp连接,ping,DNS等.这是traceroute的结果:

traceroute to kernel.org (149.20.4.69), 30 hops max, 40 byte packets
 1  172.16.4.210 (172.16.4.210)  528.765 ms  545.269 ms  616.67 ms
 2  172.16.4.226 (172.16.4.226)  563.034 ms  526.176 ms  537.07 ms
 3  10.250.85.161 (10.250.85.161)  572.805 ms  564.073 ms  556.766 ms
 4  172.31.250.9 (172.31.250.9)  556.513 ms  563.383 ms  580.724 ms
 5  172.31.250.10 (172.31.250.10)  518.15 ms  526.403 ms  537.574 ms
 6  pub2.kernel.org (149.20.4.69)  538.058 ms  514.222 ms  538.575 ms
 7  pub2.kernel.org (149.20.4.69)  537.531 ms  538.52 ms  537.556 ms
 8  pub2.kernel.org (149.20.4.69)  568.695 ms  523.099 ms  570.983 ms
 9  pub2.kernel.org (149.20.4.69)  526.511 ms  534.583 ms  537.994 ms
##### traceroute loops here - why??  #######
Run Code Online (Sandbox Code Playgroud)

所以,我可以假设172.16.4.210是对等的地址.在任何情况下,这样的地址都是可以ping的(见下文).我不知道为什么traceroute输出的结构是这样的(数据包来自ISP的内部网络到目的地,'loop'在目标地址 - 它应该不是这样的).

另外我想说明我可以ping DNS服务器,但是traceroute不会一直到它.

您可能会注意到有eth0和eth1设备.他们与案件无关.eth1未连接且eth0连接到没有Internet访问的LAN.

连接状态不良

所以,一段时间过去了,问题就出现了.除了DNS服务器(和peer,我从DNS的traceroute得到的地址)我无法ping通任何东西,并且无法通过tcp与远程主机通信.DNS解析正在发挥作用

网络实用程序提供与正常状态相同的输出.我有相同的unpingable peer(来自ifconfig结果的192.168.254.254),路由表是相同的:

# ifconfig ppp0
ppp0      Link encap:Point-Point Protocol
          inet addr:172.22.22.109  P-t-P:192.168.254.254  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:297 errors:0 dropped:0 overruns:0 frame:0
          TX packets:424 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:33706 (32.9 KiB)  TX bytes:27451 (26.8 KiB)

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.254.254 *               255.255.255.255 UH    0      0        0 ppp0
192.168.4.0     *               255.255.255.0   U     0      0        0 eth1
192.168.15.0    *               255.255.255.0   U     0      0        0 eth0
192.168.0.0     192.168.15.1    255.255.0.0     UG    0      0        0 eth0
default         192.168.254.254 0.0.0.0         UG    0      0        0 ppp0
Run Code Online (Sandbox Code Playgroud)

请注意,原始ppp连接(我用来提供正常状态输出的连接)仍然存在.我的/ etc/connect脚本没有循环(脚本在临时日志中没有新记录).

这里ping到DNS服务器:

# cat /etc/resolv.conf
#search moxa.com
nameserver 213.87.0.1
nameserver 213.87.1.1
# ping 213.87.0.1
PING 213.87.0.1 (213.87.0.1): 56 data bytes
64 bytes from 213.87.0.1: icmp_seq=0 ttl=59 time=559.8 ms
64 bytes from 213.87.0.1: icmp_seq=1 ttl=59 time=509.9 ms
64 bytes from 213.87.0.1: icmp_seq=2 ttl=59 time=559.8 ms
Run Code Online (Sandbox Code Playgroud)

和traceroute:

# traceroute 213.87.0.1
traceroute to 213.87.0.1 (213.87.0.1), 30 hops max, 40 byte packets
 1  172.16.4.210 (172.16.4.210)  542.449 ms  572.858 ms  595.681 ms
 2  172.16.4.214 (172.16.4.214)  590.392 ms  565.887 ms  676.919 ms
 3  * * *
 4  217.8.237.62 (217.8.237.62)  603.1 ms  569.078 ms  553.723 ms
 5  * * *
 6  * * *
 ## and so on ###
Run Code Online (Sandbox Code Playgroud)

*** 线路可能看起来很麻烦,但我在正常情况下为该DNS获取相同的traceroute

ping到172.16.4.210也可以正常工作.

现在到TCP.我已经在我的PC上启动了一个简单的echo服务器并尝试通过telnet连接到它(实际的ip地址未显示):

# telnet XXX.XXX.XXX.XXX 9060
Trying XXX.XXX.XXX.XXX(25635)...
Connected to XXX.XXX.XXX.XXX.
Escape character is '^]'.
aaabbbccc
Connection closed by foreign host.
Run Code Online (Sandbox Code Playgroud)

那就是这里发生的事情.connect()就像在我的自定义应用程序中成功,接着是Connection关闭...当telnet被调用时read().实际的服务器没有收到任何传入连接.为什么'connect()'正常返回(它无法从主机获得握手响应!)超出了我的知识范围.

果然telnet测试在正常状态下工作正常.

注意:

我没有在serverfault上发布这个因为我的系统的嵌入性质.据我所知,serverfault处理更传统的系统(比如运行'普通'linux的x86).我只希望stackoverflow有更多的嵌入式专家知道像我的Moxa这样的系统.

Mik*_*ton 5

:如果其他协议似乎已关闭,我如何解析DNS名称?

:您的本地DNS解析器(bind除此之外的另一种可能ncsd)可能是缓存第一个响应. dig会告诉你从哪里得到回复:

[mpenning@Bucksnort ~]$ dig cisco.com

; <<>> DiG 9.6-ESV-R4 <<>> +all cisco.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22106
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0

;; QUESTION SECTION:
;cisco.com.         IN  A

;; ANSWER SECTION:
cisco.com.      86367   IN  A   198.133.219.25

;; AUTHORITY SECTION:
cisco.com.      86367   IN  NS  ns2.cisco.com.
cisco.com.      86367   IN  NS  ns1.cisco.com.

;; Query time: 1 msec       <----------------------- 1msec is usually cached
;; SERVER: 127.0.0.1#53(127.0.0.1)  <--------------- Answered by localhost
;; WHEN: Wed Dec  7 04:41:21 2011
;; MSG SIZE  rcvd: 79

[mpenning@Bucksnort ~]$
Run Code Online (Sandbox Code Playgroud)

如果您从一个非常快速(低毫秒)的答案中得到答案127.0.0.1,那么您很可能从之前的同一DNS名称查询中获得了本地缓存的答案(人们使用缓存DNS解析器的情况很常见)ppp连接以减少连接时间,以及在ppp链路上实现小的负载减少).

如果您怀疑缓存的答案,请dig对其他DNS名称执行操作以查看是否也可以解析.

  • 如果随机DNS名称继续解析并且您仍然无法与某个主机建立TCP连接,那么在您进行此调查后编辑问题时,这是值得注意的.
  • 如果随机DNS名称无法解析,则表明丢失了默认路由或ppp连接断开.

其他诊断信息

如果您发现自己处于我描述的最后一种情况,您需要进行一些IP和ppp级调试,然后才能进一步隔离.正如有人提到的,tcpdump在这一点上是非常有价值的,但听起来你没有它.

我假设您没有与DNS服务器的同一IP地址建立TCP连接.此时有很多可能性......如果您仍然可以解析随机DNS名称,但TCP连接失败,则您可能看到的问题是在ppp连接的另一端,即内核路由缓存(它拥有一些像TCP状态信息一样的东西MSS搞砸了,你有太多的数据包丢失tcp或者任何数量的东西.

我们假设您的拓扑结构如下:

       10.1.1.2/30     10.1.1.1/30
       [ppp0]          [pppX]
uCLinux----------------------AccessServer---->[To the reset of the network]
Run Code Online (Sandbox Code Playgroud)

当您启动ppp连接时,请记下您的IP地址和默认网关的地址:

ip link show ppp0      # display the link status of your ppp0 intf (is it up?)
ip addr show ppp0      # display the IP address of your ppp0 interface
ip route show          # display your routing table
route -Cevn           # display the kernel's routing cache
Run Code Online (Sandbox Code Playgroud)

如果您没有将iproute2软件包作为发行版的一部分(iproute2提供ip实用程序),则可以找到类似的结果:

ifconfig ppp0               # display link status and addresses on ppp0
netstat -rn                 # display routing table
route -Cevn                 # display kernel routing table
Run Code Online (Sandbox Code Playgroud)

对于那些拥有iproute2实用程序的人(这几天几乎每个人都有),ifconfig已被弃用并被ip命令取代; 但是,如果你有一个较旧的2.2或2.4系统,你可能仍然需要使用ifconfig.

故障排除步骤:

  1. 当您开始遇到问题时,首先检查您是否可以ping pppX访问服务器上的地址.

    • 如果您无法ping通pppX另一方的IP地址,那么除了uCLinux计算机上的缓存响应之外,您的DNS很可能无法解析.
    • 如果你可以ping pppX,那么尝试pingTCP对等的IP地址和DNS的IP地址(如果它没有打开localhost).除非涉及防火墙,否则您必须能够ping成功地使用任何防火墙.
  2. 如果你可以ping的IP地址,pppX但你不能ping你的TCP对等的IP地址,检查你的路由表,看看你的默认路由是否仍然指出ppp0

  3. 如果您的默认路由指向ppp0,请检查您是否仍然可以ping默认路由的IP地址.

  4. 如果您可以使用ping默认路由并且可以ping连接到您尝试连接的远程主机,请检查内核的路由缓存中是否有远程TCP主机的IP地址....查找奇怪或可疑的内容

  5. 如果您可以 ping使用远程TCP主机(并且您需要做大约200个pings以确保... tcp对重大数据包丢失敏感且GPRS是众所周知的有损),请尝试取得成功telnet <remote_host> <remote_port>.如果两者都成功,那么现在是时候开始查看软件内部的线索了.

如果您仍然无法解决正在发生的事情,请在返回时包括上述命令的输出...以及如何开始ppp连接.