nxtrace / NTrace-core

NextTrace, an open source visual route tracking CLI tool
https://www.nxtrace.org
GNU General Public License v3.0
5.76k stars 340 forks source link

能不能实现类似ping -r的功能 #118

Closed szmabcd closed 1 year ago

szmabcd commented 1 year ago

类似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 ->

sjlleo commented 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

sjlleo commented 1 year ago

如无其他问题,本 issue 将被关闭

szmabcd commented 1 year ago

好的,谢谢!

------------------ 原始邮件 ------------------ 发件人: "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: @.***>