Compare commits

..

5 Commits

Author SHA1 Message Date
sjlleo
3aa4696fa9 add: 新增配置文件模块 2022-05-30 21:15:22 +08:00
sjlleo
b4abaffc7c update: 让截图大小适中 2022-05-28 11:09:45 +08:00
sjlleo
c96fb4efa3 update: IP Database Copyright的IP占比信息用表格显示 2022-05-28 10:47:03 +08:00
sjlleo
876de6bde1 update: 完善描述 2022-05-28 10:26:31 +08:00
tsosunchia
7dbec0c7a1 update README.md 增加提示 2022-05-28 02:52:27 +08:00
12 changed files with 264 additions and 38 deletions

View File

@@ -13,26 +13,24 @@
### Automated Install
```bash
#下载nt_install.sh
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh -O
#执行nt_install.sh
sudo bash nt_install.sh
# Note: This Script Only Supports Linux/macOS, Other Unix-Like Systems are UNAVAILABLE
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/nt_install.sh -O && sudo bash nt_install.sh
```
### Alternative methods
* `Release`里面为很多系统以及不同架构提供了编译好的二进制可执行文件,如果没有可以自行编译。
* 一些本项目的必要依赖在`Windows``Golang`底层实现不完全,所以目前`NextTrace``Windows`平台不可用。
如果你的目的只是为了快速测试服务器的到中国内地的线路,没有手动使用 NextTrace 的需求,那么建议你直接使用本仓库的 `quicklytest.sh`
### Fast Test
此脚本旨在快速测试服务器的到中国内地的线路,建议新手或者没有自定义`NextTrace`功能需求的用户使用。
```bash
#下载quicklytest.sh
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh -O
#执行quicklytest.sh
sudo bash quicklytest.sh
curl -Ls https://github.com/xgadget-lab/nexttrace/raw/main/quicklytest.sh -O && sudo bash quicklytest.sh
```
### Get Started
`NextTrace`默认使用`icmp`协议发起`TraceRoute`请求,该协议同时支持`IPv4``IPv6`
`NextTrace`默认使用`ICMP`协议发起`TraceRoute`请求,该协议同时支持`IPv4``IPv6`
```bash
# IPv4 ICMP Trace
@@ -141,17 +139,17 @@ Options:
## 项目截图
![NextTrace Screenshot](asset/screenshot.png)
<img src=asset/screenshot.png alt="NextTrace Screenshot" width="683" height="688" />
## FAQ 常见问题
如果你在安装或者使用的时候遇到了问题,我们建议你不要把新建一个 `issue` 作为首选项
或许可以在这里找到答案 -> [前往 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)
1. 查看是否为常见问题 -> [前往 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)
2. 不会软件的参数使用 -> [前往 Github Discussions](https://github.com/xgadget-lab/nexttrace/discussions)
3. 疑似BUG、或者功能建议 -> [前往 Github Issues](https://github.com/xgadget-lab/nexttrace/issues)
## Thanks
@@ -159,36 +157,43 @@ Options:
[Sam Sam](https://github.com/samleong123) (samsam123@samsam123.name.my)
[waiting4new](https://github.com/waiting4new)、[FFEE_CO](https://github.com/fkx4-p)、[nsnnns](https://github.com/tsosunchia)
[tsosunchia](https://github.com/tsosunchia)
[waiting4new](https://github.com/waiting4new)
[FFEE_CO](https://github.com/fkx4-p)
## IP Database Copyright
### IPv4 Database
#### China MainLand
#### China
- 项目组自行维护 ~ 御三家骨干网数据 ~ 5%
- 埃文科技 Paid Database ~ 95%
**这里有朋友就要问了,为什么不全部使用埃文的付费库?**
埃文的库一直都不是最优选择IPIP.NET 才是,但是因为他们不对私,所以我们只能选择价格更便宜的埃文库。
埃文家的数据库,在骨干网这块,准度可以说是非常糟糕,作为一款可视化的路由跟踪工具,骨干网的数据库准度非常重要。
所以我们选择了尝试自行去校准一部分骨干网数据,但是由于我们缺乏检测节点以及志愿者,所以这项工作可能会进展的尤其缓慢。
| ISP | 类型 | 数据源 | 占比 |
| :------------: | :----: | :--------------: | :--: |
| 电信/联通/移动 | 骨干网 | NextTrace | 10% |
| 电信/联通/移动 | 城域网 | 埃文科技 | 90% |
#### WorldWide
- 埃文科技 Paid Database ~ 15%
| ISP | 类型 | 数据源 | 占比 |
| :------------: | :----: | :--------------: | :--: |
| Tier-01 | 骨干网 | IPInfo | 2% |
| Tier-01 | 骨干网 | 埃文科技 | 3% |
| Tier-01 | 骨干网 | IPInSight | 5% |
| Tier-01 | 城域网 | IPInSight | 90% |
- IpInfo Free ~ 15%
- IPInSight Free ~ 70%
| ISP | 类型 | 数据源 | 占比 |
| :------------: | :----: | :--------------: | :--: |
| Others | 骨干网 | IPInSight | 5% |
| Others | 城域网 | IPInSight | 95% |
### IPv6 Database
| ISP | 类型 | 数据源 | 占比 |
| :------------: | :----: | :--------------: | :--: |
| All | 全部 | IP2Location Lite | 100% |
This product includes IP2Location LITE data available from <a href="https://lite.ip2location.com">https://lite.ip2location.com</a>.
### Others

31
config/config.go Normal file
View File

@@ -0,0 +1,31 @@
package config
import "os"
type tracerConfig struct {
Token `yaml:"Token"`
Preference `yaml:"Preference"`
}
type Token struct {
LeoMoeAPI string `yaml:"LeoMoeAPI"`
IPInfo string `yaml:"IPInfo"`
}
type Preference struct {
AlwaysRoutePath bool `yaml:"AlwaysRoutePath"`
}
type configPath func() (string, error)
func configFromRunDir() (string, error) {
return "./", nil
}
func configFromUserHomeDir() (string, error) {
dir, err := os.UserHomeDir()
if err != nil {
return "", err
}
return dir + "/.nexttrace/", nil
}

18
config/config_test.go Normal file
View File

@@ -0,0 +1,18 @@
package config
import (
"testing"
"log"
)
func TestReadConfig(t *testing.T) {
if res, err := Read(); err != nil {
log.Println(err)
} else {
log.Println(res)
}
}
func TestGenerateConfig(t *testing.T) {
Generate()
}

94
config/generate_config.go Normal file
View File

@@ -0,0 +1,94 @@
package config
import (
"os"
"io/ioutil"
"fmt"
"gopkg.in/yaml.v2"
)
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func writeFile(content []byte) error {
var err error
var path string
path, err = configFromUserHomeDir()
if err != nil {
path, err = configFromRunDir()
if err != nil {
return err
}
}
if exist, _ := pathExists(path); !exist {
err := os.Mkdir(path, os.ModePerm)
if err != nil {
return err
}
}
if err = ioutil.WriteFile(path + "ntraceConfig.yml", []byte(content), 0644); err != nil{
return err
}
return nil
}
func Generate() (*tracerConfig, error) {
var leotoken string
var iPInfoToken string
var routePathEnable string
fmt.Println("这是一个配置向导,我们会帮助您生成配置文件,它是一次性的,除非您主动要求重新生成,否则它将不会再出现")
fmt.Println("请输入您的LeoMoeAPI Token如果您没有请到 Telegram Bot @NextTraceBot 获取一个")
fmt.Scanln(&leotoken)
if leotoken == "" {
fmt.Println("检测到您的输入为空您将使用公共Token。这意味着您将和所有使用此Token的客户端共用每分钟150次IP查询的额度")
leotoken = "NextTraceDemo"
}
fmt.Println("请输入您的IPInfo Token如果您不需要使用IPInfo可以直接回车")
fmt.Scanln(&iPInfoToken)
token := Token{
LeoMoeAPI: leotoken,
IPInfo: iPInfoToken,
}
var preference Preference
fmt.Print("您是否希望在每次Traceroute结束后显示Route-Path图? (y/n)")
fmt.Scanln(&routePathEnable)
if routePathEnable == "n" || routePathEnable == "N" || routePathEnable == "no" || routePathEnable == "No" || routePathEnable == "NO" {
preference = Preference{AlwaysRoutePath: false}
} else {
preference = Preference{AlwaysRoutePath: true}
}
finalConfig := tracerConfig{
Token: token,
Preference: preference,
}
yamlData, err := yaml.Marshal(&finalConfig)
if err != nil {
return nil, err
}
if err = writeFile(yamlData); err != nil {
return nil, err
} else {
fmt.Println("配置文件创建成功")
return &finalConfig, nil
}
}

47
config/read_config.go Normal file
View File

@@ -0,0 +1,47 @@
package config
import (
"io/ioutil"
"log"
"gopkg.in/yaml.v2"
)
func (c *tracerConfig) Parse(data []byte) error {
return yaml.Unmarshal(data, c)
}
func readFile(cp configPath) ([]byte, error) {
var content []byte
path, err := cp()
if err != nil {
log.Println(err)
return nil, err
}
content, err = ioutil.ReadFile(path + "ntraceConfig.yml")
if err != nil {
return nil, err
}
return content, nil
}
func Read() (*tracerConfig, error) {
var data []byte
var err error
data, err = readFile(configFromRunDir)
if err != nil {
data, err = readFile(configFromUserHomeDir)
if err != nil {
return nil, err
}
}
var config tracerConfig
if err := config.Parse(data); err != nil {
return nil, err
}
return &config, err
}

1
go.mod
View File

@@ -11,6 +11,7 @@ require (
require (
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
require (

2
go.sum
View File

@@ -49,6 +49,8 @@ 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.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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=

View File

@@ -26,7 +26,9 @@ func GetSource(s string) Source {
return IPInSight
case "IPAPI.COM":
return IPApiCom
case "IPINFO":
return IPInfo
default:
return nil
return LeoIP
}
}

View File

@@ -8,7 +8,6 @@ import (
)
func IPInfo(ip string) (*IPGeoData, error) {
resp, err := http.Get("https://ipinfo.io/" + ip + "?token=" + token.ipinfo)
if err != nil {
return nil, err

View File

@@ -1,5 +1,7 @@
package ipgeo
import "github.com/xgadget-lab/nexttrace/config"
type tokenData struct {
ipinsight string
ipinfo string
@@ -11,3 +13,9 @@ var token = tokenData{
ipinfo: "",
ipleo: "NextTraceDemo",
}
func SetToken(c config.Token) {
token.ipleo = c.LeoMoeAPI
token.ipinfo = c.IPInfo
}

17
main.go
View File

@@ -8,6 +8,7 @@ import (
"strings"
"time"
"github.com/xgadget-lab/nexttrace/config"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/printer"
"github.com/xgadget-lab/nexttrace/reporter"
@@ -18,7 +19,7 @@ import (
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 port = fSet.Int("p", 80, "Set SYN Traceroute Port")
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).")
@@ -65,6 +66,16 @@ func main() {
log.Fatalln("Traceroute requires root/sudo privileges.")
}
configData, err := config.Read();
if err != nil {
if configData, err = config.Generate(); err != nil {
log.Fatal(err)
}
}
ipgeo.SetToken(configData.Token)
ip := util.DomainLookUp(domain)
printer.PrintTraceRouteNav(ip, domain, *dataOrigin)
@@ -110,7 +121,9 @@ func main() {
printer.TraceroutePrinter(res)
}
if *routePath {
p := configData.Preference
if *routePath || p.AlwaysRoutePath {
r := reporter.New(res, ip.String())
r.Print()
}

View File

@@ -29,6 +29,12 @@ checkSystemArch() {
'arm64' | 'aarch64')
archParam="arm64"
;;
'armv7l')
archParam='armv7'
;;
'i386')
archParam="386"
;;
*)
red "未知的系统架构,请联系开发者."
exit 1
@@ -47,7 +53,7 @@ checkSystemDistribution() {
downPath="/var/tmp/nexttrace"
;;
*)
red "unknown: $OSTYPE"
red "安装脚本暂不支持的操作系统: $OSTYPE"
exit 1
;;
esac