Skip to content

Commit

Permalink
refactor: report 支持多线程和rDNS反查
Browse files Browse the repository at this point in the history
  • Loading branch information
sjlleo committed May 25, 2022
1 parent 53b2249 commit ebd435d
Showing 1 changed file with 67 additions and 27 deletions.
94 changes: 67 additions & 27 deletions reporter/reporter.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package reporter

import (
"errors"
"fmt"
"net"
"strings"
"sync"

"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
Expand All @@ -24,9 +24,12 @@ func New(rs *trace.Result, ip string) Reporter {
}

type reporter struct {
targetIP string
routeReport map[uint16][]routeReportNode
routeResult *trace.Result
targetTTL uint16
targetIP string
routeReport map[uint16][]routeReportNode
routeReportLock sync.Mutex
routeResult *trace.Result
wg sync.WaitGroup
}

type routeReportNode struct {
Expand All @@ -40,30 +43,42 @@ func experimentTag() {
fmt.Println("Route-Path 功能实验室")
}

func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData) (routeReportNode, error) {
func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData, ttl uint16) {

var success bool = true

defer r.wg.Done()

rpn := routeReportNode{}
go func() {
ptr, err := net.LookupAddr(ip)
if err == nil {
if strings.Contains(strings.ToLower(ptr[0]), "ix") {
rpn.ix = true
} else {
rpn.ix = false
}
}
}()
ptr, err := net.LookupAddr(ip)

if err == nil {
if strings.Contains(strings.ToLower(ptr[0]), "ix") {
rpn.ix = true
} else {
rpn.ix = false
}
}
// TODO: 这种写法不好,后面再重构一下
// 判断反向解析的域名中又或者是IP地理位置数据库中,是否出现了 IX
if strings.Contains(strings.ToLower(ipGeoData.Isp), "exchange") || strings.Contains(strings.ToLower(ipGeoData.Isp), "ix") || strings.Contains(strings.ToLower(ipGeoData.Owner), "exchange") || strings.Contains(strings.ToLower(ipGeoData.Owner), "ix") {
rpn.ix = true
}

// TODO: 正则判断POP并且提取带宽大小等信息

// CN2 需要特殊处理,因为他们很多没有ASN
// 但是目前这种写法是不规范的,属于凭空标记4809的IP
// TODO: 用更好的方式显示 CN2 骨干网的路由 Path
if strings.HasPrefix(ip, "59.43") {
rpn.asn = "4809"
} else {
rpn.asn = ipGeoData.Asnumber
}

// 无论最后一跳是否为存在地理位置信息(AnyCast),都应该给予显示
if (ipGeoData.Country == "" || ipGeoData.Country == "LAN Address" || ipGeoData.Country == "-") && ip != r.targetIP {
return rpn, errors.New("GeoData Search Failed")
success = false
} else {
if ipGeoData.City == "" {
rpn.geo = []string{ipGeoData.Country, ipGeoData.Prov}
Expand All @@ -80,35 +95,55 @@ func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData)
} else {
rpn.isp = ipGeoData.Isp
}
return rpn, nil

// 有效记录
if success {
// 锁住资源,防止同时写panic
r.routeReportLock.Lock()
// 添加到MAP中
r.routeReport[ttl] = append(r.routeReport[ttl], rpn)
// 写入完成,解锁释放资源给其他协程
r.routeReportLock.Unlock()
}
}

func (r *reporter) InitialBaseData() Reporter {
var nodeIndex uint16 = 1
reportNodes := map[uint16][]routeReportNode{}
for i := uint16(0); int(i) < len(r.routeResult.Hops); i++ {

r.routeReport = reportNodes
r.targetTTL = uint16(len(r.routeResult.Hops))

for i := uint16(0); i < r.targetTTL; i++ {
traceHop := r.routeResult.Hops[i][0]
if traceHop.Success {
currentIP := traceHop.Address.String()
rpn, err := r.generateRouteReportNode(currentIP, *traceHop.Geo)
if err == nil {
reportNodes[nodeIndex] = append(reportNodes[nodeIndex], rpn)
nodeIndex += 1
}
r.wg.Add(1)
go r.generateRouteReportNode(currentIP, *traceHop.Geo, i)
}
}
r.routeReport = reportNodes

// 等待所有的子协程运行完毕
r.wg.Wait()
return r
}

func (r *reporter) Print() {
var beforeActiveTTL uint16 = 1
r.InitialBaseData()
for i := uint16(1); int(i) < len(r.routeReport)+1; i++ {

for i := uint16(1); i < r.targetTTL; i++ {
// 计算该TTL内的数据长度,如果为0,则代表没有有效数据
if len(r.routeReport[i]) == 0 {
// 跳过改跃点的数据整理
continue
}
nodeReport := r.routeReport[i][0]

if i == 1 {
fmt.Printf("AS%s %s「%s『%s", nodeReport.asn, nodeReport.isp, nodeReport.geo[0], nodeReport.geo[1])
} else {
nodeReportBefore := r.routeReport[i-1][0]
nodeReportBefore := r.routeReport[beforeActiveTTL][0]
// ASN 相同,同个 ISP 内部的数据传递
if nodeReportBefore.asn == nodeReport.asn {
// Same ASN but Coutry or City Changed
if nodeReportBefore.geo[0] != nodeReport.geo[0] {
Expand All @@ -119,8 +154,11 @@ func (r *reporter) Print() {
}
}
} else {
// ASN 不同,跨 ISP 的数据传递,这里可能会出现 POP、IP Transit、Peer、Exchange
fmt.Printf("』」")
if int(i) != len(r.routeReport)+1 {
// 部分 Shell 客户端可能无法很好的展示这个特殊字符
// TODO: 寻找其他替代字符
fmt.Printf("\n ╭╯\n ╰")
}
if nodeReport.ix {
Expand All @@ -130,6 +168,8 @@ func (r *reporter) Print() {
}
}
}
// 标记为最新的一个有效跃点
beforeActiveTTL = i
}
fmt.Println("』」")
}

0 comments on commit ebd435d

Please sign in to comment.