mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
Compare commits
57 Commits
v0.1.4-bet
...
v0.1.4-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
126115c04e | ||
|
|
ea7fd2af0f | ||
|
|
3fc81f4e71 | ||
|
|
0c2b77bd81 | ||
|
|
ac33c086c6 | ||
|
|
fadfdc87d4 | ||
|
|
eb77a2b69b | ||
|
|
02e6c6e1bf | ||
|
|
838af3b7a1 | ||
|
|
7cd16036a6 | ||
|
|
2ef4f61d7b | ||
|
|
688622738f | ||
|
|
83fe583f2a | ||
|
|
4b32594c17 | ||
|
|
927b6d4035 | ||
|
|
aa651f30cc | ||
|
|
ffec9a93cd | ||
|
|
59a744b3b5 | ||
|
|
9656dfe172 | ||
|
|
84c48dae99 | ||
|
|
4eaac372f6 | ||
|
|
c92d8a5172 | ||
|
|
acab410d4c | ||
|
|
858555fd86 | ||
|
|
31e419b199 | ||
|
|
1dddd43e67 | ||
|
|
4148d0d4b1 | ||
|
|
4f7977da8f | ||
|
|
cfc8034cb4 | ||
|
|
dbc0f87847 | ||
|
|
74a320898f | ||
|
|
329b3fdd6b | ||
|
|
3fb88f4cf4 | ||
|
|
1de84cac71 | ||
|
|
83d093f5aa | ||
|
|
8b03ca7a38 | ||
|
|
7a847bf0d5 | ||
|
|
11fe41611c | ||
|
|
71b24fb7a0 | ||
|
|
0b08e4b4a4 | ||
|
|
2608c05da1 | ||
|
|
314bdd0cce | ||
|
|
ea958059c6 | ||
|
|
b59c349264 | ||
|
|
030a487526 | ||
|
|
cac6d33fde | ||
|
|
1725a65827 | ||
|
|
4d886066a3 | ||
|
|
156043730d | ||
|
|
91ad3bc539 | ||
|
|
351da5f5a3 | ||
|
|
f8fc90d7a5 | ||
|
|
9c75635acc | ||
|
|
c9a3916cd0 | ||
|
|
89d56c437e | ||
|
|
6299dcd9a3 | ||
|
|
82f28a13f3 |
67
README.md
67
README.md
@@ -10,7 +10,7 @@
|
||||
|
||||
## How To Use
|
||||
|
||||
### Install
|
||||
### Automated Install
|
||||
|
||||
```bash
|
||||
#下载nt_install.sh
|
||||
@@ -19,6 +19,17 @@ curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh -O
|
||||
sudo bash nt_install.sh
|
||||
```
|
||||
|
||||
### Alternative methods
|
||||
|
||||
如果你的目的只是为了快速测试服务器的到中国内地的线路,没有手动使用 NextTrace 的需求,那么建议你直接使用本仓库的 `quicklytest.sh`
|
||||
|
||||
```bash
|
||||
#下载quicklytest.sh
|
||||
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh -O
|
||||
#执行quicklytest.sh
|
||||
sudo bash quicklytest.sh
|
||||
```
|
||||
|
||||
### Get Started
|
||||
|
||||
`NextTrace`默认使用`icmp`协议发起`TraceRoute`请求,该协议同时支持`IPv4`和`IPv6`
|
||||
@@ -29,6 +40,8 @@ nexttrace 1.0.0.1
|
||||
|
||||
# 表格打印(一次性输出全部跳数,需等待20-40秒)
|
||||
nexttrace -table 1.0.0.1
|
||||
# 实时打印 (-realtime与-table不能同时选择)
|
||||
nexttrace -realtime 1.0.0.1
|
||||
|
||||
# IPv6 ICMP Trace
|
||||
nexttrace 2606:4700:4700::1111
|
||||
@@ -52,27 +65,44 @@ nexttrace -U -p 53 1.0.0.1
|
||||
`NextTrace`也同样支持一些进阶功能,如 IP 反向解析、并发数控制、模式切换等
|
||||
|
||||
```bash
|
||||
# 每一跳发送2个探测包
|
||||
nexttrace -q 2 www.hkix.net
|
||||
|
||||
# 无并发,每次只发送一个探测包
|
||||
nexttrace -r 1 www.hkix.net
|
||||
|
||||
# 打开IP反向解析功能,在IPv6的骨干网定位辅助有较大帮助
|
||||
nexttrace -rdns www.bbix.net
|
||||
|
||||
# 联合使用
|
||||
nexttrace -r 1 -q 1 -report www.time.com.my
|
||||
# 特色功能:打印Route-Path图
|
||||
# Route-Path图示例:
|
||||
# AS6453 塔塔通信「Singapore『Singapore』」
|
||||
# ╭╯
|
||||
# ╰AS9299 Philippine Long Distance Telephone Co.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS36776 Five9 Inc.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS37963 阿里云「ALIDNS.COM『ALIDNS.COM』」
|
||||
nexttrace -report www.time.com.my
|
||||
```
|
||||
|
||||
### For Beginner
|
||||
|
||||
如果你实在不想去了解这些参数如何使用,或目的只是为了快速测试服务器的到中国内地的线路,那么建议你使用本仓库的 `quicklytest.sh`
|
||||
|
||||
使用此脚本前请先按照 [Install](#Install) 中的提示进行安装,才可使用,并按照提示进行操作即可。
|
||||
`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`)
|
||||
|
||||
```bash
|
||||
#下载quicklytest.sh
|
||||
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh -O
|
||||
#执行quicklytest.sh
|
||||
sudo bash quicklytest.sh
|
||||
# 可以自行指定IP数据库[此处为IP.SB],不指定则默认为LeoMoeAPI
|
||||
nexttrace -d IP.SB
|
||||
## 特别的:其中 ipinfo API 需要从ipinfo自行购买服务,如有需要可以clone本项目添加其提供的token自行编译
|
||||
## TOKEN填写路径:ipgeo/tokens.go
|
||||
## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。
|
||||
## IPAPI.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。
|
||||
```
|
||||
|
||||
`NextTrace`支持参数混合使用
|
||||
|
||||
```bash
|
||||
Example:
|
||||
nexttrace -d IPInsight -m 20 -p 443 -q 5 -r 20 -rdns -table 1.1.1.1
|
||||
nexttrace -T -q 2 -r 1 -rdns -realtime -report 2001:4860:4860::8888
|
||||
```
|
||||
|
||||
### IP 数据库
|
||||
@@ -87,11 +117,13 @@ NextTrace 所有的的 IP 地理位置`API DEMO`可以参考[这里](https://git
|
||||
|
||||
```shell
|
||||
Usage of nexttrace:
|
||||
'nexttrace [options] <hostname>' or 'nexttrace <hostname> [option...]'
|
||||
Options:
|
||||
-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")
|
||||
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com] (default "LeoMoeAPI")
|
||||
-m int
|
||||
Set the max number of hops (max TTL to be reached). (default 30)
|
||||
-p int
|
||||
@@ -104,10 +136,11 @@ Usage of nexttrace:
|
||||
Set whether rDNS will be display
|
||||
-realtime
|
||||
Output trace results in runtime
|
||||
-report
|
||||
Route Path
|
||||
-table
|
||||
Output trace results as table
|
||||
-report
|
||||
Route Path
|
||||
|
||||
```
|
||||
|
||||
## 项目截图
|
||||
@@ -120,6 +153,10 @@ Usage of nexttrace:
|
||||
|
||||
或许可以在这里找到答案 -> [前往 Github Wiki](https://github.com/xgadget-lab/nexttrace/wiki/FAQ---%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%A7%A3%E7%AD%94)
|
||||
|
||||
如果在搜索引擎,WiKi 处还是没有解决,可以试试在本项目讨论区交流 -> [前往 Github Discussions](https://github.com/xgadget-lab/nexttrace/discussions)
|
||||
|
||||
最终如果你确认遇到的是 BUG、上述方法都不能解决的话,请按照提供好的模版在 Issues 区提出问题 -> [前往 Github Issues](https://github.com/xgadget-lab/nexttrace/issues)
|
||||
|
||||
## Thanks
|
||||
|
||||
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
|
||||
|
||||
1
go.mod
1
go.mod
@@ -11,7 +11,6 @@ require (
|
||||
require (
|
||||
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/panjf2000/ants/v2 v2.5.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1,4 +1,3 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -13,8 +12,6 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
|
||||
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
|
||||
@@ -52,7 +49,6 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
43
ipgeo/ipapicom.go
Normal file
43
ipgeo/ipapicom.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package ipgeo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func IPApiCom(ip string) (*IPGeoData, error) {
|
||||
url := "http://ip-api.com/json/" + ip + "?fields=status,message,country,regionName,city,isp,as"
|
||||
client := &http.Client{
|
||||
// 2 秒超时
|
||||
Timeout: 2 * time.Second,
|
||||
}
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0")
|
||||
content, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Println("ip-api.com 请求超时(2s),请切换其他API使用")
|
||||
return nil, err
|
||||
}
|
||||
body, _ := ioutil.ReadAll(content.Body)
|
||||
res := gjson.ParseBytes(body)
|
||||
|
||||
if res.Get("status").String() != "success" {
|
||||
return &IPGeoData{}, errors.New("超过API阈值")
|
||||
}
|
||||
|
||||
re := regexp.MustCompile("[0-9]+")
|
||||
|
||||
return &IPGeoData{
|
||||
Asnumber: re.FindString(res.Get("as").String()),
|
||||
Country: res.Get("country").String(),
|
||||
City: res.Get("city").String(),
|
||||
Prov: res.Get("regionName").String(),
|
||||
Isp: res.Get("isp").String(),
|
||||
}, nil
|
||||
}
|
||||
@@ -24,6 +24,8 @@ func GetSource(s string) Source {
|
||||
return IPSB
|
||||
case "IPINSIGHT":
|
||||
return IPInSight
|
||||
case "IPAPI.COM":
|
||||
return IPApiCom
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -41,3 +41,12 @@ func TestIPInSight(t *testing.T) {
|
||||
// 这个库有时候不提供城市信息,返回值为""
|
||||
//assert.NotEmpty(t, res.City)
|
||||
}
|
||||
|
||||
func TestIPApiCom(t *testing.T) {
|
||||
res, err := IPApiCom("1.1.1.1")
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.Country)
|
||||
assert.NotEmpty(t, res.City)
|
||||
assert.NotEmpty(t, res.Prov)
|
||||
}
|
||||
|
||||
73
main.go
73
main.go
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
@@ -14,31 +15,46 @@ import (
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
)
|
||||
|
||||
var tcpSYNFlag = flag.Bool("T", false, "Use TCP SYN for tracerouting (default port is 80)")
|
||||
var udpPackageFlag = flag.Bool("U", false, "Use UDP Package for tracerouting (default port is 53 in UDP)")
|
||||
var fSet = flag.NewFlagSet("", flag.ExitOnError)
|
||||
var tcpSYNFlag = fSet.Bool("T", false, "Use TCP SYN for tracerouting (default port is 80)")
|
||||
var udpPackageFlag = fSet.Bool("U", false, "Use UDP Package for tracerouting (default port is 53 in UDP)")
|
||||
var port = flag.Int("p", 80, "Set SYN Traceroute Port")
|
||||
var numMeasurements = flag.Int("q", 3, "Set the number of probes per each hop.")
|
||||
var parallelRequests = flag.Int("r", 18, "Set ParallelRequests number. It should be 1 when there is a multi-routing.")
|
||||
var maxHops = flag.Int("m", 30, "Set the max number of hops (max TTL to be reached).")
|
||||
var dataOrigin = flag.String("d", "LeoMoeAPI", "Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight]")
|
||||
var rdnsenable = flag.Bool("rdns", false, "Set whether rDNS will be display")
|
||||
var routePath = flag.Bool("report", false, "Route Path")
|
||||
var realtimePrint = flag.Bool("realtime", false, "Output trace results in runtime")
|
||||
var tablePrint = flag.Bool("table", false, "Output trace results as table")
|
||||
var ver = flag.Bool("V", false, "Check Version")
|
||||
var numMeasurements = fSet.Int("q", 3, "Set the number of probes per each hop.")
|
||||
var parallelRequests = fSet.Int("r", 18, "Set ParallelRequests number. It should be 1 when there is a multi-routing.")
|
||||
var maxHops = fSet.Int("m", 30, "Set the max number of hops (max TTL to be reached).")
|
||||
var dataOrigin = fSet.String("d", "LeoMoeAPI", "Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com]")
|
||||
var rdnsenable = fSet.Bool("rdns", false, "Set whether rDNS will be display")
|
||||
var routePath = fSet.Bool("report", false, "Route Path")
|
||||
var tablePrint = fSet.Bool("table", false, "Output trace results as table")
|
||||
var ver = fSet.Bool("V", false, "Check Version")
|
||||
|
||||
func printArgHelp() {
|
||||
fmt.Println("\nArgs Error\nUsage : 'nexttrace [option...] HOSTNAME' or 'nexttrace HOSTNAME [option...]'\nOPTIONS: [-VTU] [-d DATAORIGIN.STR ] [ -m TTL ] [ -p PORT ] [ -q PROBES.COUNT ] [ -r PARALLELREQUESTS.COUNT ] [-rdns] [ -realtime | -table ] -report")
|
||||
fSet.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func flagApply() string {
|
||||
flag.Parse()
|
||||
printer.Version()
|
||||
|
||||
target := ""
|
||||
if len(os.Args) < 2 {
|
||||
printArgHelp()
|
||||
}
|
||||
if !strings.HasPrefix(os.Args[1], "-") {
|
||||
target = os.Args[1]
|
||||
fSet.Parse(os.Args[2:])
|
||||
} else {
|
||||
fSet.Parse(os.Args[1:])
|
||||
target = fSet.Arg(0)
|
||||
}
|
||||
if *ver {
|
||||
os.Exit(0)
|
||||
}
|
||||
ipArg := flag.Args()
|
||||
if flag.NArg() != 1 {
|
||||
fmt.Println("Args Error\nUsage : ./nexttrace [-T] [-rdns] [-displayMode <displayMode>] [-d <dataOrigin> ] [ -m <hops> ] [ -p <port> ] [ -q <probes> ] [ -r <parallelrequests> ] <hostname>")
|
||||
os.Exit(2)
|
||||
if target == "" {
|
||||
printArgHelp()
|
||||
}
|
||||
return ipArg[0]
|
||||
return target
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -88,25 +104,14 @@ func main() {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
if !(*tcpSYNFlag || *udpPackageFlag) && *tablePrint {
|
||||
printer.TracerouteTablePrinter(res)
|
||||
} else if *tcpSYNFlag || *udpPackageFlag {
|
||||
printer.TraceroutePrinter(res)
|
||||
}
|
||||
|
||||
if *routePath {
|
||||
// 如果为TCP SYN,也打印路由跟踪结果
|
||||
if *tcpSYNFlag {
|
||||
printer.TracerouteTablePrinter(res)
|
||||
}
|
||||
r := reporter.New(res, ip.String())
|
||||
r.Print()
|
||||
return
|
||||
}
|
||||
|
||||
if m == trace.ICMPTrace && *tablePrint {
|
||||
printer.TracerouteTablePrinter(res)
|
||||
}
|
||||
|
||||
if m == trace.TCPTrace || m == trace.UDPTrace {
|
||||
if *realtimePrint {
|
||||
printer.TraceroutePrinter(res)
|
||||
} else {
|
||||
printer.TracerouteTablePrinter(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
164
nt_install.sh
164
nt_install.sh
@@ -4,67 +4,32 @@ auto=False
|
||||
#是否忽略一切警告,按默认执行
|
||||
if [[ $1 == "--auto" ]]; then
|
||||
auto=True
|
||||
echo "自动运行中"
|
||||
fi
|
||||
|
||||
usrPath="/usr/local/bin"
|
||||
|
||||
function red(){
|
||||
echo -e "\e[1;31m$1\e[0m"
|
||||
function red() {
|
||||
echo -e "\033[31m"${1}"\033[0m"
|
||||
}
|
||||
|
||||
checkRootPermit() {
|
||||
[[ $EUID -ne 0 ]] && red "请使用sudo/root权限运行本脚本" && exit 1
|
||||
}
|
||||
ask_if()
|
||||
{
|
||||
local choice=""
|
||||
while [ "$choice" != "y" ] && [ "$choice" != "n" ]
|
||||
do
|
||||
echo -e "${Info} $1"
|
||||
read choice
|
||||
done
|
||||
[ $choice == y ] && return 0
|
||||
return 1
|
||||
}
|
||||
#检查脚本更新
|
||||
check_script_update()
|
||||
{
|
||||
[ "$(md5sum "${BASH_SOURCE[0]}" | awk '{print $1}')" == "$(md5sum <(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh") | awk '{print $1}')" ] && return 1 || return 0
|
||||
}
|
||||
#更新脚本
|
||||
update_script()
|
||||
{
|
||||
if curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh" || curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh"; then
|
||||
echo -e "${Info} 脚本更新完成,正在重启脚本..."
|
||||
exec bash ${BASH_SOURCE[0]}
|
||||
else
|
||||
echo -e "${Info} 更新脚本失败!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
ask_update_script()
|
||||
{
|
||||
if check_script_update; then
|
||||
echo -e "${Info} 脚本可升级"
|
||||
[[ $auto == True ]] && update_script
|
||||
ask_if "是否升级脚本?(y/n)" && update_script
|
||||
else
|
||||
echo -e "${Info} 脚本已经是最新版本"
|
||||
fi
|
||||
}
|
||||
|
||||
checkSystemArch() {
|
||||
arch=$(uname -m)
|
||||
case $arch in
|
||||
'x86_64')
|
||||
'x86_64')
|
||||
archParam='amd64'
|
||||
;;
|
||||
'mips')
|
||||
'mips')
|
||||
archParam='mips'
|
||||
;;
|
||||
'arm64'|'aarch64')
|
||||
'arm64' | 'aarch64')
|
||||
archParam="arm64"
|
||||
;;
|
||||
*)
|
||||
*)
|
||||
red "未知的系统架构,请联系开发者."
|
||||
exit 1
|
||||
;;
|
||||
@@ -88,6 +53,43 @@ checkSystemDistribution() {
|
||||
esac
|
||||
}
|
||||
|
||||
ask_if() {
|
||||
local choice=""
|
||||
red $1
|
||||
read choice
|
||||
[[ $choice == y ]] && return 0 || return 1
|
||||
}
|
||||
|
||||
#检查脚本更新
|
||||
check_script_update() {
|
||||
if [[ ${osDistribution} == "darwin" ]]; then
|
||||
[ "$(cat "${BASH_SOURCE[0]}" | md5)" == "$(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh" | md5)" ] && return 1 || return 0
|
||||
else
|
||||
[ "$(md5sum "${BASH_SOURCE[0]}" | awk '{print $1}')" == "$(md5sum <(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh") | awk '{print $1}')" ] && return 1 || return 0
|
||||
fi
|
||||
}
|
||||
|
||||
#更新脚本
|
||||
update_script() {
|
||||
if curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh" || curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh"; then
|
||||
red "脚本更新完成,正在重启脚本..."
|
||||
exec bash ${BASH_SOURCE[0]} --auto
|
||||
else
|
||||
red "更新脚本失败!"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ask_update_script() {
|
||||
if check_script_update; then
|
||||
red "脚本可升级"
|
||||
[[ $auto == True ]] && update_script
|
||||
ask_if "是否升级脚本?(n/y):[n]" && update_script
|
||||
else
|
||||
red "脚本已经是最新版本"
|
||||
fi
|
||||
}
|
||||
|
||||
getLocation() {
|
||||
red "正在获取地理位置信息..."
|
||||
countryCode=$(curl -s "http://ip-api.com/line/?fields=countryCode")
|
||||
@@ -95,43 +97,44 @@ getLocation() {
|
||||
|
||||
checkPackageManger() {
|
||||
if [[ "$(which brew)" ]]; then #务必将brew置于第一位,macOS的apt是假的
|
||||
brew update
|
||||
PACKAGE_MANAGEMENT_INSTALL='brew install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='brew uninstall'
|
||||
# brew update
|
||||
PACKAGE_MANAGEMENT_INSTALL='brew install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='brew uninstall'
|
||||
elif [[ "$(which apt)" ]]; then
|
||||
apt-get update
|
||||
PACKAGE_MANAGEMENT_INSTALL='apt-get -y --no-install-recommends install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='apt-get purge'
|
||||
apt-get update
|
||||
PACKAGE_MANAGEMENT_INSTALL='apt-get -y --no-install-recommends install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='apt-get purge'
|
||||
elif [[ "$(which dnf)" ]]; then
|
||||
dnf check-update
|
||||
PACKAGE_MANAGEMENT_INSTALL='dnf -y install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='dnf remove'
|
||||
dnf check-update
|
||||
PACKAGE_MANAGEMENT_INSTALL='dnf -y install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='dnf remove'
|
||||
elif [[ "$(which yum)" ]]; then
|
||||
PACKAGE_MANAGEMENT_INSTALL='yum -y install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='yum remove'
|
||||
PACKAGE_MANAGEMENT_INSTALL='yum -y install'
|
||||
PACKAGE_MANAGEMENT_REMOVE='yum remove'
|
||||
elif [[ "$(which zypper)" ]]; then
|
||||
zypper refresh
|
||||
PACKAGE_MANAGEMENT_INSTALL='zypper install -y --no-recommends'
|
||||
PACKAGE_MANAGEMENT_REMOVE='zypper remove'
|
||||
zypper refresh
|
||||
PACKAGE_MANAGEMENT_INSTALL='zypper install -y --no-recommends'
|
||||
PACKAGE_MANAGEMENT_REMOVE='zypper remove'
|
||||
elif [[ "$(which pacman)" ]]; then
|
||||
PACKAGE_MANAGEMENT_INSTALL='pacman -Syu --noconfirm'
|
||||
PACKAGE_MANAGEMENT_REMOVE='pacman -Rsn'
|
||||
PACKAGE_MANAGEMENT_INSTALL='pacman -Syu --noconfirm'
|
||||
PACKAGE_MANAGEMENT_REMOVE='pacman -Rsn'
|
||||
else
|
||||
red "error: The script does not support the package manager in this operating system."
|
||||
exit 1
|
||||
red "error: The script does not support the package manager in this operating system."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_software() {
|
||||
package_name="$1"
|
||||
which "$package_name" > /dev/null 2>&1 && return
|
||||
red "${package_name} 正在安装中...(此步骤时间可能较长,请耐心等待)"
|
||||
if ${PACKAGE_MANAGEMENT_INSTALL} "$package_name"; then
|
||||
red "info: $package_name is installed."
|
||||
else
|
||||
red "error: Installation of $package_name failed, please check your network."
|
||||
exit 1
|
||||
fi
|
||||
package_name="$1"
|
||||
which "$package_name" >/dev/null 2>&1 && return
|
||||
[[ ${osDistribution} == "darwin" ]] && echo -e "由于macOS brew的权限限制,请以非root权限执行下面一行提示的命令后再次运行本脚本(注意不要在该命令加sudo!):\nbrew update && ${PACKAGE_MANAGEMENT_INSTALL} $package_name " && exit 0
|
||||
red "${package_name} 正在安装中...(此步骤时间可能较长,请耐心等待)"
|
||||
if ${PACKAGE_MANAGEMENT_INSTALL} "$package_name"; then
|
||||
red "info: $package_name is installed."
|
||||
else
|
||||
red "error: Installation of $package_name failed, please check your network."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
checkVersion() {
|
||||
@@ -145,7 +148,7 @@ checkVersion() {
|
||||
red "获取版本失败,请检查网络连接"
|
||||
exit 1
|
||||
fi
|
||||
currentVersion=$(nexttrace -V | head -n 1 | awk '{print $2}') &> /dev/null
|
||||
currentVersion=$(nexttrace -V | head -n 1 | awk '{print $2}') &>/dev/null
|
||||
if [[ $currentVersion == $version ]]; then
|
||||
red "当前版本已是最新版本"
|
||||
exit 0
|
||||
@@ -155,7 +158,7 @@ checkVersion() {
|
||||
if [[ $auto == True ]]; then
|
||||
return 0
|
||||
fi
|
||||
read -r -p "是否更新软件? (y/n)" input
|
||||
read -r -p "是否更新软件? (n/y):[n]" input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
return 0
|
||||
@@ -173,14 +176,14 @@ checkVersion() {
|
||||
downloadBinrayFile() {
|
||||
red "正在获取最新版的 NextTrace 发行版文件信息..."
|
||||
# 简单说明一下,Github提供了一个API,可以获取最新发行版本的二进制文件下载地址(对应的是browser_download_url),根据刚刚测得的osDistribution、archParam,获取对应的下载地址
|
||||
# red nexttrace_${osDistribution}_${archParam}
|
||||
latestURL=$(curl -s https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | jq ".assets[] | select(.name == \"nexttrace_${osDistribution}_${archParam}\") | .browser_download_url")
|
||||
latestURL=${latestURL:1:-1}
|
||||
# red nexttrace_${osDistribution}_${archParam}
|
||||
latestURL=$(curl -s https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | jq ".assets[] | select(.name == \"nexttrace_${osDistribution}_${archParam}\") | .browser_download_url")
|
||||
latestURL=${latestURL:1:$((${#latestURL} - 1 - 1))}
|
||||
if [ "$countryCode" == "CN" ]; then
|
||||
if [[ $auto == True ]]; then
|
||||
latestURL="https://ghproxy.com/"$latestURL
|
||||
else
|
||||
read -r -p "检测到国内网络环境,是否使用镜像下载以加速(y/n)" input
|
||||
read -r -p "检测到国内网络环境,是否使用镜像下载以加速(n/y)[y]" input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
latestURL="https://ghproxy.com/"$latestURL
|
||||
@@ -222,10 +225,7 @@ runBinrayFileHelp() {
|
||||
}
|
||||
|
||||
addCronTask() {
|
||||
if [[ $auto == True ]]; then
|
||||
return 0
|
||||
fi
|
||||
read -r -p "是否添加自动更新任务?(y/n)" input
|
||||
read -r -p "是否添加自动更新任务?(n/y):[n]" input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
if [[ ${osDistribution} == "darwin" ]]; then
|
||||
@@ -253,9 +253,9 @@ addCronTask() {
|
||||
|
||||
# Check Procedure
|
||||
checkRootPermit
|
||||
ask_update_script
|
||||
checkSystemDistribution
|
||||
checkSystemArch
|
||||
ask_update_script
|
||||
checkPackageManger
|
||||
install_software wget
|
||||
install_software jq
|
||||
@@ -267,4 +267,4 @@ downloadBinrayFile
|
||||
|
||||
# Run Procedure
|
||||
runBinrayFileHelp
|
||||
addCronTask
|
||||
[[ $auto != True ]] && addCronTask
|
||||
|
||||
114
quicklytest.sh
114
quicklytest.sh
@@ -19,25 +19,50 @@ ${Font_suffix}"
|
||||
check_root() {
|
||||
[[ "$(id -u)" != "0" ]] && echo -e "${Error} must be root user !" && exit 1
|
||||
}
|
||||
ask_if()
|
||||
{
|
||||
|
||||
checkNexttrace() {
|
||||
echo -e "${Info} 正在检查Nexttrace..."
|
||||
if curl -sL -O "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh" || curl -sL -O "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh"; then
|
||||
bash nt_install.sh --auto >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
ask_if() {
|
||||
local choice=""
|
||||
while [ "$choice" != "y" ] && [ "$choice" != "n" ]
|
||||
do
|
||||
echo -e "${Info} $1"
|
||||
read choice
|
||||
done
|
||||
[ $choice == y ] && return 0
|
||||
echo -e "${Info} $1"
|
||||
read choice
|
||||
[[ $choice == y ]] && return 0
|
||||
return 1
|
||||
}
|
||||
#检查脚本更新
|
||||
check_script_update()
|
||||
{
|
||||
[ "$(md5sum "${BASH_SOURCE[0]}" | awk '{print $1}')" == "$(md5sum <(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh") | awk '{print $1}')" ] && return 1 || return 0
|
||||
|
||||
checkSystemDistribution() {
|
||||
case "$OSTYPE" in
|
||||
darwin*)
|
||||
osDistribution="darwin"
|
||||
downPath="/var/tmp/nexttrace"
|
||||
;;
|
||||
linux*)
|
||||
osDistribution="linux"
|
||||
downPath="/var/tmp/nexttrace"
|
||||
;;
|
||||
*)
|
||||
red "unknown: $OSTYPE"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#检查脚本更新
|
||||
check_script_update() {
|
||||
if [[ ${osDistribution} == "darwin" ]]; then
|
||||
[ "$(cat "${BASH_SOURCE[0]}" | md5)" == "$(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh" | md5)" ] && return 1 || return 0
|
||||
else
|
||||
[ "$(md5sum "${BASH_SOURCE[0]}" | awk '{print $1}')" == "$(md5sum <(curl -sL "https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh") | awk '{print $1}')" ] && return 1 || return 0
|
||||
fi
|
||||
}
|
||||
|
||||
#更新脚本
|
||||
update_script()
|
||||
{
|
||||
update_script() {
|
||||
if curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh" || curl -sL -o "${BASH_SOURCE[0]}" "https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh"; then
|
||||
echo -e "${Info} 脚本更新完成,正在重启脚本..."
|
||||
exec bash ${BASH_SOURCE[0]}
|
||||
@@ -46,15 +71,16 @@ update_script()
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
ask_update_script()
|
||||
{
|
||||
|
||||
ask_update_script() {
|
||||
if check_script_update; then
|
||||
echo -e "${Info} 脚本可升级"
|
||||
ask_if "是否升级脚本?(y/n)" && update_script
|
||||
ask_if "是否升级脚本?(n/y)[n]" && update_script
|
||||
else
|
||||
echo -e "${Info} 脚本已经是最新版本"
|
||||
fi
|
||||
}
|
||||
|
||||
check_mode() {
|
||||
echo -e "${Info} Nexttrace目前支持以下三种协议发起Traceroute请求:\n1.ICMP\n2.TCP(速度最快,但部分节点不支持)\n3.UDP\n(IPv6暂只支持ICMP模式)" && read -p "输入数字以选择:" node
|
||||
|
||||
@@ -67,19 +93,23 @@ check_mode() {
|
||||
[[ "${node}" == "2" ]] && TRACECMD="nexttrace -T"
|
||||
[[ "${node}" == "3" ]] && TRACECMD="nexttrace -U"
|
||||
|
||||
|
||||
echo -e "${Info} 结果是否制表?(制表模式为非实时显示)"
|
||||
if ask_if "输入y/n以选择模式:" ; then
|
||||
TRACECMD=${TRACECMD}" -rdns -table"
|
||||
echo -e "${Info} 结果是否制表?(制表模式为非实时显示)"
|
||||
if ask_if "输入n/y以选择模式:[n]"; then
|
||||
TRACECMD=${TRACECMD}" -rdns -table"
|
||||
##Route-Path功能还未完善,临时替代:
|
||||
[[ "${node}" == "2" ]] && TRACECMD=${TRACECMD}" -report"
|
||||
##
|
||||
else
|
||||
TRACECMD=${TRACECMD}" -rdns -realtime"
|
||||
TRACECMD=${TRACECMD}" -rdns -realtime"
|
||||
##Route-Path功能还未完善,临时替代:
|
||||
[[ "${node}" == "1" ]] && TRACECMD=${TRACECMD}" -report"
|
||||
[[ "${node}" == "2" ]] && TRACECMD=${TRACECMD}" -report"
|
||||
##
|
||||
fi
|
||||
|
||||
return 0
|
||||
#未实现的功能:
|
||||
ask_if "是否升级脚本?(y/n)" && update_script
|
||||
echo -e "${Info} 是否输出Route-Path?"
|
||||
ask_if "输入y/n以选择模式:" && TRACECMD=${TRACECMD}" -report"
|
||||
|
||||
#echo -e "${Info} 是否输出Route-Path?"
|
||||
#ask_if "输入n/y以选择模式:[n]" && TRACECMD=${TRACECMD}" -report"
|
||||
|
||||
}
|
||||
|
||||
test_single() {
|
||||
@@ -95,12 +125,13 @@ test_single() {
|
||||
|
||||
repeat_test_single
|
||||
}
|
||||
|
||||
repeat_test_single() {
|
||||
echo -e "${Info} 是否继续测试其他目标 ip ?"
|
||||
if ask_if "输入y/n以选择:" ; then
|
||||
test_single
|
||||
echo -e "${Info} 是否继续测试其他目标 ip ?"
|
||||
if ask_if "输入n/y以选择:[n]"; then
|
||||
test_single
|
||||
else
|
||||
echo -e "${Info} 退出脚本 ..." && exit 0
|
||||
echo -e "${Info} 退出脚本 ..." && exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -109,6 +140,7 @@ test_alternative() {
|
||||
set_alternative
|
||||
result_alternative
|
||||
}
|
||||
|
||||
select_alternative() {
|
||||
echo -e "${Info} 选择需要测速的目标网络: \n1.中国电信\n2.中国联通\n3.中国移动\n4.教育网"
|
||||
read -p "输入数字以选择:" ISP
|
||||
@@ -118,12 +150,14 @@ select_alternative() {
|
||||
echo -e "${Info} 请重新选择" && read -p "输入数字以选择:" ISP
|
||||
done
|
||||
}
|
||||
|
||||
set_alternative() {
|
||||
[[ "${ISP}" == "1" ]] && node_1
|
||||
[[ "${ISP}" == "2" ]] && node_2
|
||||
[[ "${ISP}" == "3" ]] && node_3
|
||||
[[ "${ISP}" == "4" ]] && node_4
|
||||
}
|
||||
|
||||
node_1() {
|
||||
echo -e "1.上海电信(天翼云)\n2.厦门电信CN2\n3.北京电信\n4.江苏电信\n5.广东深圳电信\n6.广州电信(天翼云)\n7.浙江电信" && read -p "输入数字以选择:" node
|
||||
|
||||
@@ -140,6 +174,7 @@ node_1() {
|
||||
[[ "${node}" == "6" ]] && ISP_name="广州电信(天翼云)" && ip=14.215.116.1
|
||||
[[ "${node}" == "7" ]] && ISP_name="浙江电信" && ip=115.236.169.86
|
||||
}
|
||||
|
||||
node_2() {
|
||||
echo -e "1.上海联通\n2.重庆联通\n3.北京联通\n4.安徽合肥联通\n5.江苏南京联通\n6.浙江杭州联通\n7.广东联通" && read -p "输入数字以选择:" node
|
||||
|
||||
@@ -156,6 +191,7 @@ node_2() {
|
||||
[[ "${node}" == "6" ]] && ISP_name="浙江联通" && ip=60.12.214.156
|
||||
[[ "${node}" == "7" ]] && ISP_name="广东联通" && ip=58.252.2.194
|
||||
}
|
||||
|
||||
node_3() {
|
||||
echo -e "1.上海移动\n2.四川成都移动\n3.北京移动\n4.浙江杭州移动\n5.广东移动\n6.江苏移动\n7.浙江移动" && read -p "输入数字以选择:" node
|
||||
|
||||
@@ -172,9 +208,11 @@ node_3() {
|
||||
[[ "${node}" == "6" ]] && ISP_name="江苏移动" && ip=120.195.6.129
|
||||
[[ "${node}" == "7" ]] && ISP_name="浙江移动" && ip=183.246.69.139
|
||||
}
|
||||
|
||||
node_4() {
|
||||
ISP_name="北京教育网" && ip=211.68.69.240
|
||||
}
|
||||
|
||||
result_alternative() {
|
||||
echo -e "${Info} 测试路由 到 ${ISP_name} 中 ..."
|
||||
${TRACECMD} ${ip} | grep -v -E 'NextTrace|XGadget-lab|Data\ Provider'
|
||||
@@ -182,12 +220,13 @@ result_alternative() {
|
||||
|
||||
repeat_test_alternative
|
||||
}
|
||||
|
||||
repeat_test_alternative() {
|
||||
echo -e "${Info} 是否继续测试其他节点?"
|
||||
if ask_if "输入y/n以选择:" ; then
|
||||
test_alternative
|
||||
echo -e "${Info} 是否继续测试其他节点?"
|
||||
if ask_if "输入n/y以选择:[n]"; then
|
||||
test_alternative
|
||||
else
|
||||
echo -e "${Info} 退出脚本 ..." && exit 0
|
||||
echo -e "${Info} 退出脚本 ..." && exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -204,6 +243,7 @@ test_all() {
|
||||
|
||||
echo -e "${Info} 四网路由快速测试 已完成 !"
|
||||
}
|
||||
|
||||
result_all() {
|
||||
ISP_name=$2
|
||||
echo -e "${Info} 测试路由 到 ${ISP_name} 中 ..."
|
||||
@@ -212,7 +252,9 @@ result_all() {
|
||||
}
|
||||
|
||||
check_root
|
||||
checkSystemDistribution
|
||||
ask_update_script
|
||||
checkNexttrace
|
||||
check_mode
|
||||
echo -e "${Info} 选择你要使用的功能: "
|
||||
echo -e "1.选择一个节点进行测试\n2.四网路由快速测试\n3.手动输入 ip 进行测试"
|
||||
|
||||
@@ -128,10 +128,18 @@ func (r *reporter) InitialBaseData() Reporter {
|
||||
}
|
||||
|
||||
func (r *reporter) Print() {
|
||||
var beforeActiveTTL uint16 = 1
|
||||
var beforeActiveTTL uint16 = 0
|
||||
r.InitialBaseData()
|
||||
// 尝试首个有效 TTL
|
||||
for i := uint16(0); i < r.targetTTL; i++ {
|
||||
if len(r.routeReport[i]) != 0 {
|
||||
beforeActiveTTL = i
|
||||
// 找到以后便不再循环
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i := uint16(1); i < r.targetTTL; i++ {
|
||||
for i := beforeActiveTTL; i < r.targetTTL; i++ {
|
||||
// 计算该TTL内的数据长度,如果为0,则代表没有有效数据
|
||||
if len(r.routeReport[i]) == 0 {
|
||||
// 跳过改跃点的数据整理
|
||||
@@ -139,7 +147,7 @@ func (r *reporter) Print() {
|
||||
}
|
||||
nodeReport := r.routeReport[i][0]
|
||||
|
||||
if i == 1 {
|
||||
if i == beforeActiveTTL {
|
||||
fmt.Printf("AS%s %s「%s『%s", nodeReport.asn, nodeReport.isp, nodeReport.geo[0], nodeReport.geo[1])
|
||||
} else {
|
||||
nodeReportBefore := r.routeReport[beforeActiveTTL][0]
|
||||
|
||||
Reference in New Issue
Block a user