如何从 ICMP Time Exceeded 数据包中取回数据?
How to get data back from ICMP Time Exceeded packet?
我只想在python中做我自己的小traceroute
...
实际上,我已经有那么多工作了。我想要做的是异步地累积到多个主机的跟踪路由。为了做到这一点,我发送的数据包包含一个字节,作为每个跟踪器的唯一 ID。问题是,我在响应中的任何地方都看不到这个 ID。
这是我编写的一个简单测试 MCVE,用于演示使用一个数据包发送到一个 TTL 为 1 的主机:
import socket
# I need two sockets, because I'm sending datagrams
# (to avoid manual packet construction)
# but I'm receiving raw icmp packets
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, proto=socket.IPPROTO_UDP)
receiver = socket.socket(socket.AF_INET, socket.SOCK_RAW, proto=1) # 1 is icmp
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, 1)
sender.sendto(bytes([42]), ("8.8.8.8", 1)) #using google public dns for testing
pkt, addr = receiver.recvfrom(65536)
# The following line raises ValueError
print( pkt.index(42) )
# ... and so would this one
print( pkt.index(bytes([42])) )
所以你看,我只是试图将一个数据包发送到一台 TTL 为 1 的主机。我收到了一个响应,我已经手动解析了它足以知道第 21 个字节是 11
,第 22 个字节是 0
- 这表明正确的 ttl 超出了 ICMP 数据包。它returns的地址也是我在正常traceroute
到8.8.8.8
中看到的第一个地址
但是,在响应中的任何地方都找不到值为 42
的字节。我的数据怎么了?根据 multiple sources,我的原始数据报数据部分的前 8 个字节应该包含在响应中,但我似乎找不到其中一个字节。
如果重要的话,我是 MacOSX High Sierra 上的 运行 Python 3.6.3,我为脚本提供了打开套接字所需的根权限。
我想你对返回的内容感到困惑。返回 IP 有效载荷(IP 数据包中包含的数据报)的前八个八位字节。这足以包含 UDP header(八个八位字节),但 UDP 有效负载的 none。包含八个八位字节的目标是您将拥有 TCP 或 UDP 端口号,以便识别发送超过 TTL 的原始数据包的进程。这允许 IP 将消息发送到正确的进程。这在 RFC 792, Internet Control Message Protocol:
中有详细说明
Time Exceeded Message
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unused |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Internet Header + 64 bits of Original Data Datagram |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IP Fields:
Destination Address
The source network and address from the original datagram's data.
ICMP Fields:
Type
11
Code
0 = time to live exceeded in transit;
1 = fragment reassembly time exceeded.
Checksum
The checksum is the 16-bit ones's complement of the one's complement
sum of the ICMP message starting with the ICMP Type. For computing the
checksum , the checksum field should be zero. This checksum may be
replaced in the future.
Internet Header + 64 bits of Data Datagram
The internet header plus the first 64 bits of the original datagram's
data. This data is used by the host to match the message to the
appropriate process. If a higher level protocol uses port numbers,
they are assumed to be in the first 64 data bits of the original
datagram's data.
Description
If the gateway processing a datagram finds the time to live field is
zero it must discard the datagram. The gateway may also notify the
source host via the time exceeded message.
If a host reassembling a fragmented datagram cannot complete the
reassembly due to missing fragments within its time limit it discards
the datagram, and it may send a time exceeded message.
If fragment zero is not available then no time exceeded need be sent
at all.
Code 0 may be received from a gateway. Code 1 may be received from a
host.
我只想在python中做我自己的小traceroute
...
实际上,我已经有那么多工作了。我想要做的是异步地累积到多个主机的跟踪路由。为了做到这一点,我发送的数据包包含一个字节,作为每个跟踪器的唯一 ID。问题是,我在响应中的任何地方都看不到这个 ID。
这是我编写的一个简单测试 MCVE,用于演示使用一个数据包发送到一个 TTL 为 1 的主机:
import socket
# I need two sockets, because I'm sending datagrams
# (to avoid manual packet construction)
# but I'm receiving raw icmp packets
sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, proto=socket.IPPROTO_UDP)
receiver = socket.socket(socket.AF_INET, socket.SOCK_RAW, proto=1) # 1 is icmp
sender.setsockopt(socket.SOL_IP, socket.IP_TTL, 1)
sender.sendto(bytes([42]), ("8.8.8.8", 1)) #using google public dns for testing
pkt, addr = receiver.recvfrom(65536)
# The following line raises ValueError
print( pkt.index(42) )
# ... and so would this one
print( pkt.index(bytes([42])) )
所以你看,我只是试图将一个数据包发送到一台 TTL 为 1 的主机。我收到了一个响应,我已经手动解析了它足以知道第 21 个字节是 11
,第 22 个字节是 0
- 这表明正确的 ttl 超出了 ICMP 数据包。它returns的地址也是我在正常traceroute
到8.8.8.8
但是,在响应中的任何地方都找不到值为 42
的字节。我的数据怎么了?根据 multiple sources,我的原始数据报数据部分的前 8 个字节应该包含在响应中,但我似乎找不到其中一个字节。
如果重要的话,我是 MacOSX High Sierra 上的 运行 Python 3.6.3,我为脚本提供了打开套接字所需的根权限。
我想你对返回的内容感到困惑。返回 IP 有效载荷(IP 数据包中包含的数据报)的前八个八位字节。这足以包含 UDP header(八个八位字节),但 UDP 有效负载的 none。包含八个八位字节的目标是您将拥有 TCP 或 UDP 端口号,以便识别发送超过 TTL 的原始数据包的进程。这允许 IP 将消息发送到正确的进程。这在 RFC 792, Internet Control Message Protocol:
中有详细说明Time Exceeded Message
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IP Fields:
Destination Address
The source network and address from the original datagram's data.
ICMP Fields:
Type
11
Code
0 = time to live exceeded in transit;
1 = fragment reassembly time exceeded.
Checksum
The checksum is the 16-bit ones's complement of the one's complement sum of the ICMP message starting with the ICMP Type. For computing the checksum , the checksum field should be zero. This checksum may be replaced in the future.
Internet Header + 64 bits of Data Datagram
The internet header plus the first 64 bits of the original datagram's data. This data is used by the host to match the message to the appropriate process. If a higher level protocol uses port numbers, they are assumed to be in the first 64 data bits of the original datagram's data.
Description
If the gateway processing a datagram finds the time to live field is zero it must discard the datagram. The gateway may also notify the source host via the time exceeded message.
If a host reassembling a fragmented datagram cannot complete the reassembly due to missing fragments within its time limit it discards the datagram, and it may send a time exceeded message.
If fragment zero is not available then no time exceeded need be sent at all.
Code 0 may be received from a gateway. Code 1 may be received from a host.