From 2403308c1bedf26a25b6369e2cc0b3223d234563 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:53:58 +0800 Subject: [PATCH 01/13] Update build.yml --- .github/workflows/build.yml | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf6da9e..ffe00b0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,7 @@ on: push: pull_request: + workflow_dispatch: name: Test & Build Release jobs: @@ -11,24 +12,35 @@ jobs: - uses: actions/setup-go@v2 with: - go-version: "1.18" + go-version: "1.20" - name: Test run: sudo go test -v -coverprofile='coverage.out' -covermode=count ./... Build: - needs: test - if: startsWith(github.ref, 'refs/tags/v') + needs: Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v2 with: - go-version: "1.18" - - - run: bash .cross_compile.sh + go-version: "1.20" + - name: compile + run: bash .cross_compile.sh + + - name: Upload files to Artifacts + uses: actions/upload-artifact@v3 + with: + path: | + dist/* + + Release: + needs: Build + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + steps: - name: Release uses: softprops/action-gh-release@v1 with: # 将下述可执行文件 release 上去 @@ -39,7 +51,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GT_Token }} publish-new-formula: - needs: build + needs: Release # The type of runner that the job will run on runs-on: ubuntu-latest From 64224c905e07e6e3c6d68c871a3a5ff32e013a99 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:01:18 +0800 Subject: [PATCH 02/13] Update ipinsight.go --- ipgeo/ipinsight.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipgeo/ipinsight.go b/ipgeo/ipinsight.go index df0c233..59f9782 100644 --- a/ipgeo/ipinsight.go +++ b/ipgeo/ipinsight.go @@ -8,7 +8,7 @@ import ( ) func IPInSight(ip string) (*IPGeoData, error) { - resp, err := http.Get("https://ipinsight.io/query?ip=" + ip) + resp, err := http.Get("https://api.ipinsight.io/query?ip=" + ip + "?token=" + token.ipinsight) if err != nil { return nil, err } From 8a01bccbff69e4d3cc03b3b21f986676788e612a Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:04:06 +0800 Subject: [PATCH 03/13] Update ipinsight.go --- ipgeo/ipinsight.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipgeo/ipinsight.go b/ipgeo/ipinsight.go index 59f9782..d43b4f5 100644 --- a/ipgeo/ipinsight.go +++ b/ipgeo/ipinsight.go @@ -8,7 +8,7 @@ import ( ) func IPInSight(ip string) (*IPGeoData, error) { - resp, err := http.Get("https://api.ipinsight.io/query?ip=" + ip + "?token=" + token.ipinsight) + resp, err := http.Get("https://api.ipinsight.io/ip/" + ip + "?token=" + token.ipinsight) if err != nil { return nil, err } From 510b0f6c32e584407d629add485cdd97c72551ec Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 11:48:49 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E5=8F=AF=E4=BD=BF=E7=94=A8=E5=88=AB?= =?UTF-8?q?=E5=90=8D=E8=B0=83=E7=94=A8=E7=AC=AC=E4=B8=89=E6=96=B9API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/cmd.go | 4 ++-- ipgeo/ipgeo.go | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 02ef472..57253c3 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -37,8 +37,8 @@ func Excute() { numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"}) parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"}) maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"}) - dataOrigin := parser.Selector("d", "data-provider", []string{"IP.SB", "IPInfo", "IPInsight", "IPAPI.com"}, &argparse.Options{Default: "LeoMoeAPI", - Help: "Choose IP Geograph Data Provider [LeoMoeAPI,IP.SB, IPInfo, IPInsight, IPAPI.com]"}) + dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com"}, &argparse.Options{Default: "LeoMoeAPI", + Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region]"}) noRdns := parser.Flag("n", "no-rdns", &argparse.Options{Help: "Do not resolve IP addresses to their domain names"}) alwaysRdns := parser.Flag("a", "always-rdns", &argparse.Options{Help: "Always resolve IP addresses to their domain names"}) routePath := parser.Flag("P", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"}) diff --git a/ipgeo/ipgeo.go b/ipgeo/ipgeo.go index 0b5e1dc..532c86d 100644 --- a/ipgeo/ipgeo.go +++ b/ipgeo/ipgeo.go @@ -39,6 +39,8 @@ func GetSource(s string) Source { return IPInSight case "IPAPI.COM": return IPApiCom + case "IP-API.COM": + return IPApiCom case "IPINFO": return IPInfo case "IP2REGION": From 110bdc27fffc7cb4a1eb193cdd2f7e476d8e1aec Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:01:18 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E6=96=B9API=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update README_zh_CN.md Update README.md Update ipinsight.go Update ipgeo.go --- README.md | 40 +++++++++++++++++--------------- README_zh_CN.md | 57 +++++++++++++++++++++++++++------------------- cmd/cmd.go | 4 ++-- ipgeo/ipgeo.go | 2 ++ ipgeo/ipinsight.go | 2 +- 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 1c03507..c3e896a 100644 --- a/README.md +++ b/README.md @@ -122,15 +122,15 @@ nexttrace --no-rdns www.bbix.net nexttrace --route-path www.time.com.my ``` -`NextTrace` supports users to select their own IP API (currently supports: `LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`) +`NextTrace` supports users to select their own IP API (currently supports: `LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IP-API.com`, `Ip2region`) ```bash -# You can specify the IP database by yourself [IP.SB here], if not specified, LeoMoeAPI will be used -nexttrace --data-provider IP.SB -## Note that the ipinfo API needs users to purchase services from ipinfo. If necessary, you can clone this project, add the token provided by ipinfo and compile it yourself +# You can specify the IP database by yourself [IP-API.com here], if not specified, LeoMoeAPI will be used +nexttrace --data-provider ip-api.com +## Note that the `ipinfo` and `IPInsight` API needs users to purchase services from them. If necessary, you can clone this project, add the token provided by `ipinfo` or `IPInsight` and compile it yourself ## Fill the token to: ipgeo/tokens.go ## Please be aware: Due to the serious abuse of IP.SB, you will often be not able to query IP data from this source -## IPAPI.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes. +## IP-API.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes. ``` `NextTrace` supports mixed parameters and shortened parameters @@ -161,15 +161,15 @@ All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/x usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns] - [-a|--always-rdns] [-P|--route-path] [-r|--report] - [-o|--output] [-t|--table] [-c|--classic] [-f|--first - ] [-M|--map] [-v|--version] [-s|--source ""] - [-D|--dev ""] [-R|--route] [-z|--send-time ] - [-i|--ttl-time ] [-g|--language (en|cn)] [IP Address - or Domain] - - An open source visual route tracking CLI tool + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com)] + [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] + [-r|--report] [--dn42] [-o|--output] [-t|--table] + [-c|--classic] [-f|--first ] [-M|--map] + [-v|--version] [-s|--source ""] [-D|--dev ""] + [-R|--route] [-z|--send-time ] [-i|--ttl-time + ] [_positionalArg_nexttrace_25 ""] + [--dot-server (dnssb|aliyun|dnspod|google|cloudflare)] + [-g|--language (en|cn)] Arguments: @@ -194,9 +194,9 @@ Arguments: 18 -m --max-hops Set the max number of hops (max TTL to be reached). Default: 30 - -d --data-provider Choose IP Geograph Data Provider - [LeoMoeAPI,IP.SB, IPInfo, IPInsight, - IPAPI.com]. Default: LeoMoeAPI + -d --data-provider Choose IP Geograph Data Provider [IP.SB, + IPInfo, IPInsight, IP-API.com, Ip2region]. + Default: LeoMoeAPI -n --no-rdns Do not resolve IP addresses to their domain names -a --always-rdns Always resolve IP addresses to their @@ -204,6 +204,7 @@ Arguments: -P --route-path Print traceroute hop path by ASN and location -r --report output using report mode + --dn42 DN42 Mode -o --output Write trace result to file (RealTimePrinter ONLY) -t --table Output trace results as table @@ -211,7 +212,7 @@ Arguments: BestTrace -f --first Start from the first_ttl hop (instead from 1). Default: 1 - -M --map Disable Print Trace Map Function + -M --map Disable Print Trace Map -v --version Print version info and exit -s --source Use source src_addr for outgoing packets -D --dev Use the following Network Devices as the @@ -224,6 +225,9 @@ Arguments: groups by TTL. Useful when some routers use rate-limit for ICMP messages. Default: 500 + --_positionalArg_nexttrace_25 IP Address or domain name + --dot-server Use DoT Server for DNS Parse [dnssb, + aliyun, dnspod, google, cloudflare] -g --language Choose the language for displaying [en, cn]. Default: cn ``` diff --git a/README_zh_CN.md b/README_zh_CN.md index b3ce6b5..df63c13 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -141,42 +141,46 @@ nexttrace --no-rdns www.bbix.net nexttrace --route-path www.time.com.my ``` -`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`) +`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IP-API.com`, `Ip2region`) ```bash -# 可以自行指定IP数据库[此处为IP.SB],不指定则默认为LeoMoeAPI -nexttrace --data-provider IP.SB -## 特别的:其中 ipinfo API 需要从 ipinfo 自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 +# 可以自行指定IP数据库[此处为IP-API.com],不指定则默认为LeoMoeAPI +nexttrace --data-provider ip-api.com +## 特别的:其中 `ipinfo` 和 `IPInsight` API 需要从这些服务商自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 ## TOKEN填写路径:ipgeo/tokens.go ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 -## IPAPI.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 +## IP-API.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 ``` `NextTrace`支持使用混合参数和简略参数 ```bash Example: -nexttrace --data-provider IPAPI.com --max-hops 20 --tcp --port 443 --queries 5 --no-rdns 1.1.1.1 +nexttrace --data-provider ip-api.com --max-hops 20 --tcp --port 443 --queries 5 --no-rdns 1.1.1.1 nexttrace -tcp --queries 2 --parallel-requests 1 --table --route-path 2001:4860:4860::8888 Equivalent to: -nexttrace -d IPAPI.com -m 20 -T -p 443 -q 5 -n 1.1.1.1 +nexttrace -d ip-api.com -m 20 -T -p 443 -q 5 -n 1.1.1.1 nexttrace -T -q 2 --parallel-requests 1 -t -R 2001:4860:4860::8888 ``` ### 全部用法详见 Usage 菜单 ```shell -Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port +usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns] - [-r|--route-path] [-o|--output] [-t|--table] [-c|--classic] - [-f|--first ] [-M|--map] [-v|--version] [-s|--source - ""] [-D|--dev ""] [-R|--route] [-z|--send-time - ] [-i|--ttl-time ] - [IP Address or Domain name] + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com)] + [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] + [-r|--report] [--dn42] [-o|--output] [-t|--table] + [-c|--classic] [-f|--first ] [-M|--map] + [-v|--version] [-s|--source ""] [-D|--dev ""] + [-R|--route] [-z|--send-time ] [-i|--ttl-time + ] [_positionalArg_nexttrace_25 ""] + [--dot-server (dnssb|aliyun|dnspod|google|cloudflare)] + [-g|--language (en|cn)] + Arguments: -h --help Print help information @@ -200,13 +204,17 @@ Arguments: 18 -m --max-hops Set the max number of hops (max TTL to be reached). Default: 30 - -d --data-provider Choose IP Geograph Data Provider - [LeoMoeAPI,IP.SB, IPInfo, IPInsight, - IPAPI.com]. Default: LeoMoeAPI - -n --no-rdns Do not resolve IP addresses to their + -d --data-provider Choose IP Geograph Data Provider [IP.SB, + IPInfo, IPInsight, IP-API.com, Ip2region]. + Default: LeoMoeAPI + -n --no-rdns Do not resolve IP addresses to their domain names - -r --route-path Print traceroute hop path by ASN and + -a --always-rdns Always resolve IP addresses to their + domain names + -P --route-path Print traceroute hop path by ASN and location + -r --report output using report mode + --dn42 DN42 Mode -o --output Write trace result to file (RealTimePrinter ONLY) -t --table Output trace results as table @@ -214,7 +222,7 @@ Arguments: BestTrace -f --first Start from the first_ttl hop (instead from 1). Default: 1 - -M --map Disable Print Trace Map Function + -M --map Disable Print Trace Map -v --version Print version info and exit -s --source Use source src_addr for outgoing packets -D --dev Use the following Network Devices as the @@ -222,11 +230,14 @@ Arguments: -R --route Show Routing Table [Provided By BGP.Tools] -z --send-time Set the time interval for sending every packet. Useful when some routers use - rate-limit for ICMP messages.. Default: 0 + rate-limit for ICMP messages. Default: 100 -i --ttl-time Set the time interval for sending packets groups by TTL. Useful when some routers - use rate-limit for ICMP messages.. - Default: 500 + use rate-limit for ICMP messages. Default: + 500 + --_positionalArg_nexttrace_25 IP Address or domain name + --dot-server Use DoT Server for DNS Parse [dnssb, + aliyun, dnspod, google, cloudflare] -g --language Choose the language for displaying [en, cn]. Default: cn ``` diff --git a/cmd/cmd.go b/cmd/cmd.go index 02ef472..57253c3 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -37,8 +37,8 @@ func Excute() { numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"}) parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"}) maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"}) - dataOrigin := parser.Selector("d", "data-provider", []string{"IP.SB", "IPInfo", "IPInsight", "IPAPI.com"}, &argparse.Options{Default: "LeoMoeAPI", - Help: "Choose IP Geograph Data Provider [LeoMoeAPI,IP.SB, IPInfo, IPInsight, IPAPI.com]"}) + dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com"}, &argparse.Options{Default: "LeoMoeAPI", + Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region]"}) noRdns := parser.Flag("n", "no-rdns", &argparse.Options{Help: "Do not resolve IP addresses to their domain names"}) alwaysRdns := parser.Flag("a", "always-rdns", &argparse.Options{Help: "Always resolve IP addresses to their domain names"}) routePath := parser.Flag("P", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"}) diff --git a/ipgeo/ipgeo.go b/ipgeo/ipgeo.go index 0b5e1dc..532c86d 100644 --- a/ipgeo/ipgeo.go +++ b/ipgeo/ipgeo.go @@ -39,6 +39,8 @@ func GetSource(s string) Source { return IPInSight case "IPAPI.COM": return IPApiCom + case "IP-API.COM": + return IPApiCom case "IPINFO": return IPInfo case "IP2REGION": diff --git a/ipgeo/ipinsight.go b/ipgeo/ipinsight.go index df0c233..d43b4f5 100644 --- a/ipgeo/ipinsight.go +++ b/ipgeo/ipinsight.go @@ -8,7 +8,7 @@ import ( ) func IPInSight(ip string) (*IPGeoData, error) { - resp, err := http.Get("https://ipinsight.io/query?ip=" + ip) + resp, err := http.Get("https://api.ipinsight.io/ip/" + ip + "?token=" + token.ipinsight) if err != nil { return nil, err } From c2eebca25cba4fc6ca16dd46341656233f3b9fba Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:38:42 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E4=BF=AE=E6=AD=A3IPInfo=20BUG=20?= =?UTF-8?q?=E5=92=8C=E5=A2=9E=E5=8A=A0IPInfoLocal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++++++++++++++++------------- README_zh_CN.md | 44 +++++++++++++++++++++++-------------- cmd/cmd.go | 4 ++-- go.mod | 1 + go.sum | 2 ++ ipgeo/ipgeo.go | 2 ++ ipgeo/ipinfo.go | 5 +++-- ipgeo/ipinfoLocal.go | 52 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 109 insertions(+), 35 deletions(-) create mode 100644 ipgeo/ipinfoLocal.go diff --git a/README.md b/README.md index 1c03507..72a62cc 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ nexttrace --no-rdns www.bbix.net nexttrace --route-path www.time.com.my ``` -`NextTrace` supports users to select their own IP API (currently supports: `LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`) +`NextTrace` supports users to select their own IP API (currently supports: `LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`, `Ip2region`, `IPInfoLocal`) ```bash # You can specify the IP database by yourself [IP.SB here], if not specified, LeoMoeAPI will be used @@ -158,18 +158,18 @@ All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/x ### For full usage list, please refer to the usage menu ```shell -usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port +Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns] - [-a|--always-rdns] [-P|--route-path] [-r|--report] - [-o|--output] [-t|--table] [-c|--classic] [-f|--first - ] [-M|--map] [-v|--version] [-s|--source ""] - [-D|--dev ""] [-R|--route] [-z|--send-time ] - [-i|--ttl-time ] [-g|--language (en|cn)] [IP Address - or Domain] - - An open source visual route tracking CLI tool + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal)] + [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] + [-r|--report] [--dn42] [-o|--output] [-t|--table] + [-c|--classic] [-f|--first ] [-M|--map] + [-v|--version] [-s|--source ""] [-D|--dev ""] + [-R|--route] [-z|--send-time ] [-i|--ttl-time + ] [_positionalArg_nexttrace_25 ""] + [--dot-server (dnssb|aliyun|dnspod|google|cloudflare)] + [-g|--language (en|cn)] Arguments: @@ -194,9 +194,9 @@ Arguments: 18 -m --max-hops Set the max number of hops (max TTL to be reached). Default: 30 - -d --data-provider Choose IP Geograph Data Provider - [LeoMoeAPI,IP.SB, IPInfo, IPInsight, - IPAPI.com]. Default: LeoMoeAPI + -d --data-provider Choose IP Geograph Data Provider [IP.SB, + IPInfo, IPInsight, IP-API.com, Ip2region, + IPInfoLocal]. Default: LeoMoeAPI -n --no-rdns Do not resolve IP addresses to their domain names -a --always-rdns Always resolve IP addresses to their @@ -204,6 +204,7 @@ Arguments: -P --route-path Print traceroute hop path by ASN and location -r --report output using report mode + --dn42 DN42 Mode -o --output Write trace result to file (RealTimePrinter ONLY) -t --table Output trace results as table @@ -211,7 +212,7 @@ Arguments: BestTrace -f --first Start from the first_ttl hop (instead from 1). Default: 1 - -M --map Disable Print Trace Map Function + -M --map Disable Print Trace Map -v --version Print version info and exit -s --source Use source src_addr for outgoing packets -D --dev Use the following Network Devices as the @@ -224,6 +225,9 @@ Arguments: groups by TTL. Useful when some routers use rate-limit for ICMP messages. Default: 500 + --_positionalArg_nexttrace_25 IP Address or domain name + --dot-server Use DoT Server for DNS Parse [dnssb, + aliyun, dnspod, google, cloudflare] -g --language Choose the language for displaying [en, cn]. Default: cn ``` diff --git a/README_zh_CN.md b/README_zh_CN.md index b3ce6b5..c662613 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -141,13 +141,14 @@ nexttrace --no-rdns www.bbix.net nexttrace --route-path www.time.com.my ``` -`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`) +`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`, `Ip2region`, `IPInfoLocal`) ```bash # 可以自行指定IP数据库[此处为IP.SB],不指定则默认为LeoMoeAPI nexttrace --data-provider IP.SB ## 特别的:其中 ipinfo API 需要从 ipinfo 自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 ## TOKEN填写路径:ipgeo/tokens.go +## 特别的:对于 `Ip2region`, `IPInfoLocal` ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 ## IPAPI.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 @@ -171,12 +172,16 @@ nexttrace -T -q 2 --parallel-requests 1 -t -R 2001:4860:4860::8888 Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns] - [-r|--route-path] [-o|--output] [-t|--table] [-c|--classic] - [-f|--first ] [-M|--map] [-v|--version] [-s|--source - ""] [-D|--dev ""] [-R|--route] [-z|--send-time - ] [-i|--ttl-time ] - [IP Address or Domain name] + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal)] + [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] + [-r|--report] [--dn42] [-o|--output] [-t|--table] + [-c|--classic] [-f|--first ] [-M|--map] + [-v|--version] [-s|--source ""] [-D|--dev ""] + [-R|--route] [-z|--send-time ] [-i|--ttl-time + ] [_positionalArg_nexttrace_25 ""] + [--dot-server (dnssb|aliyun|dnspod|google|cloudflare)] + [-g|--language (en|cn)] + Arguments: -h --help Print help information @@ -200,13 +205,17 @@ Arguments: 18 -m --max-hops Set the max number of hops (max TTL to be reached). Default: 30 - -d --data-provider Choose IP Geograph Data Provider - [LeoMoeAPI,IP.SB, IPInfo, IPInsight, - IPAPI.com]. Default: LeoMoeAPI - -n --no-rdns Do not resolve IP addresses to their + -d --data-provider Choose IP Geograph Data Provider [IP.SB, + IPInfo, IPInsight, IP-API.com, Ip2region, + IPInfoLocal]. Default: LeoMoeAPI + -n --no-rdns Do not resolve IP addresses to their domain names - -r --route-path Print traceroute hop path by ASN and + -a --always-rdns Always resolve IP addresses to their + domain names + -P --route-path Print traceroute hop path by ASN and location + -r --report output using report mode + --dn42 DN42 Mode -o --output Write trace result to file (RealTimePrinter ONLY) -t --table Output trace results as table @@ -214,7 +223,7 @@ Arguments: BestTrace -f --first Start from the first_ttl hop (instead from 1). Default: 1 - -M --map Disable Print Trace Map Function + -M --map Disable Print Trace Map -v --version Print version info and exit -s --source Use source src_addr for outgoing packets -D --dev Use the following Network Devices as the @@ -222,11 +231,14 @@ Arguments: -R --route Show Routing Table [Provided By BGP.Tools] -z --send-time Set the time interval for sending every packet. Useful when some routers use - rate-limit for ICMP messages.. Default: 0 + rate-limit for ICMP messages. Default: 100 -i --ttl-time Set the time interval for sending packets groups by TTL. Useful when some routers - use rate-limit for ICMP messages.. - Default: 500 + use rate-limit for ICMP messages. Default: + 500 + --_positionalArg_nexttrace_25 IP Address or domain name + --dot-server Use DoT Server for DNS Parse [dnssb, + aliyun, dnspod, google, cloudflare] -g --language Choose the language for displaying [en, cn]. Default: cn ``` diff --git a/cmd/cmd.go b/cmd/cmd.go index 57253c3..02b2a9e 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -37,8 +37,8 @@ func Excute() { numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"}) parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"}) maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"}) - dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com"}, &argparse.Options{Default: "LeoMoeAPI", - Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region]"}) + dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal"}, &argparse.Options{Default: "LeoMoeAPI", + Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, IPInfoLocal]"}) noRdns := parser.Flag("n", "no-rdns", &argparse.Options{Help: "Do not resolve IP addresses to their domain names"}) alwaysRdns := parser.Flag("a", "always-rdns", &argparse.Options{Help: "Always resolve IP addresses to their domain names"}) routePath := parser.Flag("P", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"}) diff --git a/go.mod b/go.mod index b37be71..16c9ceb 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.20 require ( github.com/akamensky/argparse v1.4.0 github.com/google/gopacket v1.1.19 + github.com/oschwald/maxminddb-golang v1.10.0 github.com/spf13/viper v1.15.0 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 golang.org/x/net v0.7.0 diff --git a/go.sum b/go.sum index 2d2cece..7024ea1 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg= +github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/ipgeo/ipgeo.go b/ipgeo/ipgeo.go index 532c86d..3aca36d 100644 --- a/ipgeo/ipgeo.go +++ b/ipgeo/ipgeo.go @@ -45,6 +45,8 @@ func GetSource(s string) Source { return IPInfo case "IP2REGION": return IP2Region + case "IPINFOLOCAL": + return IPInfoLocal default: return LeoIP } diff --git a/ipgeo/ipinfo.go b/ipgeo/ipinfo.go index 4433248..746b078 100644 --- a/ipgeo/ipinfo.go +++ b/ipgeo/ipinfo.go @@ -3,6 +3,7 @@ package ipgeo import ( "io/ioutil" "net/http" + "strings" "github.com/tidwall/gjson" ) @@ -21,13 +22,13 @@ func IPInfo(ip string) (*IPGeoData, error) { res := gjson.ParseBytes(body) var country string - + country = res.Get("country").String() if res.Get("country").String() == "HK" || res.Get("country").String() == "TW" { country = "CN" } return &IPGeoData{ - Asnumber: res.Get("asn").Get("asn").String(), + Asnumber: strings.Fields(strings.TrimPrefix(res.Get("org").String(), "AS"))[0], Country: country, City: res.Get("city").String(), Prov: res.Get("region").String(), diff --git a/ipgeo/ipinfoLocal.go b/ipgeo/ipinfoLocal.go new file mode 100644 index 0000000..a3d75c0 --- /dev/null +++ b/ipgeo/ipinfoLocal.go @@ -0,0 +1,52 @@ +package ipgeo + +import ( + "errors" + "github.com/oschwald/maxminddb-golang" + "net" + "os" + "strings" +) + +const ( + ipinfoDataBasePath = "./ipinfoLocal.mmdb" +) + +func IPInfoLocal(ip string) (*IPGeoData, error) { + if _, err := os.Stat(ipinfoDataBasePath); os.IsNotExist(err) { + panic("Cannot find ipinfoLocal.mmdb") + } + region, err := maxminddb.Open(ipinfoDataBasePath) + if err != nil { + panic("Cannot find ipinfoLocal.mmdb") + } + defer func(region *maxminddb.Reader) { + err := region.Close() + if err != nil { + panic(err) + } + }(region) + var record interface{} + searchErr := region.Lookup(net.ParseIP(ip), &record) + if searchErr != nil { + return &IPGeoData{}, errors.New("no results") + } + recordMap := record.(map[string]interface{}) + country_name := recordMap["country_name"].(string) + prov := "" + if recordMap["country"].(string) == "HK" { + country_name = "China" + prov = "Hong Kong" + } + if recordMap["country"].(string) == "TW" { + country_name = "China" + prov = "Taiwan" + } + return &IPGeoData{ + Asnumber: strings.TrimPrefix(recordMap["asn"].(string), "AS"), + Country: country_name, + City: "", + Prov: prov, + Owner: recordMap["as_name"].(string), + }, nil +} From 60a4454802c445d37862889ad29b8e262a90a7c7 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:56:25 +0800 Subject: [PATCH 07/13] Update README --- README.md | 5 ++++- README_zh_CN.md | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7630485..542c332 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,10 @@ nexttrace --route-path www.time.com.my ```bash # You can specify the IP database by yourself [IP-API.com here], if not specified, LeoMoeAPI will be used nexttrace --data-provider ip-api.com -## Note that the `ipinfo` and `IPInsight` API needs users to purchase services from them. If necessary, you can clone this project, add the token provided by `ipinfo` or `IPInsight` and compile it yourself +## Note that the `ipinfo` and `IPInsight` API needs users to purchase services from them. +## If necessary, you can clone this project, add the token provided by `ipinfo` or `IPInsight` and compile it yourself +## Note For the offline database IPInfoLocal, please download it yourself to the same directory as NextTrace and rename it to ipinfoLocal.mmdb. +## For the offline database Ip2region, you can download it manually to the same directory as NextTrace and rename it to ip2region.db, or let NextTrace download it automatically. ## Fill the token to: ipgeo/tokens.go ## Please be aware: Due to the serious abuse of IP.SB, you will often be not able to query IP data from this source ## IP-API.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes. diff --git a/README_zh_CN.md b/README_zh_CN.md index a94ce13..c26b475 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -146,9 +146,10 @@ nexttrace --route-path www.time.com.my ```bash # 可以自行指定IP数据库[此处为IP-API.com],不指定则默认为LeoMoeAPI nexttrace --data-provider ip-api.com -## 特别的:其中 `ipinfo` 和 `IPInsight` API 需要从这些服务商自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 +## 特别的: 其中 `ipinfo` 和 `IPInsight` API 需要从这些服务商自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 ## TOKEN填写路径:ipgeo/tokens.go -## 特别的:对于 `Ip2region`, `IPInfoLocal` +## 特别的: 对于离线库`IPInfoLocal`,请自行下载到与NextTrace同目录下,并命名为`ipinfoLocal.mmdb` +## 对于离线库`Ip2region`可NextTrace自动下载,也可自行下载到与NextTrace同目录下,并命名为`ip2region.db` ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 ## IP-API.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 From fe0fce07ece722e8d855d44bcaa43cec2987d238 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 19:11:26 +0800 Subject: [PATCH 08/13] Update README --- README.md | 2 +- README_zh_CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 542c332..68c2c25 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ nexttrace --route-path www.time.com.my nexttrace --data-provider ip-api.com ## Note that the `ipinfo` and `IPInsight` API needs users to purchase services from them. ## If necessary, you can clone this project, add the token provided by `ipinfo` or `IPInsight` and compile it yourself -## Note For the offline database IPInfoLocal, please download it yourself to the same directory as NextTrace and rename it to ipinfoLocal.mmdb. +## Note For the offline database IPInfoLocal, please download it yourself to the same directory as NextTrace and rename it to ipinfoLocal.mmdb. (You can download it from here: https://ipinfo.io/signup?ref=free-database-downloads) ## For the offline database Ip2region, you can download it manually to the same directory as NextTrace and rename it to ip2region.db, or let NextTrace download it automatically. ## Fill the token to: ipgeo/tokens.go ## Please be aware: Due to the serious abuse of IP.SB, you will often be not able to query IP data from this source diff --git a/README_zh_CN.md b/README_zh_CN.md index c26b475..9c71641 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -148,7 +148,7 @@ nexttrace --route-path www.time.com.my nexttrace --data-provider ip-api.com ## 特别的: 其中 `ipinfo` 和 `IPInsight` API 需要从这些服务商自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 ## TOKEN填写路径:ipgeo/tokens.go -## 特别的: 对于离线库`IPInfoLocal`,请自行下载到与NextTrace同目录下,并命名为`ipinfoLocal.mmdb` +## 特别的: 对于离线库`IPInfoLocal`,请自行下载到与NextTrace同目录下,并命名为`ipinfoLocal.mmdb` (可以从这里下载:https://ipinfo.io/signup?ref=free-database-downloads) ## 对于离线库`Ip2region`可NextTrace自动下载,也可自行下载到与NextTrace同目录下,并命名为`ip2region.db` ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 From dc735b0f97cf44486f0ffed4c3d4a97bd6f56b36 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 21:21:43 +0800 Subject: [PATCH 09/13] =?UTF-8?q?Update=20ipinfo.go=20=E8=BD=AC=E6=8D=A2IS?= =?UTF-8?q?O3166?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ipgeo/ipinfo.go | 253 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) diff --git a/ipgeo/ipinfo.go b/ipgeo/ipinfo.go index 746b078..483b07d 100644 --- a/ipgeo/ipinfo.go +++ b/ipgeo/ipinfo.go @@ -26,6 +26,259 @@ func IPInfo(ip string) (*IPGeoData, error) { if res.Get("country").String() == "HK" || res.Get("country").String() == "TW" { country = "CN" } + // ISO-3166 转换 + var countryMap = map[string]string{ + "AF": "Afghanistan", + "AX": "Åland Islands", + "AL": "Albania", + "DZ": "Algeria", + "AS": "American Samoa", + "AD": "Andorra", + "AO": "Angola", + "AI": "Anguilla", + "AQ": "Antarctica", + "AG": "Antigua and Barbuda", + "AR": "Argentina", + "AM": "Armenia", + "AW": "Aruba", + "AU": "Australia", + "AT": "Austria", + "AZ": "Azerbaijan", + "BH": "Bahrain", + "BS": "Bahamas", + "BD": "Bangladesh", + "BB": "Barbados", + "BY": "Belarus", + "BE": "Belgium", + "BZ": "Belize", + "BJ": "Benin", + "BM": "Bermuda", + "BT": "Bhutan", + "BO": "Bolivia", + "BQ": "Bonaire", + "BA": "Bosnia and Herzegovina", + "BW": "Botswana", + "BV": "Bouvet Island", + "BR": "Brazil", + "IO": "British Indian Ocean Territory", + "BN": "Brunei Darussalam", + "BG": "Bulgaria", + "BF": "Burkina Faso", + "BI": "Burundi", + "KH": "Cambodia", + "CM": "Cameroon", + "CA": "Canada", + "CV": "Cape Verde", + "KY": "Cayman Islands", + "CF": "Central African Republic", + "TD": "Chad", + "CL": "Chile", + "CN": "China", + "CX": "Christmas Island", + "CC": "Cocos (Keeling) Islands", + "CO": "Colombia", + "KM": "Comoros", + "CG": "Congo", + "CD": "Congo", + "CK": "Cook Islands", + "CR": "Costa Rica", + "CI": "Côte d'Ivoire", + "HR": "Croatia", + "CU": "Cuba", + "CW": "Curaçao", + "CY": "Cyprus", + "CZ": "Czech Republic", + "DK": "Denmark", + "DJ": "Djibouti", + "DM": "Dominica", + "DO": "Dominican Republic", + "EC": "Ecuador", + "EG": "Egypt", + "SV": "El Salvador", + "GQ": "Equatorial Guinea", + "ER": "Eritrea", + "EE": "Estonia", + "ET": "Ethiopia", + "FK": "Falkland Islands (Malvinas)", + "FO": "Faroe Islands", + "FJ": "Fiji", + "FI": "Finland", + "FR": "France", + "GF": "French Guiana", + "PF": "French Polynesia", + "TF": "French Southern Territories", + "GA": "Gabon", + "GM": "Gambia", + "GE": "Georgia", + "DE": "Germany", + "GH": "Ghana", + "GI": "Gibraltar", + "GR": "Greece", + "GL": "Greenland", + "GD": "Grenada", + "GP": "Guadeloupe", + "GU": "Guam", + "GT": "Guatemala", + "GG": "Guernsey", + "GN": "Guinea", + "GW": "Guinea-Bissau", + "GY": "Guyana", + "HT": "Haiti", + "HM": "Heard Island and McDonald Islands", + "VA": "Holy See (Vatican City State)", + "HN": "Honduras", + "HK": "Hong Kong", + "HU": "Hungary", + "IS": "Iceland", + "IN": "India", + "ID": "Indonesia", + "IR": "Iran", + "IQ": "Iraq", + "IE": "Ireland", + "IM": "Isle of Man", + "IL": "Israel", + "IT": "Italy", + "JM": "Jamaica", + "JP": "Japan", + "JE": "Jersey", + "JO": "Jordan", + "KZ": "Kazakhstan", + "KE": "Kenya", + "KI": "Kiribati", + "KP": "Korea", + "KR": "Korea", + "KW": "Kuwait", + "KG": "Kyrgyzstan", + "LA": "Lao People's Democratic Republic", + "LV": "Latvia", + "LB": "Lebanon", + "LS": "Lesotho", + "LR": "Liberia", + "LY": "Libya", + "LI": "Liechtenstein", + "LT": "Lithuania", + "LU": "Luxembourg", + "MO": "Macao", + "MK": "Macedonia", + "MG": "Madagascar", + "MW": "Malawi", + "MY": "Malaysia", + "MV": "Maldives", + "ML": "Mali", + "MT": "Malta", + "MH": "Marshall Islands", + "MQ": "Martinique", + "MR": "Mauritania", + "MU": "Mauritius", + "YT": "Mayotte", + "MX": "Mexico", + "FM": "Micronesia", + "MD": "Moldova", + "MC": "Monaco", + "MN": "Mongolia", + "ME": "Montenegro", + "MS": "Montserrat", + "MA": "Morocco", + "MZ": "Mozambique", + "MM": "Myanmar", + "NA": "Namibia", + "NR": "Nauru", + "NP": "Nepal", + "NL": "Netherlands", + "NC": "New Caledonia", + "NZ": "New Zealand", + "NI": "Nicaragua", + "NE": "Niger", + "NG": "Nigeria", + "NU": "Niue", + "NF": "Norfolk Island", + "MP": "Northern Mariana Islands", + "NO": "Norway", + "OM": "Oman", + "PK": "Pakistan", + "PW": "Palau", + "PS": "Palestine", + "PA": "Panama", + "PG": "Papua New Guinea", + "PY": "Paraguay", + "PE": "Peru", + "PH": "Philippines", + "PN": "Pitcairn", + "PL": "Poland", + "PT": "Portugal", + "PR": "Puerto Rico", + "QA": "Qatar", + "RE": "Réunion", + "RO": "Romania", + "RU": "Russian Federation", + "RW": "Rwanda", + "BL": "Saint Barthélemy", + "SH": "Saint Helena", + "KN": "Saint Kitts and Nevis", + "LC": "Saint Lucia", + "MF": "Saint Martin (French part)", + "PM": "Saint Pierre and Miquelon", + "VC": "Saint Vincent and the Grenadines", + "WS": "Samoa", + "SM": "San Marino", + "ST": "Sao Tome and Principe", + "SA": "Saudi Arabia", + "SN": "Senegal", + "RS": "Serbia", + "SC": "Seychelles", + "SL": "Sierra Leone", + "SG": "Singapore", + "SX": "Sint Maarten (Dutch part)", + "SK": "Slovakia", + "SI": "Slovenia", + "SB": "Solomon Islands", + "SO": "Somalia", + "ZA": "South Africa", + "GS": "South Georgia and the South Sandwich Islands", + "SS": "South Sudan", + "ES": "Spain", + "LK": "Sri Lanka", + "SD": "Sudan", + "SR": "Suriname", + "SJ": "Svalbard and Jan Mayen", + "SZ": "Swaziland", + "SE": "Sweden", + "CH": "Switzerland", + "SY": "Syrian Arab Republic", + "TW": "Taiwan", + "TJ": "Tajikistan", + "TZ": "Tanzania", + "TH": "Thailand", + "TL": "Timor-Leste", + "TG": "Togo", + "TK": "Tokelau", + "TO": "Tonga", + "TT": "Trinidad and Tobago", + "TN": "Tunisia", + "TR": "Turkey", + "TM": "Turkmenistan", + "TC": "Turks and Caicos Islands", + "TV": "Tuvalu", + "UG": "Uganda", + "UA": "Ukraine", + "AE": "United Arab Emirates", + "GB": "United Kingdom", + "US": "United States of America", + "UM": "United States Minor Outlying Islands", + "UY": "Uruguay", + "UZ": "Uzbekistan", + "VU": "Vanuatu", + "VE": "Venezuela", + "VN": "Viet Nam", + "VG": "Virgin Islands", + "VI": "Virgin Islands", + "WF": "Wallis and Futuna", + "EH": "Western Sahara", + "YE": "Yemen", + "ZM": "Zambia", + "ZW": "Zimbabwe", + } + country = countryMap[country] return &IPGeoData{ Asnumber: strings.Fields(strings.TrimPrefix(res.Get("org").String(), "AS"))[0], From 362317e95e633a5d5079c92dd57c49a6a7247a6c Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 21:47:59 +0800 Subject: [PATCH 10/13] format --- cmd/cmd.go | 5 ++- config/viper.go | 10 ++++- dn42/geofeed.go | 7 +++- dn42/ptr.go | 7 +++- fast_trace/fast_trace ipv6.go | 17 +++++++-- fast_trace/fast_trace.go | 24 +++++++++--- fast_trace/fast_trace_test.go | 5 ++- ipgeo/ip2region.go | 14 ++++++- ipgeo/ipapicom.go | 4 +- ipgeo/ipfilter.go | 2 +- ipgeo/ipinfo.go | 11 ++++-- ipgeo/ipinsight.go | 4 +- ipgeo/ipsb.go | 4 +- ipgeo/leo.go | 9 +++-- printer/basic.go | 20 ++++++++-- printer/realtime_printer.go | 56 ++++++++++++++++++++++------ printer/realtime_printer_router.go | 60 ++++++++++++++++++++++++------ reporter/reporter.go | 2 +- trace/icmp_ipv4.go | 24 ++++++++++-- trace/icmp_ipv6.go | 24 ++++++++++-- trace/tcp_ipv4.go | 19 ++++++++-- trace/tcp_ipv6.go | 25 +++++++++++-- trace/udp.go | 19 ++++++++-- tracelog/log.go | 7 +++- tracemap/tracemap.go | 7 +++- util/util.go | 26 ++++++++++--- 26 files changed, 328 insertions(+), 84 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 02b2a9e..688fca1 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -145,7 +145,10 @@ func Excute() { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - w.Conn.Close() + err := w.Conn.Close() + if err != nil { + return + } }() } diff --git a/config/viper.go b/config/viper.go index 8f31cce..3801e0b 100644 --- a/config/viper.go +++ b/config/viper.go @@ -27,8 +27,14 @@ func InitConfig() { err := viper.ReadInConfig() // Find and read the config file if err != nil { // Handle errors reading the config file fmt.Println("未能找到配置文件,我们将在您的运行目录为您创建 nt_config.yaml 默认配置") - viper.SafeWriteConfigAs("./nt_config.yaml") + err := viper.SafeWriteConfigAs("./nt_config.yaml") + if err != nil { + return + } } - viper.ReadInConfig() + err = viper.ReadInConfig() + if err != nil { + return + } } diff --git a/dn42/geofeed.go b/dn42/geofeed.go index 7b183f6..118de38 100644 --- a/dn42/geofeed.go +++ b/dn42/geofeed.go @@ -37,7 +37,12 @@ func ReadGeoFeed() ([]GeoFeedRow, error) { if err != nil { return nil, err } - defer f.Close() + defer func(f *os.File) { + err := f.Close() + if err != nil { + panic(err) + } + }(f) r := csv.NewReader(f) rows, err := r.ReadAll() diff --git a/dn42/ptr.go b/dn42/ptr.go index c470ff9..834d029 100644 --- a/dn42/ptr.go +++ b/dn42/ptr.go @@ -36,7 +36,12 @@ func FindPtrRecord(ptr string) (PtrRow, error) { if err != nil { return PtrRow{}, err } - defer f.Close() + defer func(f *os.File) { + err := f.Close() + if err != nil { + panic(err) + } + }(f) r := csv.NewReader(f) rows, err := r.ReadAll() diff --git a/fast_trace/fast_trace ipv6.go b/fast_trace/fast_trace ipv6.go index 485de17..e3f92e1 100644 --- a/fast_trace/fast_trace ipv6.go +++ b/fast_trace/fast_trace ipv6.go @@ -20,7 +20,12 @@ func (f *FastTracer) tracert_v6(location string, ispCollection ISPCollection) { if err != nil { return } - defer fp.Close() + defer func(fp *os.File) { + err := fp.Close() + if err != nil { + log.Fatal(err) + } + }(fp) log.SetOutput(fp) log.SetFlags(0) @@ -100,7 +105,10 @@ func FastTestv6(tm bool, outEnable bool) { fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网") fmt.Print("请选择选项:") - fmt.Scanln(&c) + _, err := fmt.Scanln(&c) + if err != nil { + return + } ft := FastTracer{} @@ -109,7 +117,10 @@ func FastTestv6(tm bool, outEnable bool) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - w.Conn.Close() + err := w.Conn.Close() + if err != nil { + return + } }() if !tm { diff --git a/fast_trace/fast_trace.go b/fast_trace/fast_trace.go index e7d71ec..e2a569f 100644 --- a/fast_trace/fast_trace.go +++ b/fast_trace/fast_trace.go @@ -19,14 +19,19 @@ type FastTracer struct { TracerouteMethod trace.Method } -var oe bool = false +var oe = false func (f *FastTracer) tracert(location string, ispCollection ISPCollection) { fp, err := os.OpenFile("/tmp/trace.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm) if err != nil { return } - defer fp.Close() + defer func(fp *os.File) { + err := fp.Close() + if err != nil { + log.Fatal(err) + } + }(fp) log.SetOutput(fp) log.SetFlags(0) @@ -114,7 +119,10 @@ func FastTest(tm bool, outEnable bool) { fmt.Println("Hi,欢迎使用 Fast Trace 功能,请注意 Fast Trace 功能只适合新手使用\n因为国内网络复杂,我们设置的测试目标有限,建议普通用户自测以获得更加精准的路由情况") fmt.Println("请您选择要测试的 IP 类型\n1. IPv4\n2. IPv6") fmt.Print("请选择选项:") - fmt.Scanln(&c) + _, err := fmt.Scanln(&c) + if err != nil { + return + } if c == "2" { FastTestv6(tm, outEnable) return @@ -122,7 +130,10 @@ func FastTest(tm bool, outEnable bool) { fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网") fmt.Print("请选择选项:") - fmt.Scanln(&c) + _, err = fmt.Scanln(&c) + if err != nil { + return + } ft := FastTracer{} @@ -131,7 +142,10 @@ func FastTest(tm bool, outEnable bool) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - w.Conn.Close() + err := w.Conn.Close() + if err != nil { + return + } }() if !tm { diff --git a/fast_trace/fast_trace_test.go b/fast_trace/fast_trace_test.go index 285c3b8..ae514d5 100644 --- a/fast_trace/fast_trace_test.go +++ b/fast_trace/fast_trace_test.go @@ -17,7 +17,10 @@ func TestTCPTrace(t *testing.T) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - w.Conn.Close() + err := w.Conn.Close() + if err != nil { + return + } }() ft.TracerouteMethod = trace.TCPTrace ft.testCM() diff --git a/ipgeo/ip2region.go b/ipgeo/ip2region.go index 41ae0c0..1f9e3e9 100644 --- a/ipgeo/ip2region.go +++ b/ipgeo/ip2region.go @@ -22,14 +22,24 @@ func downloadDataBase() error { if err != nil { return err } - defer resp.Body.Close() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + panic(err) + } + }(resp.Body) // Create the file out, err := os.Create(ipDataBasePath) if err != nil { return err } - defer out.Close() + defer func(out *os.File) { + err := out.Close() + if err != nil { + panic(err) + } + }(out) // Write the body to file _, err = io.Copy(out, resp.Body) diff --git a/ipgeo/ipapicom.go b/ipgeo/ipapicom.go index 310d7a8..f2809a0 100644 --- a/ipgeo/ipapicom.go +++ b/ipgeo/ipapicom.go @@ -2,7 +2,7 @@ package ipgeo import ( "errors" - "io/ioutil" + "io" "log" "net/http" "regexp" @@ -24,7 +24,7 @@ func IPApiCom(ip string) (*IPGeoData, error) { log.Println("ip-api.com 请求超时(2s),请切换其他API使用") return nil, err } - body, _ := ioutil.ReadAll(content.Body) + body, _ := io.ReadAll(content.Body) res := gjson.ParseBytes(body) if res.Get("status").String() != "success" { diff --git a/ipgeo/ipfilter.go b/ipgeo/ipfilter.go index 6da1e3f..b7aa5b1 100644 --- a/ipgeo/ipfilter.go +++ b/ipgeo/ipfilter.go @@ -13,7 +13,7 @@ func cidrRangeContains(cidrRange string, checkIP string) bool { return ipNet.Contains(secondIP) } -// 被选到的返回 geodata, true 否则返回 nil, false +// Filter 被选到的返回 geodata, true 否则返回 nil, false func Filter(ip string) (*IPGeoData, bool) { //geodata := &IPGeoData{} asn := "" diff --git a/ipgeo/ipinfo.go b/ipgeo/ipinfo.go index 483b07d..bfb26ac 100644 --- a/ipgeo/ipinfo.go +++ b/ipgeo/ipinfo.go @@ -1,7 +1,7 @@ package ipgeo import ( - "io/ioutil" + "io" "net/http" "strings" @@ -13,8 +13,13 @@ func IPInfo(ip string) (*IPGeoData, error) { if err != nil { return nil, err } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + panic(err) + } + }(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/ipgeo/ipinsight.go b/ipgeo/ipinsight.go index d43b4f5..ea62d2d 100644 --- a/ipgeo/ipinsight.go +++ b/ipgeo/ipinsight.go @@ -1,7 +1,7 @@ package ipgeo import ( - "io/ioutil" + "io" "net/http" "github.com/tidwall/gjson" @@ -12,7 +12,7 @@ func IPInSight(ip string) (*IPGeoData, error) { if err != nil { return nil, err } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/ipgeo/ipsb.go b/ipgeo/ipsb.go index cf79470..368f380 100644 --- a/ipgeo/ipsb.go +++ b/ipgeo/ipsb.go @@ -1,7 +1,7 @@ package ipgeo import ( - "io/ioutil" + "io" "log" "net/http" "os" @@ -24,7 +24,7 @@ func IPSB(ip string) (*IPGeoData, error) { log.Println("api.ip.sb 请求超时(2s),请切换其他API使用") return nil, err } - body, _ := ioutil.ReadAll(content.Body) + body, _ := io.ReadAll(content.Body) res := gjson.ParseBytes(body) if res.Get("country").String() == "" { diff --git a/ipgeo/leo.go b/ipgeo/leo.go index 9d5f309..0f9f020 100644 --- a/ipgeo/leo.go +++ b/ipgeo/leo.go @@ -19,7 +19,7 @@ import ( * 运作模型可以理解为一个 Node 一直在等待数据,当获得一个新的任务后,转交给下一个协程,不再关注这个 Node 的下一步处理过程,并且回到空闲状态继续等待新的任务 ***/ -// IP 查询池 map - ip - ip channel +// IPPool IP 查询池 map - ip - ip channel type IPPool struct { pool map[string]chan IPGeoData poolMux sync.Mutex @@ -48,14 +48,17 @@ func receiveParse() { // json解析 -> data res := gjson.Parse(data) // 根据返回的IP信息,发送给对应等待回复的IP通道上 - var domain string = res.Get("domain").String() + var domain = res.Get("domain").String() if res.Get("domain").String() == "" { domain = res.Get("owner").String() } m := make(map[string][]string) - json.Unmarshal([]byte(res.Get("router").String()), &m) + err := json.Unmarshal([]byte(res.Get("router").String()), &m) + if err != nil { + return + } lat, _ := strconv.ParseFloat(res.Get("lat").String(), 32) lng, _ := strconv.ParseFloat(res.Get("lng").String(), 32) diff --git a/printer/basic.go b/printer/basic.go index d3f4a8f..75d2110 100644 --- a/printer/basic.go +++ b/printer/basic.go @@ -12,16 +12,19 @@ var buildDate = "" var commitID = "" func Version() { - fmt.Fprintf(color.Output, "%s %s %s %s\n", + _, err := fmt.Fprintf(color.Output, "%s %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", "NextTrace"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", version), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", buildDate), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", commitID), ) + if err != nil { + panic(err) + } } func CopyRight() { - fmt.Fprintf(color.Output, "\n%s\n%s\n%s %s\n\n%s\n%s %s\n%s %s\n%s %s\n\n%s\n%s\n%s %s\n\n", + _, err := fmt.Fprintf(color.Output, "\n%s\n%s\n%s %s\n\n%s\n%s %s\n%s %s\n%s %s\n\n%s\n%s\n%s %s\n\n", color.New(color.FgCyan, color.Bold).Sprintf("%s", "NextTrace CopyRight"), color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Project Creator"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Leo"), @@ -38,27 +41,36 @@ func CopyRight() { color.New(color.FgWhite, color.Bold).Sprintf("%s", "zhshch"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "zhshch@athorx.com"), ) + if err != nil { + return + } MoeQingOrgCopyRight() PluginCopyRight() } func MoeQingOrgCopyRight() { - fmt.Fprintf(color.Output, "%s\n%s %s\n%s %s\n\n", + _, err := fmt.Fprintf(color.Output, "%s\n%s %s\n%s %s\n\n", color.New(color.FgHiYellow, color.Bold).Sprintf("%s", "MoeQing Network"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "YekongTAT"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "yekongtat@gmail.com"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Haima"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "haima@peers.cloud"), ) + if err != nil { + return + } } func PluginCopyRight() { - fmt.Fprintf(color.Output, "%s\n%s %s\n\n", + _, err := fmt.Fprintf(color.Output, "%s\n%s %s\n\n", color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Map Plugin Author"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Tso"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "tsosunchia@gmail.com"), ) + if err != nil { + return + } } func PrintTraceRouteNav(ip net.IP, domain string, dataOrigin string) { diff --git a/printer/realtime_printer.go b/printer/realtime_printer.go index 23bbbde..bc9e66f 100644 --- a/printer/realtime_printer.go +++ b/printer/realtime_printer.go @@ -39,9 +39,12 @@ func RealtimePrinter(res *trace.Result, ttl int) { } if latestIP == "" { - fmt.Fprintf(color.Output, "%s\n", + _, err := fmt.Fprintf(color.Output, "%s\n", color.New(color.FgWhite, color.Bold).Sprintf("*"), ) + if err != nil { + return + } return } @@ -51,13 +54,19 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Printf("%4s", "") } if net.ParseIP(ip).To4() == nil { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip), ) + if err != nil { + return + } } i, _ := strconv.Atoi(v[0]) @@ -77,9 +86,15 @@ func RealtimePrinter(res *trace.Result, ttl int) { case res.Hops[ttl][i].Geo.Whois == "CMIN2-NET": fallthrough case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."): - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + if err != nil { + return + } default: - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + if err != nil { + return + } } } else { @@ -115,9 +130,15 @@ func RealtimePrinter(res *trace.Result, ttl int) { case whoisFormat[0] == "[CMIN2-NET]": fallthrough case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."): - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("%-16s", whoisFormat[0])) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("%-16s", whoisFormat[0])) + if err != nil { + return + } default: - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) + if err != nil { + return + } } } @@ -147,8 +168,7 @@ func RealtimePrinter(res *trace.Result, ttl int) { } if net.ParseIP(ip).To4() != nil { - - fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -156,8 +176,11 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -165,17 +188,26 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname), ) + if err != nil { + return + } } for j := 1; j < len(v); j++ { if len(v) == 2 || j == 1 { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, " / %s", + _, err := fmt.Fprintf(color.Output, " / %s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) + if err != nil { + return + } } } fmt.Println() diff --git a/printer/realtime_printer_router.go b/printer/realtime_printer_router.go index 18007bb..215a414 100644 --- a/printer/realtime_printer_router.go +++ b/printer/realtime_printer_router.go @@ -39,9 +39,12 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { } if latestIP == "" { - fmt.Fprintf(color.Output, "%s\n", + _, err := fmt.Fprintf(color.Output, "%s\n", color.New(color.FgWhite, color.Bold).Sprintf("*"), ) + if err != nil { + return + } return } @@ -51,19 +54,28 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Printf("%4s", "") } if net.ParseIP(ip).To4() == nil { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip), ) + if err != nil { + return + } } i, _ := strconv.Atoi(v[0]) if res.Hops[ttl][i].Geo.Asnumber != "" { - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) + if err != nil { + return + } } else { fmt.Printf(" %-8s", "*") } @@ -77,7 +89,10 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { if whoisFormat[0] != "" { whoisFormat[0] = "[" + whoisFormat[0] + "]" } - fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) + _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) + if err != nil { + return + } } if res.Hops[ttl][i].Geo.Country == "" { @@ -86,7 +101,7 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { if net.ParseIP(ip).To4() != nil { - fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -94,8 +109,11 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -103,29 +121,41 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname), ) + if err != nil { + return + } } for j := 1; j < len(v); j++ { if len(v) == 2 || j == 1 { - fmt.Fprintf(color.Output, "%s", + _, err := fmt.Fprintf(color.Output, "%s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, " / %s", + _, err := fmt.Fprintf(color.Output, " / %s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) + if err != nil { + return + } } } i = 0 fmt.Println() if res.Hops[ttl][i].Geo != nil && !blockDisplay { - fmt.Fprintf(color.Output, "%s %s %s %s %s\n", + _, err := fmt.Fprintf(color.Output, "%s %s %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("-"), color.New(color.FgHiYellow, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prefix), color.New(color.FgWhite, color.Bold).Sprintf("路由表"), color.New(color.FgHiCyan, color.Bold).Sprintf("Beta"), color.New(color.FgWhite, color.Bold).Sprintf("-"), ) + if err != nil { + return + } GetRouter(&res.Hops[ttl][i].Geo.Router, "AS"+res.Hops[ttl][i].Geo.Asnumber) } blockDisplay = true @@ -136,16 +166,22 @@ func GetRouter(r *map[string][]string, node string) { routeMap := *r for _, v := range routeMap[node] { if len(routeMap[v]) != 0 { - fmt.Fprintf(color.Output, " %s %s %s\n", + _, err := fmt.Fprintf(color.Output, " %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", routeMap[v][0]), color.New(color.FgWhite, color.Bold).Sprintf("%s", v), color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node), ) + if err != nil { + return + } } else { - fmt.Fprintf(color.Output, " %s %s\n", + _, err := fmt.Fprintf(color.Output, " %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", v), color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node), ) + if err != nil { + return + } } } diff --git a/reporter/reporter.go b/reporter/reporter.go index 26b5e6a..2ea348b 100644 --- a/reporter/reporter.go +++ b/reporter/reporter.go @@ -45,7 +45,7 @@ func experimentTag() { func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData, ttl uint16) { - var success bool = true + var success = true defer r.wg.Done() diff --git a/trace/icmp_ipv4.go b/trace/icmp_ipv4.go index 6e5d288..8397b8b 100644 --- a/trace/icmp_ipv4.go +++ b/trace/icmp_ipv4.go @@ -66,7 +66,12 @@ func (t *ICMPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer t.icmpListen.Close() + defer func(icmpListen net.PacketConn) { + err := icmpListen.Close() + if err != nil { + log.Println(err) + } + }(t.icmpListen) var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -85,7 +90,12 @@ func (t *ICMPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go t.send(ttl) + go func() { + err := t.send(ttl) + if err != nil { + log.Println(err) + } + }() <-time.After(time.Millisecond * time.Duration(t.Config.PacketInterval)) } <-time.After(time.Millisecond * time.Duration(t.Config.TTLInterval)) @@ -258,7 +268,10 @@ func (t *ICMPTracer) send(ttl int) error { }, } - ipv4.NewPacketConn(t.icmpListen).SetTTL(ttl) + err := ipv4.NewPacketConn(t.icmpListen).SetTTL(ttl) + if err != nil { + return err + } wb, err := icmpHeader.Marshal(nil) if err != nil { @@ -298,7 +311,10 @@ func (t *ICMPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - h.fetchIPData(t.Config) + err := h.fetchIPData(t.Config) + if err != nil { + return err + } t.res.add(h) case <-time.After(t.Timeout): diff --git a/trace/icmp_ipv6.go b/trace/icmp_ipv6.go index 8454e91..7501314 100644 --- a/trace/icmp_ipv6.go +++ b/trace/icmp_ipv6.go @@ -67,7 +67,12 @@ func (t *ICMPTracerv6) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer t.icmpListen.Close() + defer func(icmpListen net.PacketConn) { + err := icmpListen.Close() + if err != nil { + panic(err) + } + }(t.icmpListen) var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -86,7 +91,12 @@ func (t *ICMPTracerv6) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go t.send(ttl) + go func() { + err := t.send(ttl) + if err != nil { + log.Println(err) + } + }() <-time.After(time.Millisecond * time.Duration(t.Config.PacketInterval)) } <-time.After(time.Millisecond * time.Duration(t.Config.TTLInterval)) @@ -258,7 +268,10 @@ func (t *ICMPTracerv6) send(ttl int) error { p := ipv6.NewPacketConn(t.icmpListen) icmpHeader.Body.(*icmp.Echo).Seq = ttl - p.SetHopLimit(ttl) + err := p.SetHopLimit(ttl) + if err != nil { + return err + } wb, err := icmpHeader.Marshal(nil) if err != nil { @@ -298,7 +311,10 @@ func (t *ICMPTracerv6) send(ttl int) error { h.TTL = ttl h.RTT = rtt - h.fetchIPData(t.Config) + err := h.fetchIPData(t.Config) + if err != nil { + return err + } t.res.add(h) diff --git a/trace/tcp_ipv4.go b/trace/tcp_ipv4.go index e1f386f..f2f4dec 100644 --- a/trace/tcp_ipv4.go +++ b/trace/tcp_ipv4.go @@ -55,7 +55,12 @@ func (t *TCPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer t.icmp.Close() + defer func(icmp net.PacketConn) { + err := icmp.Close() + if err != nil { + panic(err) + } + }(t.icmp) var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -78,7 +83,12 @@ func (t *TCPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go t.send(ttl) + go func() { + err := t.send(ttl) + if err != nil { + log.Println(err) + } + }() } if t.RealtimePrinter != nil { @@ -285,7 +295,10 @@ func (t *TCPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - h.fetchIPData(t.Config) + err := h.fetchIPData(t.Config) + if err != nil { + return err + } t.res.add(h) diff --git a/trace/tcp_ipv6.go b/trace/tcp_ipv6.go index c0b2686..091e8cc 100644 --- a/trace/tcp_ipv6.go +++ b/trace/tcp_ipv6.go @@ -2,6 +2,7 @@ package trace import ( "encoding/binary" + "log" "math" "math/rand" "net" @@ -50,7 +51,12 @@ func (t *TCPTracerv6) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer t.icmp.Close() + defer func(icmp net.PacketConn) { + err := icmp.Close() + if err != nil { + log.Println(err) + } + }(t.icmp) var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -70,7 +76,12 @@ func (t *TCPTracerv6) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go t.send(ttl) + go func() { + err := t.send(ttl) + if err != nil { + log.Println(err) + } + }() } if t.RealtimePrinter != nil { // 对于实时模式,应该按照TTL进行并发请求 @@ -227,7 +238,10 @@ func (t *TCPTracerv6) send(ttl int) error { return err } - ipv6.NewPacketConn(t.tcp).SetHopLimit(ttl) + err = ipv6.NewPacketConn(t.tcp).SetHopLimit(ttl) + if err != nil { + return err + } if err != nil { return err } @@ -268,7 +282,10 @@ func (t *TCPTracerv6) send(ttl int) error { h.TTL = ttl h.RTT = rtt - h.fetchIPData(t.Config) + err := h.fetchIPData(t.Config) + if err != nil { + return err + } t.res.add(h) diff --git a/trace/udp.go b/trace/udp.go index 6277466..7afa2c6 100644 --- a/trace/udp.go +++ b/trace/udp.go @@ -41,7 +41,12 @@ func (t *UDPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer t.icmp.Close() + defer func(icmp net.PacketConn) { + err := icmp.Close() + if err != nil { + log.Println(err) + } + }(t.icmp) var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -59,7 +64,12 @@ func (t *UDPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go t.send(ttl) + go func() { + err := t.send(ttl) + if err != nil { + log.Println(err) + } + }() } if t.RealtimePrinter != nil { @@ -256,7 +266,10 @@ func (t *UDPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - h.fetchIPData(t.Config) + err := h.fetchIPData(t.Config) + if err != nil { + return err + } t.res.add(h) diff --git a/tracelog/log.go b/tracelog/log.go index 240dd24..2008be3 100644 --- a/tracelog/log.go +++ b/tracelog/log.go @@ -17,7 +17,12 @@ func RealtimePrinter(res *trace.Result, ttl int) { if err != nil { return } - defer f.Close() + defer func(f *os.File) { + err := f.Close() + if err != nil { + log.Fatal(err) + } + }(f) multiWriter := io.MultiWriter(os.Stdout, f) log.SetOutput(multiWriter) diff --git a/tracemap/tracemap.go b/tracemap/tracemap.go index e00a195..26a3f11 100644 --- a/tracemap/tracemap.go +++ b/tracemap/tracemap.go @@ -11,10 +11,13 @@ import ( func GetMapUrl(r string) { url := "https://api.leo.moe/tracemap/api" - resp, _ := http.Post(url, "application/json", strings.NewReader(string(r))) + resp, _ := http.Post(url, "application/json", strings.NewReader(r)) body, _ := io.ReadAll(resp.Body) - fmt.Fprintf(color.Output, "%s %s\n", + _, err := fmt.Fprintf(color.Output, "%s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", "MapTrace URL:"), color.New(color.FgBlue, color.Bold).Sprintf("%s", string(body)), ) + if err != nil { + return + } } diff --git a/util/util.go b/util/util.go index 1173859..957d278 100644 --- a/util/util.go +++ b/util/util.go @@ -10,7 +10,7 @@ import ( "github.com/fatih/color" ) -// get the local ip and port based on our destination ip +// LocalIPPort get the local ip and port based on our destination ip func LocalIPPort(dstip net.IP) (net.IP, int) { serverAddr, err := net.ResolveUDPAddr("udp", dstip.String()+":12345") if err != nil { @@ -20,7 +20,12 @@ func LocalIPPort(dstip net.IP) (net.IP, int) { // We don't actually connect to anything, but we can determine // based on our destination ip what source ip we should use. if con, err := net.DialUDP("udp", nil, serverAddr); err == nil { - defer con.Close() + defer func(con *net.UDPConn) { + err := con.Close() + if err != nil { + log.Fatal(err) + } + }(con) if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok { return udpaddr.IP, udpaddr.Port } @@ -37,7 +42,12 @@ func LocalIPPortv6(dstip net.IP) (net.IP, int) { // We don't actually connect to anything, but we can determine // based on our destination ip what source ip we should use. if con, err := net.DialUDP("udp", nil, serverAddr); err == nil { - defer con.Close() + defer func(con *net.UDPConn) { + err := con.Close() + if err != nil { + log.Fatal(err) + } + }(con) if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok { return udpaddr.IP, udpaddr.Port } @@ -88,14 +98,20 @@ func DomainLookUp(host string, ipv4Only bool, dotServer string) net.IP { } else { fmt.Println("Please Choose the IP You Want To TraceRoute") for i, ip := range ips { - fmt.Fprintf(color.Output, "%s %s\n", + _, err := fmt.Fprintf(color.Output, "%s %s\n", color.New(color.FgHiYellow, color.Bold).Sprintf("%d.", i), color.New(color.FgWhite, color.Bold).Sprintf("%s", ip), ) + if err != nil { + return nil + } } var index int fmt.Printf("Your Option: ") - fmt.Scanln(&index) + _, err := fmt.Scanln(&index) + if err != nil { + return nil + } if index >= len(ips) || index < 0 { fmt.Println("Your Option is invalid") os.Exit(3) From a95a741ce207be0dd5885f8c6f2393aa20a5e072 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Thu, 2 Mar 2023 22:12:34 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E5=A2=9E=E5=8A=A0scanf=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fast_trace/fast_trace ipv6.go | 2 +- fast_trace/fast_trace.go | 4 ++-- util/util.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fast_trace/fast_trace ipv6.go b/fast_trace/fast_trace ipv6.go index e3f92e1..8ecf446 100644 --- a/fast_trace/fast_trace ipv6.go +++ b/fast_trace/fast_trace ipv6.go @@ -107,7 +107,7 @@ func FastTestv6(tm bool, outEnable bool) { fmt.Print("请选择选项:") _, err := fmt.Scanln(&c) if err != nil { - return + c = "1" } ft := FastTracer{} diff --git a/fast_trace/fast_trace.go b/fast_trace/fast_trace.go index e2a569f..4284957 100644 --- a/fast_trace/fast_trace.go +++ b/fast_trace/fast_trace.go @@ -121,7 +121,7 @@ func FastTest(tm bool, outEnable bool) { fmt.Print("请选择选项:") _, err := fmt.Scanln(&c) if err != nil { - return + c = "1" } if c == "2" { FastTestv6(tm, outEnable) @@ -132,7 +132,7 @@ func FastTest(tm bool, outEnable bool) { fmt.Print("请选择选项:") _, err = fmt.Scanln(&c) if err != nil { - return + c = "1" } ft := FastTracer{} diff --git a/util/util.go b/util/util.go index 957d278..1cb14cc 100644 --- a/util/util.go +++ b/util/util.go @@ -110,7 +110,7 @@ func DomainLookUp(host string, ipv4Only bool, dotServer string) net.IP { fmt.Printf("Your Option: ") _, err := fmt.Scanln(&index) if err != nil { - return nil + index = 0 } if index >= len(ips) || index < 0 { fmt.Println("Your Option is invalid") From bdfba172d190bab272bc048d5a1493c6cb191f24 Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Fri, 3 Mar 2023 12:02:48 +0800 Subject: [PATCH 12/13] revert --- README.md | 11 ++++-- README_zh_CN.md | 10 +++-- cmd/cmd.go | 20 +++++----- dn42/geofeed.go | 7 +--- dn42/ptr.go | 7 +--- ipgeo/ip2region.go | 14 +------ ipgeo/ipinfo.go | 7 +--- ipgeo/leo.go | 5 +-- printer/basic.go | 20 ++-------- printer/realtime_printer.go | 56 ++++++---------------------- printer/realtime_printer_router.go | 60 ++++++------------------------ trace/icmp_ipv4.go | 24 ++---------- trace/icmp_ipv6.go | 24 ++---------- trace/tcp_ipv4.go | 19 ++-------- trace/tcp_ipv6.go | 25 ++----------- trace/udp.go | 19 ++-------- tracemap/tracemap.go | 5 +-- util/util.go | 19 ++-------- 18 files changed, 80 insertions(+), 272 deletions(-) diff --git a/README.md b/README.md index 68c2c25..a5b3497 100644 --- a/README.md +++ b/README.md @@ -127,13 +127,16 @@ nexttrace --route-path www.time.com.my ```bash # You can specify the IP database by yourself [IP-API.com here], if not specified, LeoMoeAPI will be used nexttrace --data-provider ip-api.com -## Note that the `ipinfo` and `IPInsight` API needs users to purchase services from them. -## If necessary, you can clone this project, add the token provided by `ipinfo` or `IPInsight` and compile it yourself -## Note For the offline database IPInfoLocal, please download it yourself to the same directory as NextTrace and rename it to ipinfoLocal.mmdb. (You can download it from here: https://ipinfo.io/signup?ref=free-database-downloads) -## For the offline database Ip2region, you can download it manually to the same directory as NextTrace and rename it to ip2region.db, or let NextTrace download it automatically. +## Note There are frequency limits for free queries of the ipinfo and IPInsight APIs. You can purchase services from these providers to remove the limits. +## If necessary, you can clone this project, add the token provided by ipinfo or IPInsight and compile it yourself +## Note For the offline database IPInfoLocal, please download it manually and rename it to ipinfoLocal.mmdb. (You can download it from here: https://ipinfo.io/signup?ref=free-database-downloads) +## For the offline database Ip2region, you can download it manually and rename it to ip2region.db, or let NextTrace download it automatically. ## Fill the token to: ipgeo/tokens.go ## Please be aware: Due to the serious abuse of IP.SB, you will often be not able to query IP data from this source ## IP-API.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes. + +# You can also specify the default IP database by setting an environment variable +export NEXTTRACE_DATAPROVIDER=ipinfo ``` `NextTrace` supports mixed parameters and shortened parameters diff --git a/README_zh_CN.md b/README_zh_CN.md index 9c71641..478275b 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -146,13 +146,15 @@ nexttrace --route-path www.time.com.my ```bash # 可以自行指定IP数据库[此处为IP-API.com],不指定则默认为LeoMoeAPI nexttrace --data-provider ip-api.com -## 特别的: 其中 `ipinfo` 和 `IPInsight` API 需要从这些服务商自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译 +## 特别的: 其中 ipinfo 和 IPInsight API 对于免费版查询有频率限制,可从这些服务商自行购买服务以解除限制,如有需要可以 clone 本项目添加其提供的 token 自行编译 ## TOKEN填写路径:ipgeo/tokens.go -## 特别的: 对于离线库`IPInfoLocal`,请自行下载到与NextTrace同目录下,并命名为`ipinfoLocal.mmdb` (可以从这里下载:https://ipinfo.io/signup?ref=free-database-downloads) -## 对于离线库`Ip2region`可NextTrace自动下载,也可自行下载到与NextTrace同目录下,并命名为`ip2region.db` - +## 特别的: 对于离线库 IPInfoLocal,请自行下载并命名为 ipinfoLocal.mmdb (可以从这里下载:https://ipinfo.io/signup?ref=free-database-downloads) +## 对于离线库 Ip2region 可NextTrace自动下载,也可自行下载并命名为 ip2region.db ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 ## IP-API.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 + +# 也可以通过设置环境变量来指定默认IP数据库 +export NEXTTRACE_DATAPROVIDER=ipinfo ``` `NextTrace`支持使用混合参数和简略参数 diff --git a/cmd/cmd.go b/cmd/cmd.go index 688fca1..1ef4d28 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -141,15 +141,17 @@ func Excute() { } if strings.ToUpper(*dataOrigin) == "LEOMOEAPI" { - w := wshandle.New() - w.Interrupt = make(chan os.Signal, 1) - signal.Notify(w.Interrupt, os.Interrupt) - defer func() { - err := w.Conn.Close() - if err != nil { - return - } - }() + val, ok := os.LookupEnv("NEXTTRACE_DATAPROVIDER") + if ok { + *dataOrigin = val + } else { + w := wshandle.New() + w.Interrupt = make(chan os.Signal, 1) + signal.Notify(w.Interrupt, os.Interrupt) + defer func() { + w.Conn.Close() + }() + } } printer.PrintTraceRouteNav(ip, domain, *dataOrigin) diff --git a/dn42/geofeed.go b/dn42/geofeed.go index 118de38..7b183f6 100644 --- a/dn42/geofeed.go +++ b/dn42/geofeed.go @@ -37,12 +37,7 @@ func ReadGeoFeed() ([]GeoFeedRow, error) { if err != nil { return nil, err } - defer func(f *os.File) { - err := f.Close() - if err != nil { - panic(err) - } - }(f) + defer f.Close() r := csv.NewReader(f) rows, err := r.ReadAll() diff --git a/dn42/ptr.go b/dn42/ptr.go index 834d029..c470ff9 100644 --- a/dn42/ptr.go +++ b/dn42/ptr.go @@ -36,12 +36,7 @@ func FindPtrRecord(ptr string) (PtrRow, error) { if err != nil { return PtrRow{}, err } - defer func(f *os.File) { - err := f.Close() - if err != nil { - panic(err) - } - }(f) + defer f.Close() r := csv.NewReader(f) rows, err := r.ReadAll() diff --git a/ipgeo/ip2region.go b/ipgeo/ip2region.go index 1f9e3e9..41ae0c0 100644 --- a/ipgeo/ip2region.go +++ b/ipgeo/ip2region.go @@ -22,24 +22,14 @@ func downloadDataBase() error { if err != nil { return err } - defer func(Body io.ReadCloser) { - err := Body.Close() - if err != nil { - panic(err) - } - }(resp.Body) + defer resp.Body.Close() // Create the file out, err := os.Create(ipDataBasePath) if err != nil { return err } - defer func(out *os.File) { - err := out.Close() - if err != nil { - panic(err) - } - }(out) + defer out.Close() // Write the body to file _, err = io.Copy(out, resp.Body) diff --git a/ipgeo/ipinfo.go b/ipgeo/ipinfo.go index bfb26ac..6576a1b 100644 --- a/ipgeo/ipinfo.go +++ b/ipgeo/ipinfo.go @@ -13,12 +13,7 @@ func IPInfo(ip string) (*IPGeoData, error) { if err != nil { return nil, err } - defer func(Body io.ReadCloser) { - err := Body.Close() - if err != nil { - panic(err) - } - }(resp.Body) + defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err diff --git a/ipgeo/leo.go b/ipgeo/leo.go index 0f9f020..efdcc3f 100644 --- a/ipgeo/leo.go +++ b/ipgeo/leo.go @@ -55,10 +55,7 @@ func receiveParse() { } m := make(map[string][]string) - err := json.Unmarshal([]byte(res.Get("router").String()), &m) - if err != nil { - return - } + json.Unmarshal([]byte(res.Get("router").String()), &m) lat, _ := strconv.ParseFloat(res.Get("lat").String(), 32) lng, _ := strconv.ParseFloat(res.Get("lng").String(), 32) diff --git a/printer/basic.go b/printer/basic.go index 75d2110..d3f4a8f 100644 --- a/printer/basic.go +++ b/printer/basic.go @@ -12,19 +12,16 @@ var buildDate = "" var commitID = "" func Version() { - _, err := fmt.Fprintf(color.Output, "%s %s %s %s\n", + fmt.Fprintf(color.Output, "%s %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", "NextTrace"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", version), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", buildDate), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", commitID), ) - if err != nil { - panic(err) - } } func CopyRight() { - _, err := fmt.Fprintf(color.Output, "\n%s\n%s\n%s %s\n\n%s\n%s %s\n%s %s\n%s %s\n\n%s\n%s\n%s %s\n\n", + fmt.Fprintf(color.Output, "\n%s\n%s\n%s %s\n\n%s\n%s %s\n%s %s\n%s %s\n\n%s\n%s\n%s %s\n\n", color.New(color.FgCyan, color.Bold).Sprintf("%s", "NextTrace CopyRight"), color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Project Creator"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Leo"), @@ -41,36 +38,27 @@ func CopyRight() { color.New(color.FgWhite, color.Bold).Sprintf("%s", "zhshch"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "zhshch@athorx.com"), ) - if err != nil { - return - } MoeQingOrgCopyRight() PluginCopyRight() } func MoeQingOrgCopyRight() { - _, err := fmt.Fprintf(color.Output, "%s\n%s %s\n%s %s\n\n", + fmt.Fprintf(color.Output, "%s\n%s %s\n%s %s\n\n", color.New(color.FgHiYellow, color.Bold).Sprintf("%s", "MoeQing Network"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "YekongTAT"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "yekongtat@gmail.com"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Haima"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "haima@peers.cloud"), ) - if err != nil { - return - } } func PluginCopyRight() { - _, err := fmt.Fprintf(color.Output, "%s\n%s %s\n\n", + fmt.Fprintf(color.Output, "%s\n%s %s\n\n", color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Map Plugin Author"), color.New(color.FgWhite, color.Bold).Sprintf("%s", "Tso"), color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "tsosunchia@gmail.com"), ) - if err != nil { - return - } } func PrintTraceRouteNav(ip net.IP, domain string, dataOrigin string) { diff --git a/printer/realtime_printer.go b/printer/realtime_printer.go index bc9e66f..23bbbde 100644 --- a/printer/realtime_printer.go +++ b/printer/realtime_printer.go @@ -39,12 +39,9 @@ func RealtimePrinter(res *trace.Result, ttl int) { } if latestIP == "" { - _, err := fmt.Fprintf(color.Output, "%s\n", + fmt.Fprintf(color.Output, "%s\n", color.New(color.FgWhite, color.Bold).Sprintf("*"), ) - if err != nil { - return - } return } @@ -54,19 +51,13 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Printf("%4s", "") } if net.ParseIP(ip).To4() == nil { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip), ) - if err != nil { - return - } } i, _ := strconv.Atoi(v[0]) @@ -86,15 +77,9 @@ func RealtimePrinter(res *trace.Result, ttl int) { case res.Hops[ttl][i].Geo.Whois == "CMIN2-NET": fallthrough case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."): - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) default: - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) } } else { @@ -130,15 +115,9 @@ func RealtimePrinter(res *trace.Result, ttl int) { case whoisFormat[0] == "[CMIN2-NET]": fallthrough case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."): - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("%-16s", whoisFormat[0])) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("%-16s", whoisFormat[0])) default: - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) } } @@ -168,7 +147,8 @@ func RealtimePrinter(res *trace.Result, ttl int) { } if net.ParseIP(ip).To4() != nil { - _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + + fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -176,11 +156,8 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -188,26 +165,17 @@ func RealtimePrinter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname), ) - if err != nil { - return - } } for j := 1; j < len(v); j++ { if len(v) == 2 || j == 1 { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, " / %s", + fmt.Fprintf(color.Output, " / %s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) - if err != nil { - return - } } } fmt.Println() diff --git a/printer/realtime_printer_router.go b/printer/realtime_printer_router.go index 215a414..18007bb 100644 --- a/printer/realtime_printer_router.go +++ b/printer/realtime_printer_router.go @@ -39,12 +39,9 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { } if latestIP == "" { - _, err := fmt.Fprintf(color.Output, "%s\n", + fmt.Fprintf(color.Output, "%s\n", color.New(color.FgWhite, color.Bold).Sprintf("*"), ) - if err != nil { - return - } return } @@ -54,28 +51,19 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Printf("%4s", "") } if net.ParseIP(ip).To4() == nil { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip), ) - if err != nil { - return - } } i, _ := strconv.Atoi(v[0]) if res.Hops[ttl][i].Geo.Asnumber != "" { - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber)) } else { fmt.Printf(" %-8s", "*") } @@ -89,10 +77,7 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { if whoisFormat[0] != "" { whoisFormat[0] = "[" + whoisFormat[0] + "]" } - _, err := fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) - if err != nil { - return - } + fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0])) } if res.Hops[ttl][i].Geo.Country == "" { @@ -101,7 +86,7 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { if net.ParseIP(ip).To4() != nil { - _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -109,11 +94,8 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", + fmt.Fprintf(color.Output, " %s %s %s %s %s\n %s ", color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov), color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City), @@ -121,41 +103,29 @@ func RealtimePrinterWithRouter(res *trace.Result, ttl int) { fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner), color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname), ) - if err != nil { - return - } } for j := 1; j < len(v); j++ { if len(v) == 2 || j == 1 { - _, err := fmt.Fprintf(color.Output, "%s", + fmt.Fprintf(color.Output, "%s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, " / %s", + fmt.Fprintf(color.Output, " / %s", color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]), ) - if err != nil { - return - } } } i = 0 fmt.Println() if res.Hops[ttl][i].Geo != nil && !blockDisplay { - _, err := fmt.Fprintf(color.Output, "%s %s %s %s %s\n", + fmt.Fprintf(color.Output, "%s %s %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("-"), color.New(color.FgHiYellow, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prefix), color.New(color.FgWhite, color.Bold).Sprintf("路由表"), color.New(color.FgHiCyan, color.Bold).Sprintf("Beta"), color.New(color.FgWhite, color.Bold).Sprintf("-"), ) - if err != nil { - return - } GetRouter(&res.Hops[ttl][i].Geo.Router, "AS"+res.Hops[ttl][i].Geo.Asnumber) } blockDisplay = true @@ -166,22 +136,16 @@ func GetRouter(r *map[string][]string, node string) { routeMap := *r for _, v := range routeMap[node] { if len(routeMap[v]) != 0 { - _, err := fmt.Fprintf(color.Output, " %s %s %s\n", + fmt.Fprintf(color.Output, " %s %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", routeMap[v][0]), color.New(color.FgWhite, color.Bold).Sprintf("%s", v), color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node), ) - if err != nil { - return - } } else { - _, err := fmt.Fprintf(color.Output, " %s %s\n", + fmt.Fprintf(color.Output, " %s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", v), color.New(color.FgHiBlue, color.Bold).Sprintf("%s", node), ) - if err != nil { - return - } } } diff --git a/trace/icmp_ipv4.go b/trace/icmp_ipv4.go index 8397b8b..6e5d288 100644 --- a/trace/icmp_ipv4.go +++ b/trace/icmp_ipv4.go @@ -66,12 +66,7 @@ func (t *ICMPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer func(icmpListen net.PacketConn) { - err := icmpListen.Close() - if err != nil { - log.Println(err) - } - }(t.icmpListen) + defer t.icmpListen.Close() var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -90,12 +85,7 @@ func (t *ICMPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go func() { - err := t.send(ttl) - if err != nil { - log.Println(err) - } - }() + go t.send(ttl) <-time.After(time.Millisecond * time.Duration(t.Config.PacketInterval)) } <-time.After(time.Millisecond * time.Duration(t.Config.TTLInterval)) @@ -268,10 +258,7 @@ func (t *ICMPTracer) send(ttl int) error { }, } - err := ipv4.NewPacketConn(t.icmpListen).SetTTL(ttl) - if err != nil { - return err - } + ipv4.NewPacketConn(t.icmpListen).SetTTL(ttl) wb, err := icmpHeader.Marshal(nil) if err != nil { @@ -311,10 +298,7 @@ func (t *ICMPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - err := h.fetchIPData(t.Config) - if err != nil { - return err - } + h.fetchIPData(t.Config) t.res.add(h) case <-time.After(t.Timeout): diff --git a/trace/icmp_ipv6.go b/trace/icmp_ipv6.go index 7501314..8454e91 100644 --- a/trace/icmp_ipv6.go +++ b/trace/icmp_ipv6.go @@ -67,12 +67,7 @@ func (t *ICMPTracerv6) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer func(icmpListen net.PacketConn) { - err := icmpListen.Close() - if err != nil { - panic(err) - } - }(t.icmpListen) + defer t.icmpListen.Close() var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -91,12 +86,7 @@ func (t *ICMPTracerv6) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go func() { - err := t.send(ttl) - if err != nil { - log.Println(err) - } - }() + go t.send(ttl) <-time.After(time.Millisecond * time.Duration(t.Config.PacketInterval)) } <-time.After(time.Millisecond * time.Duration(t.Config.TTLInterval)) @@ -268,10 +258,7 @@ func (t *ICMPTracerv6) send(ttl int) error { p := ipv6.NewPacketConn(t.icmpListen) icmpHeader.Body.(*icmp.Echo).Seq = ttl - err := p.SetHopLimit(ttl) - if err != nil { - return err - } + p.SetHopLimit(ttl) wb, err := icmpHeader.Marshal(nil) if err != nil { @@ -311,10 +298,7 @@ func (t *ICMPTracerv6) send(ttl int) error { h.TTL = ttl h.RTT = rtt - err := h.fetchIPData(t.Config) - if err != nil { - return err - } + h.fetchIPData(t.Config) t.res.add(h) diff --git a/trace/tcp_ipv4.go b/trace/tcp_ipv4.go index f2f4dec..e1f386f 100644 --- a/trace/tcp_ipv4.go +++ b/trace/tcp_ipv4.go @@ -55,12 +55,7 @@ func (t *TCPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer func(icmp net.PacketConn) { - err := icmp.Close() - if err != nil { - panic(err) - } - }(t.icmp) + defer t.icmp.Close() var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -83,12 +78,7 @@ func (t *TCPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go func() { - err := t.send(ttl) - if err != nil { - log.Println(err) - } - }() + go t.send(ttl) } if t.RealtimePrinter != nil { @@ -295,10 +285,7 @@ func (t *TCPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - err := h.fetchIPData(t.Config) - if err != nil { - return err - } + h.fetchIPData(t.Config) t.res.add(h) diff --git a/trace/tcp_ipv6.go b/trace/tcp_ipv6.go index 091e8cc..c0b2686 100644 --- a/trace/tcp_ipv6.go +++ b/trace/tcp_ipv6.go @@ -2,7 +2,6 @@ package trace import ( "encoding/binary" - "log" "math" "math/rand" "net" @@ -51,12 +50,7 @@ func (t *TCPTracerv6) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer func(icmp net.PacketConn) { - err := icmp.Close() - if err != nil { - log.Println(err) - } - }(t.icmp) + defer t.icmp.Close() var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -76,12 +70,7 @@ func (t *TCPTracerv6) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go func() { - err := t.send(ttl) - if err != nil { - log.Println(err) - } - }() + go t.send(ttl) } if t.RealtimePrinter != nil { // 对于实时模式,应该按照TTL进行并发请求 @@ -238,10 +227,7 @@ func (t *TCPTracerv6) send(ttl int) error { return err } - err = ipv6.NewPacketConn(t.tcp).SetHopLimit(ttl) - if err != nil { - return err - } + ipv6.NewPacketConn(t.tcp).SetHopLimit(ttl) if err != nil { return err } @@ -282,10 +268,7 @@ func (t *TCPTracerv6) send(ttl int) error { h.TTL = ttl h.RTT = rtt - err := h.fetchIPData(t.Config) - if err != nil { - return err - } + h.fetchIPData(t.Config) t.res.add(h) diff --git a/trace/udp.go b/trace/udp.go index 7afa2c6..6277466 100644 --- a/trace/udp.go +++ b/trace/udp.go @@ -41,12 +41,7 @@ func (t *UDPTracer) Execute() (*Result, error) { if err != nil { return &t.res, err } - defer func(icmp net.PacketConn) { - err := icmp.Close() - if err != nil { - log.Println(err) - } - }(t.icmp) + defer t.icmp.Close() var cancel context.CancelFunc t.ctx, cancel = context.WithCancel(context.Background()) @@ -64,12 +59,7 @@ func (t *UDPTracer) Execute() (*Result, error) { } for i := 0; i < t.NumMeasurements; i++ { t.wg.Add(1) - go func() { - err := t.send(ttl) - if err != nil { - log.Println(err) - } - }() + go t.send(ttl) } if t.RealtimePrinter != nil { @@ -266,10 +256,7 @@ func (t *UDPTracer) send(ttl int) error { h.TTL = ttl h.RTT = rtt - err := h.fetchIPData(t.Config) - if err != nil { - return err - } + h.fetchIPData(t.Config) t.res.add(h) diff --git a/tracemap/tracemap.go b/tracemap/tracemap.go index 26a3f11..5546d69 100644 --- a/tracemap/tracemap.go +++ b/tracemap/tracemap.go @@ -13,11 +13,8 @@ func GetMapUrl(r string) { url := "https://api.leo.moe/tracemap/api" resp, _ := http.Post(url, "application/json", strings.NewReader(r)) body, _ := io.ReadAll(resp.Body) - _, err := fmt.Fprintf(color.Output, "%s %s\n", + fmt.Fprintf(color.Output, "%s %s\n", color.New(color.FgWhite, color.Bold).Sprintf("%s", "MapTrace URL:"), color.New(color.FgBlue, color.Bold).Sprintf("%s", string(body)), ) - if err != nil { - return - } } diff --git a/util/util.go b/util/util.go index 1cb14cc..40e50b9 100644 --- a/util/util.go +++ b/util/util.go @@ -20,12 +20,7 @@ func LocalIPPort(dstip net.IP) (net.IP, int) { // We don't actually connect to anything, but we can determine // based on our destination ip what source ip we should use. if con, err := net.DialUDP("udp", nil, serverAddr); err == nil { - defer func(con *net.UDPConn) { - err := con.Close() - if err != nil { - log.Fatal(err) - } - }(con) + defer con.Close() if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok { return udpaddr.IP, udpaddr.Port } @@ -42,12 +37,7 @@ func LocalIPPortv6(dstip net.IP) (net.IP, int) { // We don't actually connect to anything, but we can determine // based on our destination ip what source ip we should use. if con, err := net.DialUDP("udp", nil, serverAddr); err == nil { - defer func(con *net.UDPConn) { - err := con.Close() - if err != nil { - log.Fatal(err) - } - }(con) + defer con.Close() if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok { return udpaddr.IP, udpaddr.Port } @@ -98,13 +88,10 @@ func DomainLookUp(host string, ipv4Only bool, dotServer string) net.IP { } else { fmt.Println("Please Choose the IP You Want To TraceRoute") for i, ip := range ips { - _, err := fmt.Fprintf(color.Output, "%s %s\n", + fmt.Fprintf(color.Output, "%s %s\n", color.New(color.FgHiYellow, color.Bold).Sprintf("%d.", i), color.New(color.FgWhite, color.Bold).Sprintf("%s", ip), ) - if err != nil { - return nil - } } var index int fmt.Printf("Your Option: ") From 916ac3cb69323196a632e901eab775b18e34262e Mon Sep 17 00:00:00 2001 From: tsosunchia <59512455+tsosunchia@users.noreply.github.com> Date: Fri, 3 Mar 2023 12:07:37 +0800 Subject: [PATCH 13/13] add CHUNZHEN api --- README.md | 14 ++++-- README_zh_CN.md | 10 ++-- cmd/cmd.go | 4 +- fast_trace/fast_trace ipv6.go | 5 +- fast_trace/fast_trace.go | 5 +- fast_trace/fast_trace_test.go | 5 +- ipgeo/chunzhen.go | 91 +++++++++++++++++++++++++++++++++++ ipgeo/ipgeo.go | 2 + ipgeo/ipinfo.go | 9 +++- 9 files changed, 122 insertions(+), 23 deletions(-) create mode 100644 ipgeo/chunzhen.go diff --git a/README.md b/README.md index a5b3497..6b2f1c6 100644 --- a/README.md +++ b/README.md @@ -127,13 +127,17 @@ nexttrace --route-path www.time.com.my ```bash # You can specify the IP database by yourself [IP-API.com here], if not specified, LeoMoeAPI will be used nexttrace --data-provider ip-api.com -## Note There are frequency limits for free queries of the ipinfo and IPInsight APIs. You can purchase services from these providers to remove the limits. +## Note There are frequency limits for free queries of the ipinfo and IPInsight APIs. You can purchase services from these providers to remove the limits ## If necessary, you can clone this project, add the token provided by ipinfo or IPInsight and compile it yourself ## Note For the offline database IPInfoLocal, please download it manually and rename it to ipinfoLocal.mmdb. (You can download it from here: https://ipinfo.io/signup?ref=free-database-downloads) -## For the offline database Ip2region, you can download it manually and rename it to ip2region.db, or let NextTrace download it automatically. +## For the offline database Ip2region, you can download it manually and rename it to ip2region.db, or let NextTrace download it automatically ## Fill the token to: ipgeo/tokens.go ## Please be aware: Due to the serious abuse of IP.SB, you will often be not able to query IP data from this source -## IP-API.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes. +## IP-API.com has a stricter restiction on API calls, if you can't query IP data from this source, please try again in a few minutes + +# The Pure-FTPd IP database defaults to using http://127.0.0.1:2060 as the query interface. To customize it, please use environment variables +export NEXTTRACE_CHUNZHENURL=http://127.0.0.1:2060 +## You can use https://github.com/freshcn/qqwry to build your own Pure-FTPd IP database service # You can also specify the default IP database by setting an environment variable export NEXTTRACE_DATAPROVIDER=ipinfo @@ -167,7 +171,7 @@ All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/x Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal)] + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal|chunzhen)] [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] [-r|--report] [--dn42] [-o|--output] [-t|--table] [-c|--classic] [-f|--first ] [-M|--map] @@ -202,7 +206,7 @@ Arguments: reached). Default: 30 -d --data-provider Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, - IPInfoLocal]. Default: LeoMoeAPI + IPInfoLocal, CHUNZHEN]. Default: LeoMoeAPI -n --no-rdns Do not resolve IP addresses to their domain names -a --always-rdns Always resolve IP addresses to their diff --git a/README_zh_CN.md b/README_zh_CN.md index 478275b..7516602 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -141,7 +141,7 @@ nexttrace --no-rdns www.bbix.net nexttrace --route-path www.time.com.my ``` -`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`, `Ip2region`, `IPInfoLocal`) +`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`, `Ip2region`, `IPInfoLocal`, `CHUNZHEN`) ```bash # 可以自行指定IP数据库[此处为IP-API.com],不指定则默认为LeoMoeAPI @@ -153,6 +153,10 @@ nexttrace --data-provider ip-api.com ## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。 ## IP-API.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。 +# 纯真IP数据库默认使用 http://127.0.0.1:2060 作为查询接口,如需自定义请使用环境变量 +export NEXTTRACE_CHUNZHENURL=http://127.0.0.1:2060 +## 可使用 https://github.com/freshcn/qqwry 自行搭建纯真IP数据库服务 + # 也可以通过设置环境变量来指定默认IP数据库 export NEXTTRACE_DATAPROVIDER=ipinfo ``` @@ -175,7 +179,7 @@ nexttrace -T -q 2 --parallel-requests 1 -t -R 2001:4860:4860::8888 Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port ] [-q|--queries ] [--parallel-requests ] [-m|--max-hops ] [-d|--data-provider - (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal)] + (Ip2region|ip2region|IP.SB|ip.sb|IPInfo|ipinfo|IPInsight|ipinsight|IPAPI.com|ip-api.com|IPInfoLocal|ipinfolocal|chunzhen)] [-n|--no-rdns] [-a|--always-rdns] [-P|--route-path] [-r|--report] [--dn42] [-o|--output] [-t|--table] [-c|--classic] [-f|--first ] [-M|--map] @@ -210,7 +214,7 @@ Arguments: reached). Default: 30 -d --data-provider Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, - IPInfoLocal]. Default: LeoMoeAPI + IPInfoLocal, CHUNZHEN]. Default: LeoMoeAPI -n --no-rdns Do not resolve IP addresses to their domain names -a --always-rdns Always resolve IP addresses to their diff --git a/cmd/cmd.go b/cmd/cmd.go index 1ef4d28..b922f0c 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -37,8 +37,8 @@ func Excute() { numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"}) parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"}) maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"}) - dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal"}, &argparse.Options{Default: "LeoMoeAPI", - Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, IPInfoLocal]"}) + dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal", "chunzhen"}, &argparse.Options{Default: "LeoMoeAPI", + Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, IPInfoLocal, CHUNZHEN]"}) noRdns := parser.Flag("n", "no-rdns", &argparse.Options{Help: "Do not resolve IP addresses to their domain names"}) alwaysRdns := parser.Flag("a", "always-rdns", &argparse.Options{Help: "Always resolve IP addresses to their domain names"}) routePath := parser.Flag("P", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"}) diff --git a/fast_trace/fast_trace ipv6.go b/fast_trace/fast_trace ipv6.go index 8ecf446..de85842 100644 --- a/fast_trace/fast_trace ipv6.go +++ b/fast_trace/fast_trace ipv6.go @@ -117,10 +117,7 @@ func FastTestv6(tm bool, outEnable bool) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - err := w.Conn.Close() - if err != nil { - return - } + w.Conn.Close() }() if !tm { diff --git a/fast_trace/fast_trace.go b/fast_trace/fast_trace.go index 4284957..a52907b 100644 --- a/fast_trace/fast_trace.go +++ b/fast_trace/fast_trace.go @@ -142,10 +142,7 @@ func FastTest(tm bool, outEnable bool) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - err := w.Conn.Close() - if err != nil { - return - } + w.Conn.Close() }() if !tm { diff --git a/fast_trace/fast_trace_test.go b/fast_trace/fast_trace_test.go index ae514d5..285c3b8 100644 --- a/fast_trace/fast_trace_test.go +++ b/fast_trace/fast_trace_test.go @@ -17,10 +17,7 @@ func TestTCPTrace(t *testing.T) { w.Interrupt = make(chan os.Signal, 1) signal.Notify(w.Interrupt, os.Interrupt) defer func() { - err := w.Conn.Close() - if err != nil { - return - } + w.Conn.Close() }() ft.TracerouteMethod = trace.TCPTrace ft.testCM() diff --git a/ipgeo/chunzhen.go b/ipgeo/chunzhen.go new file mode 100644 index 0000000..8326892 --- /dev/null +++ b/ipgeo/chunzhen.go @@ -0,0 +1,91 @@ +package ipgeo + +import ( + "encoding/json" + "github.com/xgadget-lab/nexttrace/util" + "io" + "log" + "net/http" + "strings" + "time" +) + +func Chunzhen(ip string) (*IPGeoData, error) { + url := util.GetenvDefault("NEXTTRACE_CHUNZHENURL", "http://127.0.0.1:2060") + "?ip=" + ip + client := &http.Client{ + // 2 秒超时 + Timeout: 2 * time.Second, + } + req, _ := http.NewRequest("GET", url, nil) + content, err := client.Do(req) + if err != nil { + log.Println("纯真 请求超时(2s),请切换其他API使用") + return &IPGeoData{}, err + } + body, _ := io.ReadAll(content.Body) + + var data map[string]interface{} + err = json.Unmarshal(body, &data) + if err != nil { + return &IPGeoData{}, err + } + city := data[ip].(map[string]interface{})["area"].(string) + region := data[ip].(map[string]interface{})["country"].(string) + var asn string + if data[ip].(map[string]interface{})["asn"] != nil { + asn = data[ip].(map[string]interface{})["asn"].(string) + } + // 判断是否前两个字为香港或台湾 + var country string + provinces := []string{ + "北京", + "天津", + "河北", + "山西", + "内蒙古", + "辽宁", + "吉林", + "黑龙江", + "上海", + "江苏", + "浙江", + "安徽", + "福建", + "江西", + "山东", + "河南", + "湖北", + "湖南", + "广东", + "广西", + "海南", + "重庆", + "四川", + "贵州", + "云南", + "西藏", + "陕西", + "甘肃", + "青海", + "宁夏", + "新疆", + "台湾", + "香港", + "澳门", + } + for _, province := range provinces { + if strings.Contains(region, province) { + country = "中国" + city = region + city + break + } + } + if country == "" { + country = region + } + return &IPGeoData{ + Asnumber: asn, + Country: country, + City: city, + }, nil +} diff --git a/ipgeo/ipgeo.go b/ipgeo/ipgeo.go index 3aca36d..78264b6 100644 --- a/ipgeo/ipgeo.go +++ b/ipgeo/ipgeo.go @@ -47,6 +47,8 @@ func GetSource(s string) Source { return IP2Region case "IPINFOLOCAL": return IPInfoLocal + case "CHUNZHEN": + return Chunzhen default: return LeoIP } diff --git a/ipgeo/ipinfo.go b/ipgeo/ipinfo.go index 6576a1b..1b34294 100644 --- a/ipgeo/ipinfo.go +++ b/ipgeo/ipinfo.go @@ -279,12 +279,19 @@ func IPInfo(ip string) (*IPGeoData, error) { "ZW": "Zimbabwe", } country = countryMap[country] + i := strings.Index(res.Get("org").String(), " ") + var owner string + if i == -1 { + owner = "" + } else { + owner = res.Get("org").String()[i:] + } return &IPGeoData{ Asnumber: strings.Fields(strings.TrimPrefix(res.Get("org").String(), "AS"))[0], Country: country, City: res.Get("city").String(), Prov: res.Get("region").String(), - Owner: res.Get("asn").Get("domain").String(), + Owner: owner, }, nil }