mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-04-22 04:02:07 +08:00
Compare commits
6 Commits
1a985cfbbe
...
16484ea6ca
Author | SHA1 | Date | |
---|---|---|---|
![]() |
16484ea6ca | ||
![]() |
ba10f8b64c | ||
![]() |
09abb17c08 | ||
![]() |
aa8bc941a6 | ||
![]() |
3b19d43eef | ||
![]() |
c9c62e86f3 |
@ -55,7 +55,7 @@ backtrace
|
|||||||
|
|
||||||
```
|
```
|
||||||
Usage: backtrace [options]
|
Usage: backtrace [options]
|
||||||
-e Enable logging
|
-log Enable logging
|
||||||
-h Show help information
|
-h Show help information
|
||||||
-s Disabe show ip info (default true)
|
-s Disabe show ip info (default true)
|
||||||
-v Show version
|
-v Show version
|
||||||
|
@ -22,10 +22,10 @@ var (
|
|||||||
"61.139.2.69", "119.6.6.6", "211.137.96.205",
|
"61.139.2.69", "119.6.6.6", "211.137.96.205",
|
||||||
}
|
}
|
||||||
ipv4Names = []string{
|
ipv4Names = []string{
|
||||||
"北京电信", "北京联通", "北京移动",
|
"北京电信v4", "北京联通v4", "北京移动v4",
|
||||||
"上海电信", "上海联通", "上海移动",
|
"上海电信v4", "上海联通v4", "上海移动v4",
|
||||||
"广州电信", "广州联通", "广州移动",
|
"广州电信v4", "广州联通v4", "广州移动v4",
|
||||||
"成都电信", "成都联通", "成都移动",
|
"成都电信v4", "成都联通v4", "成都移动v4",
|
||||||
}
|
}
|
||||||
ipv6s = []string{
|
ipv6s = []string{
|
||||||
"2400:89c0:1053:3::69", // 北京电信 IPv6
|
"2400:89c0:1053:3::69", // 北京电信 IPv6
|
||||||
|
@ -5,31 +5,64 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BackTrace() {
|
func BackTrace(test bool) {
|
||||||
// 获取IP地址数量
|
if test {
|
||||||
ipCount := len(ipv4s)
|
ipv4Count := 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)
|
||||||
}
|
}
|
||||||
|
for i := range ipv6s {
|
||||||
loop:
|
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 {
|
||||||
if r != "" {
|
if r != "" {
|
||||||
fmt.Println(r)
|
fmt.Println(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,5 @@ import (
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
func TestBackTrace(t *testing.T) {
|
func TestBackTrace(t *testing.T) {
|
||||||
BackTrace()
|
BackTrace(false)
|
||||||
}
|
}
|
||||||
|
@ -2,30 +2,31 @@ package backtrace
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
_ "embed"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed bk/prefix/as4809.txt
|
//go:embed prefix/as4809.txt
|
||||||
var as4809Data string
|
var as4809Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as4134.txt
|
//go:embed prefix/as4134.txt
|
||||||
var as4134Data string
|
var as4134Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as9929.txt
|
//go:embed prefix/as9929.txt
|
||||||
var as9929Data string
|
var as9929Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as4837.txt
|
//go:embed prefix/as4837.txt
|
||||||
var as4837Data string
|
var as4837Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as58807.txt
|
//go:embed prefix/as58807.txt
|
||||||
var as58807Data string
|
var as58807Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as9808.txt
|
//go:embed prefix/as9808.txt
|
||||||
var as9808Data string
|
var as9808Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as58453.txt
|
//go:embed prefix/as58453.txt
|
||||||
var as58453Data string
|
var as58453Data string
|
||||||
|
|
||||||
//go:embed bk/prefix/as23764.txt
|
//go:embed prefix/as23764.txt
|
||||||
var as23764Data string
|
var as23764Data string
|
||||||
|
|
||||||
// ASN -> Prefix strings
|
// ASN -> Prefix strings
|
||||||
|
@ -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) {
|
||||||
|
103
bk/trace_ipv6.go
103
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,103 @@ 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}
|
||||||
|
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}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,12 +25,13 @@ func main() {
|
|||||||
http.Get("https://hits.spiritlhl.net/backtrace.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
|
http.Get("https://hits.spiritlhl.net/backtrace.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
|
||||||
}()
|
}()
|
||||||
fmt.Println(Green("项目地址:"), Yellow("https://github.com/oneclickvirt/backtrace"))
|
fmt.Println(Green("项目地址:"), Yellow("https://github.com/oneclickvirt/backtrace"))
|
||||||
var showVersion, showIpInfo, help bool
|
var showVersion, showIpInfo, help, test bool
|
||||||
backtraceFlag := flag.NewFlagSet("backtrace", flag.ContinueOnError)
|
backtraceFlag := flag.NewFlagSet("backtrace", flag.ContinueOnError)
|
||||||
backtraceFlag.BoolVar(&help, "h", false, "Show help information")
|
backtraceFlag.BoolVar(&help, "h", false, "Show help information")
|
||||||
backtraceFlag.BoolVar(&showVersion, "v", false, "Show version")
|
backtraceFlag.BoolVar(&showVersion, "v", false, "Show version")
|
||||||
backtraceFlag.BoolVar(&showIpInfo, "s", true, "Disabe show ip info")
|
backtraceFlag.BoolVar(&showIpInfo, "s", true, "Disabe show ip info")
|
||||||
backtraceFlag.BoolVar(&backtrace.EnableLoger, "e", false, "Enable logging")
|
backtraceFlag.BoolVar(&backtrace.EnableLoger, "log", false, "Enable logging")
|
||||||
|
backtraceFlag.BoolVar(&test, "test", false, "Test Mode")
|
||||||
backtraceFlag.Parse(os.Args[1:])
|
backtraceFlag.Parse(os.Args[1:])
|
||||||
if help {
|
if help {
|
||||||
fmt.Printf("Usage: %s [options]\n", os.Args[0])
|
fmt.Printf("Usage: %s [options]\n", os.Args[0])
|
||||||
@ -56,7 +57,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
backtrace.BackTrace()
|
backtrace.BackTrace(test)
|
||||||
fmt.Println(Yellow("准确线路自行查看详细路由,本测试结果仅作参考"))
|
fmt.Println(Yellow("准确线路自行查看详细路由,本测试结果仅作参考"))
|
||||||
fmt.Println(Yellow("同一目标地址多个线路时,可能检测已越过汇聚层,除了第一个线路外,后续信息可能无效"))
|
fmt.Println(Yellow("同一目标地址多个线路时,可能检测已越过汇聚层,除了第一个线路外,后续信息可能无效"))
|
||||||
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
|
||||||
|
Loading…
Reference in New Issue
Block a user