mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-04-22 04:02:07 +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 {
|
||||||
|
@ -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.
|
// 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)
|
||||||
}
|
|
||||||
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 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return req, nil
|
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