diff --git a/bk/backtrace.go b/bk/backtrace.go index c310900..8069a12 100644 --- a/bk/backtrace.go +++ b/bk/backtrace.go @@ -6,24 +6,57 @@ import ( ) func BackTrace(test bool) { - if !test { - // 获取IP地址数量 - ipCount := len(ipv4s) + if test { + ipv4Count := len(ipv4s) + ipv6Count := len(ipv6s) + totalCount := ipv4Count + ipv6Count var ( - s = make([]string, ipCount) // 动态分配切片大小 + s = make([]string, totalCount) c = make(chan Result) t = time.After(time.Second * 10) ) for i := range ipv4s { go trace(c, i) } - loop: + for i := range ipv6s { + go traceIPv6(c, i, ipv4Count) + } + loopIPv4v6: for range s { select { case o := <-c: s[o.i] = o.s case <-t: - break loop + break loopIPv4v6 + } + } + for i := 0; i < ipv4Count; i++ { + if s[i] != "" { + fmt.Println(s[i]) + } + } + for i := ipv4Count; i < totalCount; i++ { + if s[i] != "" { + fmt.Println(s[i]) + } + } + } else { + ipCount := len(ipv4s) + var ( + s = make([]string, ipCount) + c = make(chan Result) + t = time.After(time.Second * 10) + ) + for i := range ipv4s { + go trace(c, i) + } + loopIPv4: + for range s { + select { + case o := <-c: + s[o.i] = o.s + case <-t: + break loopIPv4 } } for _, r := range s { diff --git a/bk/trace_common.go b/bk/trace_common.go index 1367c8b..149ff4d 100644 --- a/bk/trace_common.go +++ b/bk/trace_common.go @@ -116,16 +116,27 @@ func (t *Tracer) NewSession(ip net.IP) (*Session, error) { } func (t *Tracer) init() { - // 初始化IPv4连接 - for _, network := range t.Networks { - if strings.HasPrefix(network, "ip4") { - t.conn, t.err = t.listen(network, t.Addr) - if t.err == nil { - go t.serve(t.conn) - break - } - } - } + // 初始化IPv4连接 + for _, network := range t.Networks { + if strings.HasPrefix(network, "ip4") { + t.conn, t.err = t.listen(network, t.Addr) + if t.err == nil { + go t.serve(t.conn) + break + } + } + } + // 初始化IPv6连接 + for _, network := range t.Networks { + if strings.HasPrefix(network, "ip6") { + conn, err := net.ListenIP(network, t.Addr) + if err == nil { + t.ipv6conn = ipv6.NewPacketConn(conn) + go t.serveIPv6(t.ipv6conn) + break + } + } + } } // Close closes listening socket. @@ -210,19 +221,30 @@ func (t *Tracer) serveData(from net.IP, b []byte) error { func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) { id := uint16(atomic.AddUint32(&t.seq, 1)) var b []byte + req := &packet{dst, id, ttl, time.Now()} if dst.To4() == nil { // IPv6 b = newPacketV6(id, dst, ttl) + if t.ipv6conn != nil { + cm := &ipv6.ControlMessage{ + HopLimit: ttl, + } + _, err := t.ipv6conn.WriteTo(b, cm, &net.IPAddr{IP: dst}) + if err != nil { + return nil, err + } + return req, nil + } + return nil, errors.New("IPv6 connection not available") } else { // IPv4 b = newPacketV4(id, dst, ttl) + _, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst}) + if err != nil { + return nil, err + } + return req, nil } - req := &packet{dst, id, ttl, time.Now()} - _, err := t.conn.WriteToIP(b, &net.IPAddr{IP: dst}) - if err != nil { - return nil, err - } - return req, nil } func (t *Tracer) addSession(s *Session) { diff --git a/bk/trace_ipv6.go b/bk/trace_ipv6.go index 3dff9cc..2550b9f 100644 --- a/bk/trace_ipv6.go +++ b/bk/trace_ipv6.go @@ -2,8 +2,11 @@ package backtrace import ( "encoding/binary" + "fmt" "net" + "strings" + . "github.com/oneclickvirt/defaultset" "golang.org/x/net/icmp" "golang.org/x/net/ipv6" ) @@ -34,3 +37,105 @@ func newPacketV6(id uint16, dst net.IP, ttl int) []byte { // 合并头部和ICMP数据 return append(ipHeaderBytes, icmpData...) } + +func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error { + defer conn.Close() + buf := make([]byte, 1500) + for { + n, _, from, err := conn.ReadFrom(buf) + if err != nil { + return err + } + fromIP := from.(*net.IPAddr).IP + err = t.serveData(fromIP, buf[:n]) + if err != nil { + continue + } + } +} + +// IPv6追踪函数 +func traceIPv6(ch chan Result, i int, offset int) { + hops, err := Trace(net.ParseIP(ipv6s[i])) + if err != nil { + s := fmt.Sprintf("%v %-40s %v", ipv6Names[i], ipv6s[i], err) + ch <- Result{i + offset, s} // 注意这里加了offset + return + } + + var asns []string + for _, h := range hops { + for _, n := range h.Nodes { + asn := ipAsn(n.IP.String()) + if asn != "" { + asns = append(asns, asn) + } + } + } + + // 处理路由信息 + if asns != nil && len(asns) > 0 { + var tempText string + asns = removeDuplicates(asns) + tempText += fmt.Sprintf("%v ", ipv6Names[i]) + hasAS4134 := false + hasAS4809 := false + for _, asn := range asns { + if asn == "AS4134" { + hasAS4134 = true + } + if asn == "AS4809" { + hasAS4809 = true + } + } + // 判断是否包含 AS4134 和 AS4809 + if hasAS4134 && hasAS4809 { + // 同时包含 AS4134 和 AS4809 属于 CN2GT + asns = append([]string{"AS4809b"}, asns...) + } else if hasAS4809 { + // 仅包含 AS4809 属于 CN2GIA + asns = append([]string{"AS4809a"}, asns...) + } + tempText += fmt.Sprintf("%-40s ", ipv6s[i]) + for _, asn := range asns { + asnDescription := m[asn] + switch asn { + case "": + continue + case "AS4809": // 被 AS4809a 和 AS4809b 替代了 + continue + case "AS9929": + if !strings.Contains(tempText, asnDescription) { + tempText += DarkGreen(asnDescription) + " " + } + case "AS4809a": + if !strings.Contains(tempText, asnDescription) { + tempText += DarkGreen(asnDescription) + " " + } + case "AS23764": + if !strings.Contains(tempText, asnDescription) { + tempText += DarkGreen(asnDescription) + " " + } + case "AS4809b": + if !strings.Contains(tempText, asnDescription) { + tempText += Green(asnDescription) + " " + } + case "AS58807": + if !strings.Contains(tempText, asnDescription) { + tempText += Green(asnDescription) + " " + } + default: + if !strings.Contains(tempText, asnDescription) { + tempText += White(asnDescription) + " " + } + } + } + if tempText == (fmt.Sprintf("%v ", ipv6Names[i]) + fmt.Sprintf("%-40s ", ipv6s[i])) { + tempText += fmt.Sprintf("%v", Red("检测不到已知线路的ASN")) + } + ch <- Result{i + offset, tempText} + } else { + s := fmt.Sprintf("%v %-40s %v", ipv6Names[i], ipv6s[i], Red("检测不到回程路由节点的IP地址")) + ch <- Result{i + offset, s} + } +}