mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
Compare commits
4 Commits
v0.1.2-bet
...
v0.1.4-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
870d1f3b5a | ||
|
|
ebd435db53 | ||
|
|
53b2249ce5 | ||
|
|
7215a1e2b7 |
@@ -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
|
||||
|
||||
39
README.md
39
README.md
@@ -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
|
||||
```
|
||||
|
||||
## 项目截图
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
<!--
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
|
||||
|
||||
@@ -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("』」")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user