mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-04-22 04:02:07 +08:00
Compare commits
6 Commits
153787b112
...
7a644b403e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7a644b403e | ||
![]() |
7efc61cbe4 | ||
![]() |
0c6b11883f | ||
![]() |
4f9603bee7 | ||
![]() |
509f6a3dd6 | ||
![]() |
8d69825c32 |
12
README.md
12
README.md
@ -10,17 +10,15 @@
|
|||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
- [x] 检测回程显示IPV4地址时的线路(使用1500字节的包),不显示IP地址时显示ASN检测不到,原版[backtrace](https://github.com/zhanghanyun/backtrace)也支持
|
- [x] 检测回程显示IPV4地址时的线路(使用1500字节的包),不显示IP地址时显示ASN检测不到
|
||||||
- [x] 支持对```4837```、```9929```和```163```线路的判断,原版[backtrace](https://github.com/zhanghanyun/backtrace)也支持
|
- [x] 支持对```9929```、```4837```和```163```线路的判断
|
||||||
- [x] 支持对```CN2GT```和```CN2GIA```线路的判断,原版[backtrace](https://github.com/zhanghanyun/backtrace)不支持,原版全部识别为```CN2```了
|
- [x] 支持对```CTGNET```、```CN2GIA```和```CN2GT```线路的判断
|
||||||
- [x] 支持对```CMIN2```和```CMI```线路的判断,原版[backtrace](https://github.com/zhanghanyun/backtrace)也支持,但所支持的IP区间不一样,本项目更多
|
- [x] 支持对```CMIN2```和```CMI```线路的判断
|
||||||
- [x] 支持对整个回程路由进行线路分析,与原版[backtrace](https://github.com/zhanghanyun/backtrace)仅进行一次判断不同
|
- [x] 支持对整个回程路由进行线路分析,一个目标IP可能会分析出多种线路
|
||||||
- [x] 修复原版[backtrace](https://github.com/zhanghanyun/backtrace)对IPV4地址信息获取时json解析失败依然打印信息的问题,本项目忽略错误继续执行路由线路查询
|
|
||||||
- [x] 增加对全平台的编译支持,原版[backtrace](https://github.com/zhanghanyun/backtrace)仅支持linux平台的amd64和arm64架构
|
- [x] 增加对全平台的编译支持,原版[backtrace](https://github.com/zhanghanyun/backtrace)仅支持linux平台的amd64和arm64架构
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] 增加对CTG回程的判断
|
|
||||||
- [ ] 自动检测汇聚层,裁剪结果不输出汇聚层后的线路(区分境内外段)
|
- [ ] 自动检测汇聚层,裁剪结果不输出汇聚层后的线路(区分境内外段)
|
||||||
- [ ] 添加对主流ISP的POP点检测,区分国际互联能力
|
- [ ] 添加对主流ISP的POP点检测,区分国际互联能力
|
||||||
- [ ] 增加IPV6路由能力检测
|
- [ ] 增加IPV6路由能力检测
|
||||||
|
4
back/README.md
Normal file
4
back/README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# 部分参考资料
|
||||||
|
|
||||||
|
https://blog.sunflyer.cn/archives/594
|
||||||
|
|
@ -29,6 +29,7 @@ var (
|
|||||||
}
|
}
|
||||||
m = map[string]string{
|
m = map[string]string{
|
||||||
// [] 前的字符串个数,中文占2个字符串
|
// [] 前的字符串个数,中文占2个字符串
|
||||||
|
"AS23764": "电信CTGNET [精品线路]",
|
||||||
"AS4809a": "电信CN2GIA [精品线路]",
|
"AS4809a": "电信CN2GIA [精品线路]",
|
||||||
"AS4809b": "电信CN2GT [优质线路]",
|
"AS4809b": "电信CN2GT [优质线路]",
|
||||||
"AS4134": "电信163 [普通线路]",
|
"AS4134": "电信163 [普通线路]",
|
||||||
@ -109,6 +110,10 @@ func trace(ch chan Result, i int) {
|
|||||||
if !strings.Contains(tempText, asnDescription) {
|
if !strings.Contains(tempText, asnDescription) {
|
||||||
tempText += DarkGreen(asnDescription) + " "
|
tempText += DarkGreen(asnDescription) + " "
|
||||||
}
|
}
|
||||||
|
case "AS23764":
|
||||||
|
if !strings.Contains(tempText, asnDescription) {
|
||||||
|
tempText += DarkGreen(asnDescription) + " "
|
||||||
|
}
|
||||||
case "AS4809b":
|
case "AS4809b":
|
||||||
if !strings.Contains(tempText, asnDescription) {
|
if !strings.Contains(tempText, asnDescription) {
|
||||||
tempText += Green(asnDescription) + " "
|
tempText += Green(asnDescription) + " "
|
||||||
@ -149,6 +154,8 @@ func ipAsn(ip string) string {
|
|||||||
return "AS58807"
|
return "AS58807"
|
||||||
case strings.HasPrefix(ip, "223.118") || strings.HasPrefix(ip, "223.119") || strings.HasPrefix(ip, "223.120") || strings.HasPrefix(ip, "223.121"):
|
case strings.HasPrefix(ip, "223.118") || strings.HasPrefix(ip, "223.119") || strings.HasPrefix(ip, "223.120") || strings.HasPrefix(ip, "223.121"):
|
||||||
return "AS58453"
|
return "AS58453"
|
||||||
|
case strings.HasPrefix(ip, "69.194") || strings.HasPrefix(ip, "203.22"):
|
||||||
|
return "AS23764"
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
//go:build linux || freebsd || openbsd || darwin
|
||||||
|
// +build linux freebsd openbsd darwin
|
||||||
|
|
||||||
package backtrace
|
package backtrace
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,53 +0,0 @@
|
|||||||
package backtrace
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
. "github.com/oneclickvirt/defaultset"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (t *Tracer) listen(network string, laddr *net.IPAddr) (*net.IPConn, error) {
|
|
||||||
if EnableLoger {
|
|
||||||
InitLogger()
|
|
||||||
defer Logger.Sync()
|
|
||||||
conn, err := net.ListenIP(network, laddr)
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
raw, err := conn.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_ = raw.Control(func(fd uintptr) {
|
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
} else {
|
|
||||||
conn, err := net.ListenIP(network, laddr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
raw, err := conn.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_ = raw.Control(func(fd uintptr) {
|
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package backtrace
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
. "github.com/oneclickvirt/defaultset"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (t *Tracer) listen(network string, laddr *net.IPAddr) (*net.IPConn, error) {
|
|
||||||
if EnableLoger {
|
|
||||||
InitLogger()
|
|
||||||
defer Logger.Sync()
|
|
||||||
conn, err := net.ListenIP(network, laddr)
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
raw, err := conn.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_ = raw.Control(func(fd uintptr) {
|
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
Logger.Info(err.Error())
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
} else {
|
|
||||||
conn, err := net.ListenIP(network, laddr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
raw, err := conn.SyscallConn()
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_ = raw.Control(func(fd uintptr) {
|
|
||||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,6 @@
|
|||||||
|
//go:build !linux && !freebsd && !openbsd && !darwin && !windows
|
||||||
|
// +build !linux,!freebsd,!openbsd,!darwin,!windows
|
||||||
|
|
||||||
package backtrace
|
package backtrace
|
||||||
|
|
||||||
import (
|
import (
|
@ -3,14 +3,16 @@ package backtrace
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"golang.org/x/net/icmp"
|
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
"golang.org/x/net/ipv6"
|
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConfig is the default configuration for Tracer.
|
// DefaultConfig is the default configuration for Tracer.
|
||||||
@ -43,7 +45,8 @@ type Tracer struct {
|
|||||||
Config
|
Config
|
||||||
|
|
||||||
once sync.Once
|
once sync.Once
|
||||||
conn *net.IPConn
|
conn *net.IPConn // Ipv4连接
|
||||||
|
ipv6conn *ipv6.PacketConn // IPv6连接
|
||||||
err error
|
err error
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
@ -113,13 +116,26 @@ func (t *Tracer) NewSession(ip net.IP) (*Session, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) init() {
|
func (t *Tracer) init() {
|
||||||
|
// 初始化IPv4连接
|
||||||
for _, network := range t.Networks {
|
for _, network := range t.Networks {
|
||||||
|
if strings.HasPrefix(network, "ip4") {
|
||||||
t.conn, t.err = t.listen(network, t.Addr)
|
t.conn, t.err = t.listen(network, t.Addr)
|
||||||
if t.err != nil {
|
if t.err == nil {
|
||||||
continue
|
|
||||||
}
|
|
||||||
go t.serve(t.conn)
|
go t.serve(t.conn)
|
||||||
return
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 初始化IPv6 ICMP连接
|
||||||
|
c, err := net.ListenPacket("ip6:ipv6-icmp", "")
|
||||||
|
if err == nil {
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err == nil {
|
||||||
|
t.ipv6conn = p
|
||||||
|
go t.serveIPv6(p)
|
||||||
|
} else {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +147,10 @@ func (t *Tracer) Close() {
|
|||||||
if t.conn != nil {
|
if t.conn != nil {
|
||||||
t.conn.Close()
|
t.conn.Close()
|
||||||
}
|
}
|
||||||
|
if t.ipv6conn != nil {
|
||||||
|
t.ipv6conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) serve(conn *net.IPConn) error {
|
func (t *Tracer) serve(conn *net.IPConn) error {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
buf := make([]byte, 1500)
|
buf := make([]byte, 1500)
|
||||||
@ -185,8 +203,13 @@ func (t *Tracer) serveData(from net.IP, b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
|
func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
|
||||||
|
if dst.To4() == nil {
|
||||||
|
// IPv6
|
||||||
|
return t.sendRequestV6(dst, ttl)
|
||||||
|
}
|
||||||
|
// Ipv4
|
||||||
id := uint16(atomic.AddUint32(&t.seq, 1))
|
id := uint16(atomic.AddUint32(&t.seq, 1))
|
||||||
b := newPacket(id, dst, ttl)
|
b := newPacketV4(id, dst, ttl)
|
||||||
req := &packet{dst, id, ttl, time.Now()}
|
req := &packet{dst, id, ttl, time.Now()}
|
||||||
_, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst})
|
_, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -352,33 +375,6 @@ var (
|
|||||||
errNoReplyData = errors.New("no reply data")
|
errNoReplyData = errors.New("no reply data")
|
||||||
)
|
)
|
||||||
|
|
||||||
func newPacket(id uint16, dst net.IP, ttl int) []byte {
|
|
||||||
// TODO: reuse buffers...
|
|
||||||
msg := icmp.Message{
|
|
||||||
Type: ipv4.ICMPTypeEcho,
|
|
||||||
Body: &icmp.Echo{
|
|
||||||
ID: int(id),
|
|
||||||
Seq: int(id),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
p, _ := msg.Marshal(nil)
|
|
||||||
ip := &ipv4.Header{
|
|
||||||
Version: ipv4.Version,
|
|
||||||
Len: ipv4.HeaderLen,
|
|
||||||
TotalLen: ipv4.HeaderLen + len(p),
|
|
||||||
TOS: 16,
|
|
||||||
ID: int(id),
|
|
||||||
Dst: dst,
|
|
||||||
Protocol: ProtocolICMP,
|
|
||||||
TTL: ttl,
|
|
||||||
}
|
|
||||||
buf, err := ip.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return append(buf, p...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IANA Assigned Internet Protocol Numbers
|
// IANA Assigned Internet Protocol Numbers
|
||||||
const (
|
const (
|
||||||
ProtocolICMP = 1
|
ProtocolICMP = 1
|
35
bk/trace_ipv4.go
Normal file
35
bk/trace_ipv4.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package backtrace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newPacketV4(id uint16, dst net.IP, ttl int) []byte {
|
||||||
|
// TODO: reuse buffers...
|
||||||
|
msg := icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: int(id),
|
||||||
|
Seq: int(id),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p, _ := msg.Marshal(nil)
|
||||||
|
ip := &ipv4.Header{
|
||||||
|
Version: ipv4.Version,
|
||||||
|
Len: ipv4.HeaderLen,
|
||||||
|
TotalLen: ipv4.HeaderLen + len(p),
|
||||||
|
TOS: 16,
|
||||||
|
ID: int(id),
|
||||||
|
Dst: dst,
|
||||||
|
Protocol: ProtocolICMP,
|
||||||
|
TTL: ttl,
|
||||||
|
}
|
||||||
|
buf, err := ip.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return append(buf, p...)
|
||||||
|
}
|
125
bk/trace_ipv6.go
Normal file
125
bk/trace_ipv6.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package backtrace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newPacketV6(id uint16, dst net.IP, ttl int) ([]byte, error) {
|
||||||
|
// 创建ICMPv6 Echo请求消息
|
||||||
|
msg := icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest,
|
||||||
|
Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: int(id),
|
||||||
|
Seq: int(id),
|
||||||
|
Data: []byte("TRACEROUTE"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接序列化ICMPv6消息
|
||||||
|
// 第一个参数是协议号,对于ICMPv6应该是58
|
||||||
|
return msg.Marshal(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tracer) sendRequestV6(dst net.IP, ttl int) (*packet, error) {
|
||||||
|
id := uint16(atomic.AddUint32(&t.seq, 1))
|
||||||
|
// 创建ICMPv6消息
|
||||||
|
msg := icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest,
|
||||||
|
Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: int(id),
|
||||||
|
Seq: int(id),
|
||||||
|
Data: []byte("TRACEROUTE"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 序列化ICMPv6消息
|
||||||
|
b, err := msg.Marshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 获取底层连接
|
||||||
|
ipv6Conn, err := t.getIPv6Conn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 设置IPv6数据包的跳数限制(TTL)
|
||||||
|
if err := ipv6Conn.SetHopLimit(ttl); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 发送数据包
|
||||||
|
if _, err := ipv6Conn.WriteTo(b, nil, &net.IPAddr{IP: dst}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 创建一个数据包记录,用于后续匹配回复
|
||||||
|
req := &packet{dst, id, ttl, time.Now()}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIPv6Conn 获取IPv6的PacketConn接口
|
||||||
|
func (t *Tracer) getIPv6Conn() (*ipv6.PacketConn, error) {
|
||||||
|
if t.ipv6conn != nil {
|
||||||
|
return t.ipv6conn, nil
|
||||||
|
}
|
||||||
|
// 创建一个UDP连接
|
||||||
|
c, err := net.ListenPacket("udp6", "::")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 将其包装为IPv6 PacketConn
|
||||||
|
p := ipv6.NewPacketConn(c)
|
||||||
|
// 设置控制消息
|
||||||
|
if err := p.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true); err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t.ipv6conn = p
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error {
|
||||||
|
defer conn.Close()
|
||||||
|
buf := make([]byte, 1500)
|
||||||
|
for {
|
||||||
|
n, cm, src, err := conn.ReadFrom(buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 从控制消息中获取跳数限制
|
||||||
|
hopLimit := 0
|
||||||
|
if cm != nil {
|
||||||
|
hopLimit = cm.HopLimit
|
||||||
|
}
|
||||||
|
// 解析ICMP消息
|
||||||
|
msg, err := icmp.ParseMessage(ProtocolIPv6ICMP, buf[:n])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 根据消息类型处理
|
||||||
|
switch msg.Type {
|
||||||
|
case ipv6.ICMPTypeEchoReply:
|
||||||
|
echo := msg.Body.(*icmp.Echo)
|
||||||
|
t.serveReply(src.(*net.IPAddr).IP, &packet{src.(*net.IPAddr).IP, uint16(echo.ID), hopLimit, time.Now()})
|
||||||
|
case ipv6.ICMPTypeTimeExceeded:
|
||||||
|
// 处理超时消息,获取原始数据包
|
||||||
|
data := msg.Body.(*icmp.TimeExceeded).Data
|
||||||
|
// 尝试提取嵌入的原始Echo请求
|
||||||
|
if len(data) < 8 { // 至少需要IPv6头部前8个字节
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 跳过IPv6头部和ICMPv6头部,简化处理,实际可能需要更复杂的解析
|
||||||
|
innerMsg, err := icmp.ParseMessage(ProtocolIPv6ICMP, data[48:])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if echo, ok := innerMsg.Body.(*icmp.Echo); ok {
|
||||||
|
t.serveReply(src.(*net.IPAddr).IP, &packet{src.(*net.IPAddr).IP, uint16(echo.ID), hopLimit, time.Now()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user