提问人:Swagnik Dutta 提问时间:9/4/2023 最后编辑:Swagnik Dutta 更新时间:9/5/2023 访问量:92
如何验证ICMP回显数据包的校验和?
How to validate the checksum of an ICMP echo packet?
问:
我有一个 ping 实用程序的工作实现,我将其作为业余爱好项目进行。我很难弄清楚在收到回显回复数据包时应如何验证校验和。我会解释为什么。
以下是我创建 ICMP 回显请求数据包的方法。
type ICMPHeader struct {
Type uint8
Code uint8
Checksum uint16
Identifier uint16
SequenceNumber uint16
}
type ICMPPacket struct {
Header *ICMPHeader
}
func (pinger *Pinger) createICMPPacket(seqNo int) (*ICMPPacket, error) {
packet := &ICMPPacket{
Header: &ICMPHeader{
Type: ICMPHeaderType,
Code: ICMPHeaderSubtype,
Checksum: 0, // initially zeroed
Identifier: 0,
SequenceNumber: uint16(seqNo),
},
}
packetSerialized, err := packet.Serialize()
if err != nil {
return nil, errors.Wrapf(err, "error serializing ICMP packet")
}
packet.Header.Checksum = calculateChecksum(packetSerialized)
return packet, nil
}
数据包中没有有效负载/数据部分,因为对于我发送回显请求数据包的用例,我在标头中包含所有相关字段。
ICMP 校验和是针对整个消息(包括标头和数据)计算的。但是,由于此方案中没有数据,因此仅使用标头字节作为校验和来完成计算。08 00 00 00 00 00 00 00
f7 ff
因此,我最终发出的字节流的 ICMP 部分是,08 00 f7 ff 00 00 00 00
但是在 Wireshark 中,我看到一些任意 22 字节被添加为我的 ICMP 数据包字节流中的数据。这些字节似乎包含来自 IPv4 标头的一些信息。
第一个问题,这些字节是如何添加的?
继续前进,根据 RFC792 第 15 页中所写的内容,
在回显消息中接收到的数据必须在回显应答消息中返回。
我的回显应答数据包包含与数据包数据相同的 22 字节流。
我了解,在收到 ICMP 回显应答数据包后,校验和验证应包括将校验和字段归零,重新计算整个 ICMP 数据包(包括标头和有效负载)的校验和,然后将其与先前计算的校验和进行比较。
这就引出了我的下一组问题
- ICMP 数据包中存在任意字节(在校验和计算期间未包含任意字节)(仅基于标头数据)是否会影响我的校验和验证逻辑?我应该考虑它们,还是应该只考虑标头数据进行验证?
- 即使我选择忽略任意字节,仍然存在回显数据包(类型 8)和回显应答数据包(类型 0)之间的字段不同的问题。“类型”字段中的这种差异可确保校验和不匹配。我应该如何解决这个问题?
Type
我没有找到任何关于如何验证 ICMP 回显回复的校验和的规则,即使实际的 ping 实现也不会打扰回显回复的 csfailed
变量。
任何帮助都是值得赞赏的。
答: 暂无答案
评论
Write
net.Conn
golang.org/x/net/icmp
net/icmp
net.Addr
func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error)
fd_unix.go
conn.Write
func (fd *FD) Write(p []byte) (int, error) {