fix: 添加ipv6的hop日志记录

This commit is contained in:
spiritlhl 2025-04-08 13:37:54 +00:00
parent 466c8dbe5d
commit fcc0403612
2 changed files with 66 additions and 25 deletions

View File

@ -13,6 +13,7 @@ import (
"golang.org/x/net/icmp" "golang.org/x/net/icmp"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
. "github.com/oneclickvirt/defaultset"
) )
// DefaultConfig is the default configuration for Tracer. // DefaultConfig is the default configuration for Tracer.
@ -132,6 +133,16 @@ func (t *Tracer) init() {
conn, err := net.ListenIP(network, t.Addr) conn, err := net.ListenIP(network, t.Addr)
if err == nil { if err == nil {
t.ipv6conn = ipv6.NewPacketConn(conn) t.ipv6conn = ipv6.NewPacketConn(conn)
err = t.ipv6conn.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true)
if err != nil {
if EnableLoger {
InitLogger()
defer Logger.Sync()
Logger.Info("设置IPv6控制消息失败: " + err.Error())
}
t.ipv6conn.Close()
continue
}
go t.serveIPv6(t.ipv6conn) go t.serveIPv6(t.ipv6conn)
break break
} }
@ -224,18 +235,23 @@ func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
req := &packet{dst, id, ttl, time.Now()} req := &packet{dst, id, ttl, time.Now()}
if dst.To4() == nil { if dst.To4() == nil {
// IPv6 // IPv6
b = newPacketV6(id, dst, ttl) b := newPacketV6(id, dst, ttl)
if t.ipv6conn != nil { if t.ipv6conn != nil {
cm := &ipv6.ControlMessage{ cm := &ipv6.ControlMessage{
HopLimit: ttl, HopLimit: ttl,
} }
_, err := t.ipv6conn.WriteTo(b, cm, &net.IPAddr{IP: dst}) _, err := t.ipv6conn.WriteTo(b, cm, &net.IPAddr{IP: dst})
if err != nil { if err != nil {
if EnableLoger {
InitLogger()
defer Logger.Sync()
Logger.Info("发送IPv6请求失败: " + err.Error())
}
return nil, err return nil, err
} }
return req, nil return req, nil
} }
return nil, errors.New("IPv6 connection not available") return nil, errors.New("IPv6连接不可用")
} else { } else {
// IPv4 // IPv4
b = newPacketV4(id, dst, ttl) b = newPacketV4(id, dst, ttl)

View File

@ -1,7 +1,6 @@
package backtrace package backtrace
import ( import (
"encoding/binary"
"fmt" "fmt"
"net" "net"
"strings" "strings"
@ -11,45 +10,71 @@ import (
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
) )
// func newPacketV6(id uint16, dst net.IP, ttl int) []byte {
// // 创建ICMP消息回显请求
// msg := icmp.Message{
// Type: ipv6.ICMPTypeEchoRequest,
// Body: &icmp.Echo{
// ID: int(id),
// Seq: int(id),
// },
// }
// // 序列化ICMP消息
// icmpData, _ := msg.Marshal(nil)
// // 手动创建原始IPv6数据包头部
// ipHeaderBytes := make([]byte, ipv6.HeaderLen)
// // 设置版本和流量类别(第一个字节)
// ipHeaderBytes[0] = (ipv6.Version << 4)
// // 设置下一个头部(协议)
// ipHeaderBytes[6] = ProtocolIPv6ICMP
// // 设置跳数限制
// ipHeaderBytes[7] = byte(ttl)
// // 设置有效载荷长度2字节字段
// binary.BigEndian.PutUint16(ipHeaderBytes[4:6], uint16(len(icmpData)))
// // 设置目标地址最后16个字节
// copy(ipHeaderBytes[24:40], dst.To16())
// // 合并头部和ICMP数据
// return append(ipHeaderBytes, icmpData...)
// }
func newPacketV6(id uint16, dst net.IP, ttl int) []byte { func newPacketV6(id uint16, dst net.IP, ttl int) []byte {
// 创建ICMP消息回显请求 // 使用ipv6包的Echo请求
msg := icmp.Message{ msg := icmp.Message{
Type: ipv6.ICMPTypeEchoRequest, Type: ipv6.ICMPTypeEchoRequest,
Code: 0,
Body: &icmp.Echo{ Body: &icmp.Echo{
ID: int(id), ID: int(id),
Seq: int(id), Seq: int(id),
Data: []byte("HELLO-R-U-THERE"),
}, },
} }
// 序列化ICMP消息 // 序列化ICMP消息
icmpData, _ := msg.Marshal(nil) icmpBytes, _ := msg.Marshal(nil)
// 手动创建原始IPv6数据包头部 return icmpBytes
ipHeaderBytes := make([]byte, ipv6.HeaderLen)
// 设置版本和流量类别(第一个字节)
ipHeaderBytes[0] = (ipv6.Version << 4)
// 设置下一个头部(协议)
ipHeaderBytes[6] = ProtocolIPv6ICMP
// 设置跳数限制
ipHeaderBytes[7] = byte(ttl)
// 设置有效载荷长度2字节字段
binary.BigEndian.PutUint16(ipHeaderBytes[4:6], uint16(len(icmpData)))
// 设置目标地址最后16个字节
copy(ipHeaderBytes[24:40], dst.To16())
// 合并头部和ICMP数据
return append(ipHeaderBytes, icmpData...)
} }
func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error { func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error {
if EnableLoger {
InitLogger()
defer Logger.Sync()
}
defer conn.Close() defer conn.Close()
buf := make([]byte, 1500) buf := make([]byte, 1500)
for { for {
n, _, from, err := conn.ReadFrom(buf) n, cm, src, err := conn.ReadFrom(buf)
if err != nil { if err != nil {
if EnableLoger {
Logger.Error("读取IPv6响应失败: " + err.Error())
}
return err return err
} }
fromIP := from.(*net.IPAddr).IP if EnableLoger {
Logger.Info(fmt.Sprintf("收到IPv6响应: 来源=%v, 跳数=%d", src, cm.HopLimit))
}
fromIP := src.(*net.IPAddr).IP
err = t.serveData(fromIP, buf[:n]) err = t.serveData(fromIP, buf[:n])
if err != nil { if err != nil && EnableLoger {
continue Logger.Warn("处理IPv6数据失败: " + err.Error())
} }
} }
} }