Closed szmabcd closed 1 year ago
Hi szmabcd,
出于安全性考虑,现代路由设备都已经不再支持 Record Route,通常会丢弃此内容目前 Go 语言也没有在 IP 字段中设置 Record Route 消息头的 API,如果需要实现这个功能,需要更深入的重构底层 IPv4 头部,这会使得项目极其复杂,这不符合我们轻量化的理念。
你可以参考这段代码编写你自己的逻辑,我在 go.dev 源码中简化了构建,并且只加上了 Record Route 头。
package main
import (
"encoding/binary"
"fmt"
)
type IPv4Header struct {
Version uint8
IHL uint8
TOS uint8
Length uint16
Id uint16
Flags uint8
FragOff uint16
TTL uint8
Protocol uint8
Checksum uint16
Src [4]byte
Dst [4]byte
Options []byte
Payload []byte
}
func (h *IPv4Header) Marshal() []byte {
buf := make([]byte, h.IHL*4+len(h.Payload))
buf[0] = (h.Version << 4) | h.IHL
buf[1] = h.TOS
binary.BigEndian.PutUint16(buf[2:], h.Length)
binary.BigEndian.PutUint16(buf[4:], h.Id)
flagsAndFragOff := (uint16(h.Flags) << 13) | h.FragOff
binary.BigEndian.PutUint16(buf[6:], flagsAndFragOff)
buf[8] = h.TTL
buf[9] = h.Protocol
binary.BigEndian.PutUint16(buf[10:], h.Checksum)
copy(buf[12:], h.Src[:])
copy(buf[16:], h.Dst[:])
// 将选项和数据添加到缓冲区
copy(buf[20:], h.Options)
copy(buf[h.IHL*4:], h.Payload)
return buf
}
func main() {
// Set up a Record Route option
// Option Type: 7 (Record Route)
// Option Length: 39 (maximum length)
// Option Pointer: 4 (points to the first address field)
recordRouteOption := make([]byte, 39)
recordRouteOption[0] = 7
recordRouteOption[1] = 39
recordRouteOption[2] = 4
// A simple example: create an ICMP Echo request IP header
header := &IPv4Header{
Version: 4,
IHL: 5 + len(recordRouteOption)/4, // 5 for the base header, plus the number of 32-bit words in the option
TOS: 0,
Length: 100,
Id: 0,
Flags: 2,
FragOff: 0,
TTL: 64,
Protocol: 1, // ICMP
Src: [4]byte{192, 168, 3, 1},
Dst: [4]byte{192, 168, 3, 1},
Options: recordRouteOption,
}
buf := header.Marshal()
fmt.Println(buf)
}
Thanks.
Best Regards, Leo Shen
如无其他问题,本 issue 将被关闭
好的,谢谢!
------------------ 原始邮件 ------------------ 发件人: "sjlleo/nexttrace" @.>; 发送时间: 2023年5月27日(星期六) 中午11:17 @.>; @.**@.>; 主题: Re: [sjlleo/nexttrace] 能不能实现类似ping -r的功能 (Issue #118)
Hi szmabcd,
出于安全性考虑,现代路由设备都已经不再支持 Record Route,通常会丢弃此内容目前 Go 语言也没有在 IP 字段中设置 Record Route 消息头的 API,如果需要实现这个功能,需要更深入的重构底层 IPv4 头部,这会使得项目极其复杂,这不符合我们轻量化的理念。
你可以参考这段代码编写你自己的逻辑,我在 go.dev 源码中简化了构建,并且只加上了 Record Route 头。 package main import ( "encoding/binary" "fmt" ) type IPv4Header struct { Version uint8 IHL uint8 TOS uint8 Length uint16 Id uint16 Flags uint8 FragOff uint16 TTL uint8 Protocol uint8 Checksum uint16 Src [4]byte Dst [4]byte Options []byte Payload []byte } func (h IPv4Header) Marshal() []byte { buf := make([]byte, h.IHL4+len(h.Payload)) buf[0] = (h.Version << 4) | h.IHL buf[1] = h.TOS binary.BigEndian.PutUint16(buf[2:], h.Length) binary.BigEndian.PutUint16(buf[4:], h.Id) flagsAndFragOff := (uint16(h.Flags) << 13) | h.FragOff binary.BigEndian.PutUint16(buf[6:], flagsAndFragOff) buf[8] = h.TTL buf[9] = h.Protocol binary.BigEndian.PutUint16(buf[10:], h.Checksum) copy(buf[12:], h.Src[:]) copy(buf[16:], h.Dst[:]) // 将选项和数据添加到缓冲区 copy(buf[20:], h.Options) copy(buf[h.IHL*4:], h.Payload) return buf } func main() { // Set up a Record Route option // Option Type: 7 (Record Route) // Option Length: 39 (maximum length) // Option Pointer: 4 (points to the first address field) recordRouteOption := make([]byte, 39) recordRouteOption[0] = 7 recordRouteOption[1] = 39 recordRouteOption[2] = 4 // A simple example: create an ICMP Echo request IP header header := &IPv4Header{ Version: 4, IHL: 5 + len(recordRouteOption)/4, // 5 for the base header, plus the number of 32-bit words in the option TOS: 0, Length: 100, Id: 0, Flags: 2, FragOff: 0, TTL: 64, Protocol: 1, // ICMP Src: [4]byte{192, 168, 3, 1}, Dst: [4]byte{192, 168, 3, 1}, Options: recordRouteOption, } buf := header.Marshal() fmt.Println(buf) }
Thanks.
Best Regards, Leo Shen
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
类似windows下的ping -r功能,显示来回路径,
C:\Users\ZerOne>ping -r 9 192.168.3.1
正在 Ping 192.168.3.1 具有 32 字节的数据: 来自 192.168.3.1 的回复: 字节=32 时间=1ms TTL=64 路由: 192.168.3.1 -> 192.168.3.1 来自 192.168.3.1 的回复: 字节=32 时间=2ms TTL=64 路由: 192.168.3.1 -> 192.168.3.1 来自 192.168.3.1 的回复: 字节=32 时间=2ms TTL=64 路由: 192.168.3.1 -> 192.168.3.1 来自 192.168.3.1 的回复: 字节=32 时间=2ms TTL=64 路由: 192.168.3.1 ->