Compare commits

...

4 Commits

Author SHA1 Message Date
zhshch2002
870d1f3b5a update: get version from git 2022-05-25 12:56:47 +08:00
sjlleo
ebd435db53 refactor: report 支持多线程和rDNS反查 2022-05-25 10:48:47 +08:00
sjlleo
53b2249ce5 fix: 尝试性修复部分 CentOS 6、Debian8 下 wget 安装失败 2022-05-25 08:13:57 +08:00
sjlleo
7215a1e2b7 update: 更新 NextTrace 最新的 CLI 参数 2022-05-24 21:33:18 +08:00
5 changed files with 110 additions and 55 deletions

View File

@@ -21,15 +21,15 @@ for pl in ${PLATFORMS}; do
echo "build => ${TARGET}"
if [ "${DEBUG_MODE}" == "debug" ]; then
go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${COMMIT_SHA1}'\
-ldflags "-X 'github.com/xgadget-lab/nexttrace/printer.version=${BUILD_VERSION}' \
-X 'github.com/xgadget-lab/nexttrace/printer.buildDate=${BUILD_DATE}' \
-X 'github.com/xgadget-lab/nexttrace/printer.commitID=${COMMIT_SHA1}'\
-w -s"
else
go build -trimpath -o ${TARGET} \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${COMMIT_SHA1}'\
-ldflags "-X 'github.com/xgadget-lab/nexttrace/printer.version=${BUILD_VERSION}' \
-X 'github.com/xgadget-lab/nexttrace/printer.buildDate=${BUILD_DATE}' \
-X 'github.com/xgadget-lab/nexttrace/printer.commitID=${COMMIT_SHA1}'\
-w -s"
fi
done

View File

@@ -24,12 +24,6 @@ bash -c "$(curl -Ls https://raw.githubusercontent.com/xgadget-lab/nexttrace/main
# IPv4 ICMP Trace
nexttrace 1.0.0.1
# 获得 route-path
nexttrace -report 1.0.0.1
# 打开IP反向解析 rdns
nexttrace -rdns 1.0.0.1
# 表格打印一次性输出全部跳数需等待20-40秒
nexttrace -table 1.0.0.1
@@ -51,6 +45,19 @@ nexttrace -U 1.0.0.1
nexttrace -U -p 53 1.0.0.1
```
`NextTrace`也同样支持一些进阶功能如IP反向解析、并发数控制、模式切换等
```bash
# 无并发,每次只发送一个探测包
nexttrace -r 1 www.hkix.net
# 打开IP反向解析功能在IPv6的骨干网定位辅助有较大帮助
nexttrace -rdns www.bbix.net
# 联合使用
nexttrace -r 1 -q 1 -report www.time.com.my
```
### IP数据库
目前使用的IP数据库默认为我们自己搭建的API服务如果后期遇到滥用我们可能会选择关闭。
@@ -65,10 +72,9 @@ NextTrace所有的的IP地理位置`API DEMO`可以参考[这里](https://github
Usage of nexttrace:
-T Use TCP SYN for tracerouting (default port is 80)
-U Use UDP Package for tracerouting (default port is 53 in UDP)
-V Check Version
-d string
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight] (default "LeoMoeAPI")
-displayMode string
Choose The Display Mode [table, classic] (default "table")
-m int
Set the max number of hops (max TTL to be reached). (default 30)
-p int
@@ -79,15 +85,22 @@ Usage of nexttrace:
Set ParallelRequests number. It should be 1 when there is a multi-routing. (default 18)
-rdns
Set whether rDNS will be display
-realtime
Output trace results in runtime
-report
Route Path
-table
Output trace results as table
```
## 项目截图
![](asset/screenshot_special.png)
![](asset/screenshot.png)
<!--
Leo注描述可能不合适建议再加以斟酌已经修改
## History
- v0.0.6.alpha - Now
@@ -96,19 +109,15 @@ Usage of nexttrace:
- 最初版本 - v0.0.5.alpha
- https://github.com/OwO-Network/traceroute
- 感谢 Leo (leo.moe) & Vincent (vincent.moe) 发起了这个项目,并完成了最初的工作。
-->
## Thanks
[Sam Sam](https://github.com/samleong123) (samsam123@samsam123.name.my)
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
[waiting4new](https://github.com/waiting4new)
[Sam Sam](https://github.com/samleong123) (samsam123@samsam123.name.my)
FFEE_CO
nsnnns
[waiting4new](https://github.com/waiting4new)、[FFEE_CO](https://github.com/fkx4-p)、[nsnnns](https://github.com/tsosunchia)
## IP Database Copyright

View File

@@ -52,11 +52,12 @@ installWgetPackage() {
# macOS should install wget originally. Nothing to do
echo "wget 正在安装中..."
# try apt
apt-get -h &>/dev/null
# 是时候直接使用 APT 来管理包了
apt -h &>/dev/null
if [ $? -eq 0 ]; then
# 先更新一下数据源有些机器数据源比较老可能会404
apt-get update -y &>/dev/null
apt-get install wget -y &>/dev/null
apt update -y &>/dev/null
apt install wget -y &>/dev/null
fi
# try yum
@@ -79,8 +80,9 @@ installWgetPackage() {
pacman -Sy &>/dev/null
pacman -S wget &>/dev/null
fi
wget -h &>/dev/null
# 有的发行版自带的wget只有 --help 参数
wget --help &>/dev/null
if [ $? -ne 0 ]; then
echo "wget 安装失败"
exit 1

View File

@@ -5,8 +5,12 @@ import (
"net"
)
var version = "v0.0.0.alpha"
var buildDate = ""
var commitID = ""
func Version() {
fmt.Print("NextTrace v0.1.2-Beta ") // TODO get version from git
fmt.Println("NextTrace ", version, buildDate, commitID)
fmt.Println("XGadget-lab Leo (leo.moe) & Vincent (vincent.moe) & zhshch (xzhsh.ch)")
}

View File

@@ -1,10 +1,10 @@
package reporter
import (
"errors"
"fmt"
"net"
"strings"
"sync"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
@@ -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 {
@@ -40,30 +43,42 @@ func experimentTag() {
fmt.Println("Route-Path 功能实验室")
}
func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData) (routeReportNode, error) {
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
}
}
}()
func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData, ttl uint16) {
var success bool = true
defer r.wg.Done()
rpn := routeReportNode{}
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}
@@ -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] {
@@ -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 {
@@ -130,6 +168,8 @@ func (r *reporter) Print() {
}
}
}
// 标记为最新的一个有效跃点
beforeActiveTTL = i
}
fmt.Println("』」")
}