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) {
 | 
					func BackTrace(test bool) {
 | 
				
			||||||
	if !test {
 | 
						if test {
 | 
				
			||||||
		// 获取IP地址数量
 | 
							ipv4Count := len(ipv4s)
 | 
				
			||||||
		ipCount := len(ipv4s)
 | 
							ipv6Count := len(ipv6s)
 | 
				
			||||||
 | 
							totalCount := ipv4Count + ipv6Count
 | 
				
			||||||
		var (
 | 
							var (
 | 
				
			||||||
			s = make([]string, ipCount) // 动态分配切片大小
 | 
								s = make([]string, totalCount)
 | 
				
			||||||
			c = make(chan Result)
 | 
								c = make(chan Result)
 | 
				
			||||||
			t = time.After(time.Second * 10)
 | 
								t = time.After(time.Second * 10)
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
		for i := range ipv4s {
 | 
							for i := range ipv4s {
 | 
				
			||||||
			go trace(c, i)
 | 
								go trace(c, i)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	loop:
 | 
							for i := range ipv6s {
 | 
				
			||||||
 | 
								go traceIPv6(c, i, ipv4Count)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						loopIPv4v6:
 | 
				
			||||||
		for range s {
 | 
							for range s {
 | 
				
			||||||
			select {
 | 
								select {
 | 
				
			||||||
			case o := <-c:
 | 
								case o := <-c:
 | 
				
			||||||
				s[o.i] = o.s
 | 
									s[o.i] = o.s
 | 
				
			||||||
			case <-t:
 | 
								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 {
 | 
							for _, r := range s {
 | 
				
			||||||
 | 
				
			|||||||
@ -116,16 +116,27 @@ func (t *Tracer) NewSession(ip net.IP) (*Session, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *Tracer) init() {
 | 
					func (t *Tracer) init() {
 | 
				
			||||||
	// 初始化IPv4连接
 | 
					    // 初始化IPv4连接
 | 
				
			||||||
	for _, network := range t.Networks {
 | 
					    for _, network := range t.Networks {
 | 
				
			||||||
		if strings.HasPrefix(network, "ip4") {
 | 
					        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 {
 | 
				
			||||||
				go t.serve(t.conn)
 | 
					                go t.serve(t.conn)
 | 
				
			||||||
				break
 | 
					                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.
 | 
					// 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) {
 | 
					func (t *Tracer) sendRequest(dst net.IP, ttl int) (*packet, error) {
 | 
				
			||||||
    id := uint16(atomic.AddUint32(&t.seq, 1))
 | 
					    id := uint16(atomic.AddUint32(&t.seq, 1))
 | 
				
			||||||
    var b []byte
 | 
					    var b []byte
 | 
				
			||||||
 | 
					    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 {
 | 
				
			||||||
 | 
					            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 {
 | 
					    } else {
 | 
				
			||||||
        // IPv4
 | 
					        // IPv4
 | 
				
			||||||
        b = newPacketV4(id, dst, ttl)
 | 
					        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) {
 | 
					func (t *Tracer) addSession(s *Session) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								bk/trace_ipv6.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								bk/trace_ipv6.go
									
									
									
									
									
								
							@ -2,8 +2,11 @@ package backtrace
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						. "github.com/oneclickvirt/defaultset"
 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
						"golang.org/x/net/icmp"
 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
						"golang.org/x/net/ipv6"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -34,3 +37,105 @@ func newPacketV6(id uint16, dst net.IP, ttl int) []byte {
 | 
				
			|||||||
	// 合并头部和ICMP数据
 | 
						// 合并头部和ICMP数据
 | 
				
			||||||
	return append(ipHeaderBytes, icmpData...)
 | 
						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