mirror of
				https://github.com/oneclickvirt/backtrace.git
				synced 2025-11-04 15:52:37 +08:00 
			
		
		
		
	feat: 添加IPV6初始化
This commit is contained in:
		
							parent
							
								
									c9c62e86f3
								
							
						
					
					
						commit
						3b19d43eef
					
				@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -126,6 +126,17 @@ func (t *Tracer) init() {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // 初始化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,20 +221,31 @@ 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)
 | 
			
		||||
    }
 | 
			
		||||
    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) {
 | 
			
		||||
	t.mu.Lock()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								bk/trace_ipv6.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								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}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user