From a832d354da2382e3ee43aebccb859a1a34ded363 Mon Sep 17 00:00:00 2001 From: spiritlhl <103393591+spiritLHLS@users.noreply.github.com> Date: Fri, 11 Apr 2025 13:35:35 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=93=E6=9E=84=E5=8C=96IPV4?= =?UTF-8?q?=E5=92=8CIPV6=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bk/asn.go | 95 -------------------------------------------- bk/backtrace.go | 14 ++++--- bk/ipv4_asn.go | 31 +++++++++++++++ bk/listen_common.go | 55 ++++++++++++------------- bk/listen_unknown.go | 9 +++-- bk/listen_windows.go | 63 ++++++++++++++--------------- bk/trace_common.go | 41 +++++++++---------- bk/trace_ipv4.go | 51 ++++++++++++------------ bk/trace_ipv6.go | 59 +++++++++++++-------------- bk/utils.go | 66 ++++++++++++++++++++++++++++++ bk/version.go | 5 --- cmd/main.go | 7 ++-- go.mod | 23 ++++++++++- go.sum | 44 ++++++++++++++++++++ model/model.go | 65 ++++++++++++++++++++++++++++++ 15 files changed, 381 insertions(+), 247 deletions(-) delete mode 100644 bk/asn.go create mode 100644 bk/ipv4_asn.go create mode 100644 bk/utils.go delete mode 100644 bk/version.go create mode 100644 model/model.go diff --git a/bk/asn.go b/bk/asn.go deleted file mode 100644 index de95028..0000000 --- a/bk/asn.go +++ /dev/null @@ -1,95 +0,0 @@ -package backtrace - -import ( - "strings" -) - -type Result struct { - i int - s string -} - -var ( - ipv4s = []string{ - // "219.141.136.12", "202.106.50.1", - "219.141.140.10", "202.106.195.68", "221.179.155.161", - "202.96.209.133", "210.22.97.1", "211.136.112.200", - "58.60.188.222", "210.21.196.6", "120.196.165.24", - "61.139.2.69", "119.6.6.6", "211.137.96.205", - } - ipv4Names = []string{ - "北京电信v4", "北京联通v4", "北京移动v4", - "上海电信v4", "上海联通v4", "上海移动v4", - "广州电信v4", "广州联通v4", "广州移动v4", - "成都电信v4", "成都联通v4", "成都移动v4", - } - ipv6s = []string{ - "2400:89c0:1053:3::69", // 北京电信 IPv6 - "2400:89c0:1013:3::54", // 北京联通 IPv6 - "2409:8c00:8421:1303::55", // 北京移动 IPv6 - "240e:e1:aa00:4000::24", // 上海电信 IPV6 - "2408:80f1:21:5003::a", // 上海联通 IPv6 - "2409:8c1e:75b0:3003::26", // 上海移动 IPv6 - "240e:97c:2f:3000::44", // 广州电信 IPv6 - "2408:8756:f50:1001::c", // 广州联通 IPv6 - "2409:8c54:871:1001::12", // 广州移动 IPv6 - } - ipv6Names = []string{ - "北京电信v6", "北京联通v6", "北京移动v6", - "上海电信v6", "上海联通v6", "上海移动v6", - "广州电信v6", "广州联通v6", "广州移动v6", - } - m = map[string]string{ - // [] 前的字符串个数,中文占2个字符串 - "AS23764": "电信CTGNET [精品线路]", - "AS4809a": "电信CN2GIA [精品线路]", - "AS4809b": "电信CN2GT [优质线路]", - "AS4809": "电信CN2 [优质线路]", - "AS4134": "电信163 [普通线路]", - "AS9929": "联通9929 [优质线路]", - "AS4837": "联通4837 [普通线路]", - "AS58807": "移动CMIN2 [精品线路]", - "AS9808": "移动CMI [普通线路]", - "AS58453": "移动CMI [普通线路]", - } -) - -func removeDuplicates(elements []string) []string { - encountered := map[string]bool{} // 用于存储已经遇到的元素 - result := []string{} // 存储去重后的结果 - for v := range elements { // 遍历切片中的元素 - if encountered[elements[v]] == true { // 如果该元素已经遇到过 - // 存在过就不加入了 - } else { - encountered[elements[v]] = true // 将该元素标记为已经遇到 - result = append(result, elements[v]) // 将该元素加入到结果切片中 - } - } - return result // 返回去重后的结果切片 -} - -func ipAsn(ip string) string { - if strings.Contains(ip, ":") { - return ipv6Asn(ip) - } - switch { - case strings.HasPrefix(ip, "59.43"): - return "AS4809" - case strings.HasPrefix(ip, "202.97"): - return "AS4134" - case strings.HasPrefix(ip, "218.105") || strings.HasPrefix(ip, "210.51"): - return "AS9929" - case strings.HasPrefix(ip, "219.158"): - return "AS4837" - case strings.HasPrefix(ip, "223.120.19") || strings.HasPrefix(ip, "223.120.17") || strings.HasPrefix(ip, "223.120.16") || - strings.HasPrefix(ip, "223.120.140") || strings.HasPrefix(ip, "223.120.130") || strings.HasPrefix(ip, "223.120.131") || - strings.HasPrefix(ip, "223.120.141"): - return "AS58807" - case strings.HasPrefix(ip, "223.118") || strings.HasPrefix(ip, "223.119") || strings.HasPrefix(ip, "223.120") || strings.HasPrefix(ip, "223.121"): - return "AS58453" - case strings.HasPrefix(ip, "69.194") || strings.HasPrefix(ip, "203.22"): - return "AS23764" - default: - return "" - } -} diff --git a/bk/backtrace.go b/bk/backtrace.go index 8069a12..452b382 100644 --- a/bk/backtrace.go +++ b/bk/backtrace.go @@ -3,22 +3,24 @@ package backtrace import ( "fmt" "time" + + "github.com/oneclickvirt/backtrace/model" ) func BackTrace(test bool) { if test { - ipv4Count := len(ipv4s) - ipv6Count := len(ipv6s) + ipv4Count := len(model.Ipv4s) + ipv6Count := len(model.Ipv6s) totalCount := ipv4Count + ipv6Count var ( s = make([]string, totalCount) c = make(chan Result) t = time.After(time.Second * 10) ) - for i := range ipv4s { + for i := range model.Ipv4s { go trace(c, i) } - for i := range ipv6s { + for i := range model.Ipv6s { go traceIPv6(c, i, ipv4Count) } loopIPv4v6: @@ -41,13 +43,13 @@ func BackTrace(test bool) { } } } else { - ipCount := len(ipv4s) + ipCount := len(model.Ipv4s) var ( s = make([]string, ipCount) c = make(chan Result) t = time.After(time.Second * 10) ) - for i := range ipv4s { + for i := range model.Ipv4s { go trace(c, i) } loopIPv4: diff --git a/bk/ipv4_asn.go b/bk/ipv4_asn.go new file mode 100644 index 0000000..8b35710 --- /dev/null +++ b/bk/ipv4_asn.go @@ -0,0 +1,31 @@ +package backtrace + +import ( + "strings" +) + +func ipv4Asn(ip string) string { + if strings.Contains(ip, ":") { + return ipv6Asn(ip) + } + switch { + case strings.HasPrefix(ip, "59.43"): + return "AS4809" + case strings.HasPrefix(ip, "202.97"): + return "AS4134" + case strings.HasPrefix(ip, "218.105") || strings.HasPrefix(ip, "210.51"): + return "AS9929" + case strings.HasPrefix(ip, "219.158"): + return "AS4837" + case strings.HasPrefix(ip, "223.120.19") || strings.HasPrefix(ip, "223.120.17") || strings.HasPrefix(ip, "223.120.16") || + strings.HasPrefix(ip, "223.120.140") || strings.HasPrefix(ip, "223.120.130") || strings.HasPrefix(ip, "223.120.131") || + strings.HasPrefix(ip, "223.120.141"): + return "AS58807" + case strings.HasPrefix(ip, "223.118") || strings.HasPrefix(ip, "223.119") || strings.HasPrefix(ip, "223.120") || strings.HasPrefix(ip, "223.121"): + return "AS58453" + case strings.HasPrefix(ip, "69.194") || strings.HasPrefix(ip, "203.22"): + return "AS23764" + default: + return "" + } +} diff --git a/bk/listen_common.go b/bk/listen_common.go index 1ed3370..939b848 100644 --- a/bk/listen_common.go +++ b/bk/listen_common.go @@ -7,34 +7,35 @@ import ( "net" "syscall" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" ) func (t *Tracer) listen(network string, laddr *net.IPAddr) (*net.IPConn, error) { - conn, err := net.ListenIP(network, laddr) - if err != nil { - if EnableLoger { - Logger.Info(err.Error()) - } - return nil, err - } - raw, err := conn.SyscallConn() - if err != nil { - if EnableLoger { - 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 { - if EnableLoger { - Logger.Info(err.Error()) - } - conn.Close() - return nil, err - } - return conn, nil -} \ No newline at end of file + conn, err := net.ListenIP(network, laddr) + if err != nil { + if model.EnableLoger { + Logger.Info(err.Error()) + } + return nil, err + } + raw, err := conn.SyscallConn() + if err != nil { + if model.EnableLoger { + 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 { + if model.EnableLoger { + Logger.Info(err.Error()) + } + conn.Close() + return nil, err + } + return conn, nil +} diff --git a/bk/listen_unknown.go b/bk/listen_unknown.go index bb3fde5..b6b1191 100644 --- a/bk/listen_unknown.go +++ b/bk/listen_unknown.go @@ -7,24 +7,25 @@ import ( "net" "syscall" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" ) func (t *Tracer) listen(network string, laddr *net.IPAddr) (*net.IPConn, error) { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() } conn, err := net.ListenIP(network, laddr) if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Info(err.Error()) } return nil, err } raw, err := conn.SyscallConn() if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Info(err.Error()) } conn.Close() @@ -34,7 +35,7 @@ func (t *Tracer) listen(network string, laddr *net.IPAddr) (*net.IPConn, error) err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1) }) if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Info(err.Error()) } conn.Close() diff --git a/bk/listen_windows.go b/bk/listen_windows.go index 5f87269..d2ddd1b 100644 --- a/bk/listen_windows.go +++ b/bk/listen_windows.go @@ -6,39 +6,40 @@ package backtrace import ( "net" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" "golang.org/x/sys/windows" ) 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 { - if EnableLoger { - Logger.Info(err.Error()) - } - return nil, err - } - raw, err := conn.SyscallConn() - if err != nil { - if EnableLoger { - Logger.Info(err.Error()) - } - conn.Close() - return nil, err - } - _ = raw.Control(func(fd uintptr) { - err = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_HDRINCL, 1) - }) - if err != nil { - if EnableLoger { - Logger.Info(err.Error()) - } - conn.Close() - return nil, err - } - return conn, nil -} \ No newline at end of file + if model.EnableLoger { + InitLogger() + defer Logger.Sync() + } + conn, err := net.ListenIP(network, laddr) + if err != nil { + if model.EnableLoger { + Logger.Info(err.Error()) + } + return nil, err + } + raw, err := conn.SyscallConn() + if err != nil { + if model.EnableLoger { + Logger.Info(err.Error()) + } + conn.Close() + return nil, err + } + _ = raw.Control(func(fd uintptr) { + err = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, windows.IP_HDRINCL, 1) + }) + if err != nil { + if model.EnableLoger { + Logger.Info(err.Error()) + } + conn.Close() + return nil, err + } + return conn, nil +} diff --git a/bk/trace_common.go b/bk/trace_common.go index 1847de2..208a45c 100644 --- a/bk/trace_common.go +++ b/bk/trace_common.go @@ -11,6 +11,7 @@ import ( "sync/atomic" "time" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" @@ -136,7 +137,7 @@ func (t *Tracer) init() { t.ipv6conn = ipv6.NewPacketConn(conn) err = t.ipv6conn.SetControlMessage(ipv6.FlagHopLimit|ipv6.FlagSrc|ipv6.FlagDst|ipv6.FlagInterface, true) if err != nil { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() Logger.Info("设置IPv6控制消息失败: " + err.Error()) @@ -183,19 +184,19 @@ func (t *Tracer) serveData(from net.IP, b []byte) error { // IPv6处理 msg, err := icmp.ParseMessage(ProtocolIPv6ICMP, b) if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Warn("解析IPv6 ICMP消息失败: " + err.Error()) } return err } // 记录所有收到的消息类型,帮助调试 - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("收到IPv6 ICMP消息: 类型=%v, 代码=%v", msg.Type, msg.Code)) } // 处理不同类型的ICMP消息 if msg.Type == ipv6.ICMPTypeEchoReply { if echo, ok := msg.Body.(*icmp.Echo); ok { - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("处理IPv6回显应答: ID=%d, Seq=%d", echo.ID, echo.Seq)) } return t.serveReply(from, &packet{from, uint16(echo.ID), 1, time.Now()}) @@ -203,7 +204,7 @@ func (t *Tracer) serveData(from net.IP, b []byte) error { } else if msg.Type == ipv6.ICMPTypeTimeExceeded { b = getReplyData(msg) if len(b) < ipv6.HeaderLen { - if EnableLoger { + if model.EnableLoger { Logger.Warn("IPv6时间超过消息太短") } return errMessageTooShort @@ -212,12 +213,12 @@ func (t *Tracer) serveData(from net.IP, b []byte) error { if b[0]>>4 == ipv6.Version { ip, err := ipv6.ParseHeader(b) if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Warn("解析IPv6头部失败: " + err.Error()) } return err } - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("处理IPv6时间超过: 目标=%v, FlowLabel=%d, HopLimit=%d", ip.Dst, ip.FlowLabel, ip.HopLimit)) } @@ -265,7 +266,7 @@ func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) { } _, err := t.ipv6conn.WriteTo(b, cm, &net.IPAddr{IP: dst}) if err != nil { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() Logger.Info("发送IPv6请求失败: " + err.Error()) @@ -308,7 +309,7 @@ func (t *Tracer) removeSession(s *Session) { } func (t *Tracer) serveReply(dst net.IP, res *packet) error { - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("处理回复: 目标=%v, 来源=%v, ID=%d, TTL=%d", dst, res.IP, res.ID, res.TTL)) } @@ -317,7 +318,7 @@ func (t *Tracer) serveReply(dst net.IP, res *packet) error { t.mu.RLock() defer t.mu.RUnlock() // // 调试输出会话信息 - // if EnableLoger && len(t.sess) > 0 { + // if model.EnableLoger && len(t.sess) > 0 { // for ip, sessions := range t.sess { // Logger.Info(fmt.Sprintf("会话信息: IP=%v, 会话数=%d", // net.IP([]byte(ip)), len(sessions))) @@ -325,11 +326,11 @@ func (t *Tracer) serveReply(dst net.IP, res *packet) error { // } // 查找对应的会话 a := t.sess[string(shortDst)] - if len(a) == 0 && EnableLoger { + if len(a) == 0 && model.EnableLoger { Logger.Warn(fmt.Sprintf("找不到目标IP=%v的会话", dst)) } for _, s := range a { - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("处理会话响应: 会话目标=%v", s.ip)) } s.handle(res) @@ -395,13 +396,13 @@ func (s *Session) handle(res *packet) { now := res.Time n := 0 var req *packet - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("处理会话响应: 会话目标=%v, 响应源=%v, ID=%d, TTL=%d", s.ip, res.IP, res.ID, res.TTL)) } s.mu.Lock() // // 打印出所有待处理的探测包 - // if EnableLoger && len(s.probes) > 0 { + // if model.EnableLoger && len(s.probes) > 0 { // Logger.Info(fmt.Sprintf("当前会话有 %d 个待处理的探测包", len(s.probes))) // for i, probe := range s.probes { // Logger.Info(fmt.Sprintf("探测包 #%d: ID=%d, TTL=%d, 时间=%v", @@ -411,14 +412,14 @@ func (s *Session) handle(res *packet) { // 查找匹配的请求包 for _, r := range s.probes { if now.Sub(r.Time) > s.t.Timeout { - // if EnableLoger { + // if model.EnableLoger { // Logger.Info(fmt.Sprintf("探测包超时: ID=%d, TTL=%d", r.ID, r.TTL)) // } continue } // 对于IPv6 松散匹配 if r.ID == res.ID || res.IP.To4() == nil { - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("找到匹配的探测包: ID=%d, TTL=%d", r.ID, r.TTL)) } req = r @@ -430,7 +431,7 @@ func (s *Session) handle(res *packet) { s.probes = s.probes[:n] s.mu.Unlock() if req == nil { - if EnableLoger { + if model.EnableLoger { Logger.Warn(fmt.Sprintf("未找到匹配的探测包: 响应ID=%d", res.ID)) } return @@ -439,7 +440,7 @@ func (s *Session) handle(res *packet) { if hops < 1 { hops = 1 } - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("创建响应: IP=%v, RTT=%v, Hops=%d", res.IP, res.Time.Sub(req.Time), hops)) } @@ -449,11 +450,11 @@ func (s *Session) handle(res *packet) { RTT: res.Time.Sub(req.Time), Hops: hops, }: - if EnableLoger { + if model.EnableLoger { Logger.Info("响应已发送到通道") } default: - if EnableLoger { + if model.EnableLoger { Logger.Warn("发送响应到通道失败,通道已满") } } diff --git a/bk/trace_ipv4.go b/bk/trace_ipv4.go index 3f144d2..8621b85 100644 --- a/bk/trace_ipv4.go +++ b/bk/trace_ipv4.go @@ -5,6 +5,7 @@ import ( "net" "strings" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" @@ -39,37 +40,37 @@ func newPacketV4(id uint16, dst net.IP, ttl int) []byte { // trace IPv4追踪函数 func trace(ch chan Result, i int) { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() - Logger.Info(fmt.Sprintf("开始追踪 %s (%s)", ipv4Names[i], ipv4s[i])) + Logger.Info(fmt.Sprintf("开始追踪 %s (%s)", model.Ipv4Names[i], model.Ipv4s[i])) } - hops, err := Trace(net.ParseIP(ipv4s[i])) + hops, err := Trace(net.ParseIP(model.Ipv4s[i])) if err != nil { - s := fmt.Sprintf("%v %-15s %v", ipv4Names[i], ipv4s[i], err) + s := fmt.Sprintf("%v %-15s %v", model.Ipv4Names[i], model.Ipv4s[i], err) - if EnableLoger { - Logger.Error(fmt.Sprintf("追踪 %s (%s) 失败: %v", ipv4Names[i], ipv4s[i], err)) + if model.EnableLoger { + Logger.Error(fmt.Sprintf("追踪 %s (%s) 失败: %v", model.Ipv4Names[i], model.Ipv4s[i], err)) } ch <- Result{i, s} return } // 记录每个hop的信息 - if EnableLoger { + if model.EnableLoger { for hopNum, hop := range hops { for nodeNum, node := range hop.Nodes { Logger.Info(fmt.Sprintf("追踪 %s (%s) - Hop %d, Node %d: %s (RTT: %v)", - ipv4Names[i], ipv4s[i], hopNum+1, nodeNum+1, node.IP.String(), node.RTT)) + model.Ipv4Names[i], model.Ipv4s[i], hopNum+1, nodeNum+1, node.IP.String(), node.RTT)) } } } var asns []string for _, h := range hops { for _, n := range h.Nodes { - asn := ipAsn(n.IP.String()) + asn := ipv4Asn(n.IP.String()) if asn != "" { asns = append(asns, asn) - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("IP %s 对应的ASN: %s", n.IP.String(), asn)) } } @@ -79,7 +80,7 @@ func trace(ch chan Result, i int) { if asns != nil && len(asns) > 0 { var tempText string asns = removeDuplicates(asns) - tempText += fmt.Sprintf("%v ", ipv4Names[i]) + tempText += fmt.Sprintf("%v ", model.Ipv4Names[i]) hasAS4134 := false hasAS4809 := false for _, asn := range asns { @@ -94,19 +95,19 @@ func trace(ch chan Result, i int) { if hasAS4134 && hasAS4809 { // 同时包含 AS4134 和 AS4809 属于 CN2GT asns = append([]string{"AS4809b"}, asns...) - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GT", ipv4Names[i], ipv4s[i])) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GT", model.Ipv4Names[i], model.Ipv4s[i])) } } else if hasAS4809 { // 仅包含 AS4809 属于 CN2GIA asns = append([]string{"AS4809a"}, asns...) - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GIA", ipv4Names[i], ipv4s[i])) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GIA", model.Ipv4Names[i], model.Ipv4s[i])) } } - tempText += fmt.Sprintf("%-24s ", ipv4s[i]) + tempText += fmt.Sprintf("%-24s ", model.Ipv4s[i]) for _, asn := range asns { - asnDescription := m[asn] + asnDescription := model.M[asn] switch asn { case "": continue @@ -138,22 +139,22 @@ func trace(ch chan Result, i int) { } } } - if tempText == (fmt.Sprintf("%v ", ipv4Names[i]) + fmt.Sprintf("%-15s ", ipv4s[i])) { + if tempText == (fmt.Sprintf("%v ", model.Ipv4Names[i]) + fmt.Sprintf("%-15s ", model.Ipv4s[i])) { tempText += fmt.Sprintf("%v", Red("检测不到已知线路的ASN")) - if EnableLoger { - Logger.Warn(fmt.Sprintf("%s (%s) 检测不到已知线路的ASN", ipv4Names[i], ipv4s[i])) + if model.EnableLoger { + Logger.Warn(fmt.Sprintf("%s (%s) 检测不到已知线路的ASN", model.Ipv4Names[i], model.Ipv4s[i])) } } - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 追踪完成,结果: %s", ipv4Names[i], ipv4s[i], tempText)) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 追踪完成,结果: %s", model.Ipv4Names[i], model.Ipv4s[i], tempText)) } ch <- Result{i, tempText} } else { - s := fmt.Sprintf("%v %-15s %v", ipv4Names[i], ipv4s[i], Red("检测不到回程路由节点的IP地址")) + s := fmt.Sprintf("%v %-15s %v", model.Ipv4Names[i], model.Ipv4s[i], Red("检测不到回程路由节点的IP地址")) - if EnableLoger { - Logger.Warn(fmt.Sprintf("%s (%s) 检测不到回程路由节点的IP地址", ipv4Names[i], ipv4s[i])) + if model.EnableLoger { + Logger.Warn(fmt.Sprintf("%s (%s) 检测不到回程路由节点的IP地址", model.Ipv4Names[i], model.Ipv4s[i])) } ch <- Result{i, s} } diff --git a/bk/trace_ipv6.go b/bk/trace_ipv6.go index 3f6f2a2..98f4da1 100644 --- a/bk/trace_ipv6.go +++ b/bk/trace_ipv6.go @@ -5,6 +5,7 @@ import ( "net" "strings" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" "golang.org/x/net/icmp" "golang.org/x/net/ipv6" @@ -27,7 +28,7 @@ func newPacketV6(id uint16, dst net.IP, ttl int) []byte { } func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() } @@ -36,17 +37,17 @@ func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error { for { n, cm, src, err := conn.ReadFrom(buf) if err != nil { - if EnableLoger { + if model.EnableLoger { Logger.Error("读取IPv6响应失败: " + err.Error()) } return err } - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("收到IPv6响应: 来源=%v, 跳数=%d", src, cm.HopLimit)) } fromIP := src.(*net.IPAddr).IP err = t.serveData(fromIP, buf[:n]) - if err != nil && EnableLoger { + if err != nil && model.EnableLoger { Logger.Warn("处理IPv6数据失败: " + err.Error()) } } @@ -54,36 +55,36 @@ func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error { // traceIPv6 IPv6追踪函数 func traceIPv6(ch chan Result, i int, offset int) { - if EnableLoger { + if model.EnableLoger { InitLogger() defer Logger.Sync() - Logger.Info(fmt.Sprintf("开始追踪 %s (%s)", ipv6Names[i], ipv6s[i])) + Logger.Info(fmt.Sprintf("开始追踪 %s (%s)", model.Ipv6Names[i], model.Ipv6s[i])) } - hops, err := Trace(net.ParseIP(ipv6s[i])) + hops, err := Trace(net.ParseIP(model.Ipv6s[i])) if err != nil { - s := fmt.Sprintf("%v %-24s %v", ipv6Names[i], ipv6s[i], err) - if EnableLoger { - Logger.Error(fmt.Sprintf("追踪 %s (%s) 失败: %v", ipv6Names[i], ipv6s[i], err)) + s := fmt.Sprintf("%v %-24s %v", model.Ipv6Names[i], model.Ipv6s[i], err) + if model.EnableLoger { + Logger.Error(fmt.Sprintf("追踪 %s (%s) 失败: %v", model.Ipv6Names[i], model.Ipv6s[i], err)) } ch <- Result{i + offset, s} return } // 记录每个hop的信息 - if EnableLoger { + if model.EnableLoger { for hopNum, hop := range hops { for nodeNum, node := range hop.Nodes { Logger.Info(fmt.Sprintf("追踪 %s (%s) - Hop %d, Node %d: %s (RTT: %v)", - ipv6Names[i], ipv6s[i], hopNum+1, nodeNum+1, node.IP.String(), node.RTT)) + model.Ipv6Names[i], model.Ipv6s[i], hopNum+1, nodeNum+1, node.IP.String(), node.RTT)) } } } var asns []string for _, h := range hops { for _, n := range h.Nodes { - asn := ipAsn(n.IP.String()) + asn := ipv6Asn(n.IP.String()) if asn != "" { asns = append(asns, asn) - if EnableLoger { + if model.EnableLoger { Logger.Info(fmt.Sprintf("IP %s 对应的ASN: %s", n.IP.String(), asn)) } } @@ -93,7 +94,7 @@ func traceIPv6(ch chan Result, i int, offset int) { if asns != nil && len(asns) > 0 { var tempText string asns = removeDuplicates(asns) - tempText += fmt.Sprintf("%v ", ipv6Names[i]) + tempText += fmt.Sprintf("%v ", model.Ipv6Names[i]) hasAS4134 := false hasAS4809 := false for _, asn := range asns { @@ -108,19 +109,19 @@ func traceIPv6(ch chan Result, i int, offset int) { if hasAS4134 && hasAS4809 { // 同时包含 AS4134 和 AS4809 属于 CN2GT asns = append([]string{"AS4809b"}, asns...) - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GT", ipv6Names[i], ipv6s[i])) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GT", model.Ipv6Names[i], model.Ipv6s[i])) } } else if hasAS4809 { // 仅包含 AS4809 属于 CN2GIA asns = append([]string{"AS4809a"}, asns...) - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GIA", ipv6Names[i], ipv6s[i])) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 线路识别为: CN2GIA", model.Ipv6Names[i], model.Ipv6s[i])) } } - tempText += fmt.Sprintf("%-24s ", ipv6s[i]) + tempText += fmt.Sprintf("%-24s ", model.Ipv6s[i]) for _, asn := range asns { - asnDescription := m[asn] + asnDescription := model.M[asn] switch asn { case "": continue @@ -152,21 +153,21 @@ func traceIPv6(ch chan Result, i int, offset int) { } } } - if tempText == (fmt.Sprintf("%v ", ipv6Names[i]) + fmt.Sprintf("%-40s ", ipv6s[i])) { + if tempText == (fmt.Sprintf("%v ", model.Ipv6Names[i]) + fmt.Sprintf("%-40s ", model.Ipv6s[i])) { tempText += fmt.Sprintf("%v", Red("检测不到已知线路的ASN")) - if EnableLoger { - Logger.Warn(fmt.Sprintf("%s (%s) 检测不到已知线路的ASN", ipv6Names[i], ipv6s[i])) + if model.EnableLoger { + Logger.Warn(fmt.Sprintf("%s (%s) 检测不到已知线路的ASN", model.Ipv6Names[i], model.Ipv6s[i])) } } - if EnableLoger { - Logger.Info(fmt.Sprintf("%s (%s) 追踪完成,结果: %s", ipv6Names[i], ipv6s[i], tempText)) + if model.EnableLoger { + Logger.Info(fmt.Sprintf("%s (%s) 追踪完成,结果: %s", model.Ipv6Names[i], model.Ipv6s[i], tempText)) } ch <- Result{i + offset, tempText} } else { - s := fmt.Sprintf("%v %-24s %v", ipv6Names[i], ipv6s[i], Red("检测不到回程路由节点的IP地址")) - if EnableLoger { - Logger.Warn(fmt.Sprintf("%s (%s) 检测不到回程路由节点的IP地址", ipv6Names[i], ipv6s[i])) + s := fmt.Sprintf("%v %-24s %v", model.Ipv6Names[i], model.Ipv6s[i], Red("检测不到回程路由节点的IP地址")) + if model.EnableLoger { + Logger.Warn(fmt.Sprintf("%s (%s) 检测不到回程路由节点的IP地址", model.Ipv6Names[i], model.Ipv6s[i])) } ch <- Result{i + offset, s} } diff --git a/bk/utils.go b/bk/utils.go new file mode 100644 index 0000000..95b3306 --- /dev/null +++ b/bk/utils.go @@ -0,0 +1,66 @@ +package backtrace + +import ( + "fmt" + "io" + "strings" + "time" + + "github.com/imroc/req/v3" + "github.com/oneclickvirt/backtrace/model" + + . "github.com/oneclickvirt/defaultset" +) + +type Result struct { + i int + s string +} + +func removeDuplicates(elements []string) []string { + encountered := map[string]bool{} // 用于存储已经遇到的元素 + result := []string{} // 存储去重后的结果 + for v := range elements { // 遍历切片中的元素 + if encountered[elements[v]] == true { // 如果该元素已经遇到过 + // 存在过就不加入了 + } else { + encountered[elements[v]] = true // 将该元素标记为已经遇到 + result = append(result, elements[v]) // 将该元素加入到结果切片中 + } + } + return result // 返回去重后的结果切片 +} + +func getData(endpoint string) string { + client := req.C() + client.SetTimeout(10 * time.Second) + client.R(). + SetRetryCount(2). + SetRetryBackoffInterval(1*time.Second, 5*time.Second). + SetRetryFixedInterval(2 * time.Second) + if model.EnableLoger { + InitLogger() + defer Logger.Sync() + } + for _, baseUrl := range model.CdnList { + url := baseUrl + endpoint + resp, err := client.R().Get(url) + if err == nil { + defer resp.Body.Close() + b, err := io.ReadAll(resp.Body) + if strings.Contains(string(b), "error") { + continue + } + if err == nil { + if model.EnableLoger { + Logger.Info(fmt.Sprintf("Received data length: %d", len(b))) + } + return string(b) + } + } + if model.EnableLoger { + Logger.Info(fmt.Sprintf("HTTP request failed: %v", err)) + } + } + return "" +} diff --git a/bk/version.go b/bk/version.go deleted file mode 100644 index 903ae5d..0000000 --- a/bk/version.go +++ /dev/null @@ -1,5 +0,0 @@ -package backtrace - -const BackTraceVersion = "v0.0.5" - -var EnableLoger = false diff --git a/cmd/main.go b/cmd/main.go index 63c3e8f..06624fc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,10 +5,11 @@ import ( "flag" "fmt" "net/http" - "runtime" "os" + "runtime" backtrace "github.com/oneclickvirt/backtrace/bk" + "github.com/oneclickvirt/backtrace/model" . "github.com/oneclickvirt/defaultset" ) @@ -30,7 +31,7 @@ func main() { backtraceFlag.BoolVar(&help, "h", false, "Show help information") backtraceFlag.BoolVar(&showVersion, "v", false, "Show version") backtraceFlag.BoolVar(&showIpInfo, "s", true, "Disabe show ip info") - backtraceFlag.BoolVar(&backtrace.EnableLoger, "log", false, "Enable logging") + backtraceFlag.BoolVar(&model.EnableLoger, "log", false, "Enable logging") backtraceFlag.BoolVar(&test, "test", false, "Test Mode") backtraceFlag.Parse(os.Args[1:]) if help { @@ -39,7 +40,7 @@ func main() { return } if showVersion { - fmt.Println(backtrace.BackTraceVersion) + fmt.Println(model.BackTraceVersion) return } if showIpInfo { diff --git a/go.mod b/go.mod index b3d7440..a3c3681 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,30 @@ go 1.22.4 require ( github.com/oneclickvirt/defaultset v0.0.0-20240624051018-30a50859e1b5 - golang.org/x/net v0.26.0 - golang.org/x/sys v0.21.0 + golang.org/x/net v0.33.0 + golang.org/x/sys v0.28.0 ) require ( + github.com/andybalholm/brotli v1.1.1 // indirect + github.com/cloudflare/circl v1.5.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/imroc/req/v3 v3.50.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/onsi/ginkgo/v2 v2.22.0 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.48.2 // indirect + github.com/refraction-networking/utls v1.6.7 // indirect + go.uber.org/mock v0.5.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.27.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/tools v0.28.0 // indirect ) diff --git a/go.sum b/go.sum index fe8681e..599887f 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,64 @@ +github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= +github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/imroc/req/v3 v3.50.0 h1:n3BVnZiTRpvkN5T1IB79LC/THhFU9iXksNRMH4ZNVaY= +github.com/imroc/req/v3 v3.50.0/go.mod h1:tsOk8K7zI6cU4xu/VWCZVtq9Djw9IWm4MslKzme5woU= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/oneclickvirt/defaultset v0.0.0-20240624051018-30a50859e1b5 h1:TUM6XzOB7Z7OxyXi3fwlZY9KfuVbvUBusYiNbSfX208= github.com/oneclickvirt/defaultset v0.0.0-20240624051018-30a50859e1b5/go.mod h1:e9Jt4tf2sbemCtc84/XgKcHy9EZ2jkc5x2sW1NiJS+E= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE= +github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= +github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..85997f3 --- /dev/null +++ b/model/model.go @@ -0,0 +1,65 @@ +package model + +const BackTraceVersion = "v0.0.5" + +var EnableLoger = false + +var ( + IcmpTargets = "https://raw.githubusercontent.com/spiritLHLS/icmp_targets/refs/heads/main/nodes.json" + CdnList = []string{ + "http://cdn1.spiritlhl.net/", + "http://cdn2.spiritlhl.net/", + "http://cdn3.spiritlhl.net/", + "http://cdn4.spiritlhl.net/", + } + Ipv4s = []string{ + "219.141.140.10", // 北京电信v4 + "202.106.195.68", // 北京联通v4 + "221.179.155.161", // 北京移动v4 + "202.96.209.133", // 上海电信v4 + "210.22.97.1", // 上海联通v4 + "211.136.112.200", // 上海移动v4 + "58.60.188.222", // 广州电信v4 + "210.21.196.6", // 广州联通v4 + "120.196.165.24", // 广州移动v4 + "61.139.2.69", // 成都电信v4 + "119.6.6.6", // 成都联通v4 + "211.137.96.205", // 成都移动v4 + } + + Ipv4Names = []string{ + "北京电信v4", "北京联通v4", "北京移动v4", + "上海电信v4", "上海联通v4", "上海移动v4", + "广州电信v4", "广州联通v4", "广州移动v4", + "成都电信v4", "成都联通v4", "成都移动v4", + } + Ipv6s = []string{ + "2400:89c0:1053:3::69", // 北京电信 IPv6 + "2400:89c0:1013:3::54", // 北京联通 IPv6 + "2409:8c00:8421:1303::55", // 北京移动 IPv6 + "240e:e1:aa00:4000::24", // 上海电信 IPV6 + "2408:80f1:21:5003::a", // 上海联通 IPv6 + "2409:8c1e:75b0:3003::26", // 上海移动 IPv6 + "240e:97c:2f:3000::44", // 广州电信 IPv6 + "2408:8756:f50:1001::c", // 广州联通 IPv6 + "2409:8c54:871:1001::12", // 广州移动 IPv6 + } + Ipv6Names = []string{ + "北京电信v6", "北京联通v6", "北京移动v6", + "上海电信v6", "上海联通v6", "上海移动v6", + "广州电信v6", "广州联通v6", "广州移动v6", + } + M = map[string]string{ + // [] 前的字符串个数,中文占2个字符串 + "AS23764": "电信CTGNET [精品线路]", + "AS4809a": "电信CN2GIA [精品线路]", + "AS4809b": "电信CN2GT [优质线路]", + "AS4809": "电信CN2 [优质线路]", + "AS4134": "电信163 [普通线路]", + "AS9929": "联通9929 [优质线路]", + "AS4837": "联通4837 [普通线路]", + "AS58807": "移动CMIN2 [精品线路]", + "AS9808": "移动CMI [普通线路]", + "AS58453": "移动CMI [普通线路]", + } +)