mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afe18fc4c0 | ||
|
|
cc1d6177ca | ||
|
|
c8077919ce | ||
|
|
cfc79489d4 | ||
|
|
f60e6fbc99 | ||
|
|
de0f49d01b | ||
|
|
7ae47fdb6f | ||
|
|
471412b740 | ||
|
|
8aca06fe24 | ||
|
|
003db157a9 | ||
|
|
6e88706d62 | ||
|
|
0940014b09 | ||
|
|
5a7d04ab1e | ||
|
|
c6b7db8d59 | ||
|
|
95f8cef54c | ||
|
|
99ad5649a0 | ||
|
|
4bc4f1c176 | ||
|
|
b663e69343 | ||
|
|
7619e74152 | ||
|
|
c682f90856 | ||
|
|
68c84488ae | ||
|
|
deaebfa383 | ||
|
|
b467128c24 | ||
|
|
de93a2b3cb | ||
|
|
66de7df351 | ||
|
|
9685b80820 | ||
|
|
8a3a9d5e38 | ||
|
|
c826dd50ec | ||
|
|
4664bc727a | ||
|
|
b66b7edc46 | ||
|
|
457f25035c | ||
|
|
8220bd7920 | ||
|
|
372ac9d383 | ||
|
|
916a5dc9d0 |
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@@ -48,4 +48,41 @@ jobs:
|
||||
dist/nexttrace_freebsd_amd64
|
||||
dist/nexttrace_freebsd_arm64
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GT_Token }}
|
||||
GITHUB_TOKEN: ${{ secrets.GT_Token }}
|
||||
|
||||
publish-new-formula:
|
||||
needs: build
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Runs a single command using the runners shell
|
||||
- name: config git
|
||||
run: |
|
||||
git config --global user.email "${{ secrets.git_mail }}"
|
||||
git config --global user.name "${{ secrets.git_name }}"
|
||||
- name: Clone repo
|
||||
run: |
|
||||
git clone https://github.com/xgadget-lab/homebrew-nexttrace.git
|
||||
- name: Exec scipt
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
bash genFormula.sh
|
||||
# - name: setup SSH keys and known_hosts
|
||||
# run: |
|
||||
# mkdir -p ~/.ssh
|
||||
# ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
# ssh-agent -a $SSH_AUTH_SOCK > /dev/null
|
||||
# ssh-add - <<< "${{ secrets.ID_RSA }}"
|
||||
# env:
|
||||
# SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
- name: Git Push
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
git commit -am 'Publish a new version with Formula' || true
|
||||
git remote set-url origin https://${{ secrets.gt_token }}@github.com/xgadget-lab/homebrew-nexttrace.git
|
||||
git push
|
||||
# env:
|
||||
# SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
9
.github/workflows/publishNewFormula.yml
vendored
9
.github/workflows/publishNewFormula.yml
vendored
@@ -3,7 +3,6 @@ name: Publish New Formula
|
||||
# Controls when the action will run. Workflow runs when manually triggered using the UI
|
||||
# or API.
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
@@ -22,7 +21,7 @@ jobs:
|
||||
git config --global user.name "${{ secrets.git_name }}"
|
||||
- name: Clone repo
|
||||
run: |
|
||||
git clone https://github.com/xgadget-lab/homebrew-nexttrace.git
|
||||
git clone https://github.com/sjlleo/homebrew-nexttrace.git
|
||||
- name: Exec scipt
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
@@ -38,9 +37,9 @@ jobs:
|
||||
- name: Git Push
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
git commit -am 'Publish a new version with Formula'
|
||||
git remote set-url origin https://${{ secrets.gt_token }}@github.com/xgadget-lab/homebrew-nexttrace.git
|
||||
git push || 1
|
||||
git commit -am 'Publish a new version with Formula' || true
|
||||
git remote set-url origin https://${{ secrets.gt_token }}@github.com/sjlleo/homebrew-nexttrace.git
|
||||
git push
|
||||
# env:
|
||||
# SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -161,3 +161,5 @@ Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# compile target directory
|
||||
dist/
|
||||
|
||||
405
README.md
405
README.md
@@ -8,7 +8,228 @@
|
||||
|
||||
An open source visual routing tool that pursues light weight, developed using Golang.
|
||||
|
||||
2022/12/18: Due to time and effort, it is becoming more and more difficult to maintain 2 branches at the same time, so I will be phasing out support for the NextTrace Enhanced version in the near future. I will resume updating the `Enhanced` version when I have more time.
|
||||
## How To Use
|
||||
|
||||
Document Language: English | [简体中文](README_zh_CN.md)
|
||||
|
||||
### Automated Installation
|
||||
|
||||
```bash
|
||||
# Linux one-click install script
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/sjlleo/nexttrace/main/nt_install.sh)
|
||||
|
||||
# GHPROXY 镜像(国内使用)
|
||||
bash -c "$(curl -Ls https://ghproxy.com/https://raw.githubusercontent.com/sjlleo/nexttrace/main/nt_install.sh)"
|
||||
|
||||
# macOS brew install command
|
||||
brew tap xgadget-lab/nexttrace && brew install nexttrace
|
||||
```
|
||||
|
||||
Windows users please go to [Release Page](https://github.com/sjlleo/nexttrace/releases/latest) directly and download exe file.
|
||||
|
||||
- `Release` provides compiled executables for many systems and architectures, if not, you can compile it yourself.
|
||||
- Some of the necessary dependencies of this project are not fully implemented in `Golang` on `Windows`, so currently `NextTrace` is experimental on `Windows` platform.
|
||||
|
||||
### Get Started
|
||||
|
||||
`NextTrace` uses the `ICMP` protocol to perform TraceRoute requests by default, which supports both `IPv4` and `IPv6`
|
||||
|
||||
```bash
|
||||
# IPv4 ICMP Trace
|
||||
nexttrace 1.0.0.1
|
||||
|
||||
# Form printing (output all hops at one time, wait 20-40 seconds)
|
||||
nexttrace --table 1.0.0.1
|
||||
|
||||
# IPv6 ICMP Trace
|
||||
nexttrace 2606:4700:4700::1111
|
||||
|
||||
# Path Visualization With the -M parameter, a map URL is returned
|
||||
nexttrace --map koreacentral.blob.core.windows.net
|
||||
# MapTrace URL: https://api.leo.moe/tracemap/html/c14e439e-3250-5310-8965-42a1e3545266.html
|
||||
```
|
||||
|
||||
PS: The routing visualization drawing module was written by [@tsosunchia](https://github.com/tsosunchia), and the specific code can be viewed at [tsosunchia/traceMap](https://github.com/tsosunchia/traceMap).
|
||||
|
||||
Note that in LeoMoeAPI 2.0, due to the addition of geographical location data, **we have deprecated the online query part of the OpenStreetMap API in the traceMap plugin and are using location information from our own database**.
|
||||
|
||||
The routing visualization function requires the geographical coordinates of each Hop, but third-party APIs generally do not provide this information, so this function is currently only supported when used with LeoMoeAPI.
|
||||
|
||||
`NextTrace` now supports quick testing, and friends who have a one-time backhaul routing test requirement can use it
|
||||
|
||||
```bash
|
||||
# IPv4 ICMP Fast Test (Beijing + Shanghai + Guangzhou + Hangzhou) in China Telecom / Unicom / Mobile / Education Network
|
||||
nexttrace --fast-trace
|
||||
|
||||
# You can also use TCP SYN for testing
|
||||
nexttrace --fast-trace --tcp
|
||||
```
|
||||
|
||||
`NextTrace` already supports route tracing for specified Network Devices
|
||||
|
||||
```bash
|
||||
# Use eth0 network interface
|
||||
nexttrace --dev eth0 2606:4700:4700::1111
|
||||
|
||||
# Use eth0 network interface's IP
|
||||
# When using the network interface's IP for route tracing, note that the IP type to be traced should be the same as network interface's IP type (e.g. both IPv4)
|
||||
nexttrace --source 204.98.134.56 9.9.9.9
|
||||
```
|
||||
|
||||
`NextTrace` can also use `TCP` and `UDP` protocols to perform `Traceroute` requests, but these protocols only supports `IPv4` now
|
||||
|
||||
```bash
|
||||
# TCP SYN Trace
|
||||
nexttrace --tcp www.bing.com
|
||||
|
||||
# You can specify the port by yourself [here is 443], the default port is 80
|
||||
nexttrace --tcp --port 443 1.0.0.1
|
||||
|
||||
# UDP Trace
|
||||
nexttrace --udp 1.0.0.1
|
||||
|
||||
nexttrace --udp --port 53 1.0.0.1
|
||||
```
|
||||
|
||||
`NextTrace` also supports some advanced functions, such as ttl control, concurrent probe packet count control, mode switching, etc.
|
||||
|
||||
```bash
|
||||
# Send 2 probe packets per hop
|
||||
nexttrace --queries 2 www.hkix.net
|
||||
|
||||
# No concurrent probe packets, only one probe packet is sent at a time
|
||||
nexttrace --parallel-requests 1 www.hkix.net
|
||||
|
||||
# Start Trace with TTL of 5, end at TTL of 10
|
||||
nexttrace --first 5 --max-hops 10 www.decix.net
|
||||
|
||||
# Turn off the IP reverse parsing function
|
||||
nexttrace --no-rdns www.bbix.net
|
||||
|
||||
# Feature: print Route-Path diagram
|
||||
# Route-Path diagram example:
|
||||
# AS6453 Tata Communication「Singapore『Singapore』」
|
||||
# ╭╯
|
||||
# ╰AS9299 Philippine Long Distance Telephone Co.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS36776 Five9 Inc.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS37963 Aliyun「ALIDNS.COM『ALIDNS.COM』」
|
||||
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`)
|
||||
|
||||
```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
|
||||
## 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.
|
||||
```
|
||||
|
||||
`NextTrace` supports mixed parameters and shortened parameters
|
||||
|
||||
```bash
|
||||
Example:
|
||||
nexttrace --data-provider IPAPI.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 -T -q 2 --parallel-requests 1 -t -R 2001:4860:4860::8888
|
||||
```
|
||||
|
||||
### IP Database
|
||||
|
||||
#### We use [bgp.tools](https://bgp.tools) as a data provider for routing tables.
|
||||
|
||||
NextTrace BackEnd is now open-source.
|
||||
|
||||
https://github.com/sjlleo/nexttrace-backend
|
||||
|
||||
All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
|
||||
|
||||
### For full usage list, please refer to the usage menu
|
||||
|
||||
```shell
|
||||
Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port
|
||||
<integer>] [-q|--queries <integer>] [--parallel-requests
|
||||
<integer>] [-m|--max-hops <integer>] [-d|--data-provider
|
||||
(IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns]
|
||||
[-r|--route-path] [-o|--output] [-t|--table] [-c|--classic]
|
||||
[-f|--first <integer>] [-M|--map] [-v|--version] [-s|--source
|
||||
"<value>"] [-D|--dev "<value>"] [-R|--route] [-z|--send-time
|
||||
<integer>] [-i|--ttl-time <integer>]
|
||||
[IP Address or Domain name]
|
||||
Arguments:
|
||||
|
||||
-h --help Print help information
|
||||
-T --tcp Use TCP SYN for tracerouting (default port
|
||||
is 80)
|
||||
-U --udp Use UDP SYN for tracerouting (default port
|
||||
is 53)
|
||||
-F --fast-trace One-Key Fast Trace to China ISPs
|
||||
-p --port Set the destination port to use. It is
|
||||
either initial udp port value for
|
||||
"default"method (incremented by each
|
||||
probe, default is 33434), or initial seq
|
||||
for "icmp" (incremented as well, default
|
||||
from 1), or some constantdestination port
|
||||
for other methods (with default of 80 for
|
||||
"tcp", 53 for "udp", etc.)
|
||||
-q --queries Set the number of probes per each hop.
|
||||
Default: 3
|
||||
--parallel-requests Set ParallelRequests number. It should be
|
||||
1 when there is a multi-routing. Default:
|
||||
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
|
||||
domain names
|
||||
-r --route-path Print traceroute hop path by ASN and
|
||||
location
|
||||
-o --output Write trace result to file
|
||||
(RealTimePrinter ONLY)
|
||||
-t --table Output trace results as table
|
||||
-c --classic Classic Output trace results like
|
||||
BestTrace
|
||||
-f --first Start from the first_ttl hop (instead from
|
||||
1). Default: 1
|
||||
-M --map Print Trace Map. This will return a Trace
|
||||
Map URL
|
||||
-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
|
||||
source address in outgoing packets
|
||||
-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
|
||||
-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
|
||||
```
|
||||
|
||||
## Project screenshot
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## NextTrace Enhanced
|
||||
|
||||
`NextTrace Enhanced` is an enhanced version for enthusiasts, `Enhanced` provides trace route calls in the form of Web API and a simple Looking Glass webpage with built-in visualization.
|
||||
|
||||
The `Enhanced` version supports many functions that the `lite` version does not have, such as the ability to customize the timeout period, and the ability to specify TTL as the starting point for route tracking, etc. For ordinary users, the `lite` version is usually enough.
|
||||
|
||||
https://github.com/OwO-Network/nexttrace-enhanced
|
||||
|
||||
## 公告
|
||||
|
||||
@@ -53,188 +274,6 @@ The LeoMoeAPI data is subject to copyright restrictions from multiple data sourc
|
||||
|
||||
We hope you can give us as much feedback as possible on IP geolocation errors (see issue) so that it can be calibrated in the first place and others can benefit from it.
|
||||
|
||||
## How To Use
|
||||
|
||||
Document Language: English | [简体中文](README_zh_CN.md)
|
||||
|
||||
### Automated Installation
|
||||
|
||||
```bash
|
||||
# Linux one-click install script
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/sjlleo/nexttrace/main/nt_install.sh)
|
||||
|
||||
# macOS brew install command
|
||||
brew tap xgadget-lab/nexttrace && brew install nexttrace
|
||||
```
|
||||
|
||||
Windows users please go to [Release Page](https://github.com/sjlleo/nexttrace/releases/latest) directly and download exe file.
|
||||
|
||||
- `Release` provides compiled executables for many systems and architectures, if not, you can compile it yourself.
|
||||
- Some of the necessary dependencies of this project are not fully implemented in `Golang` on `Windows`, so currently `NextTrace` is experimental on `Windows` platform.
|
||||
|
||||
### Get Started
|
||||
|
||||
`NextTrace` uses the `ICMP` protocol to perform TraceRoute requests by default, which supports both `IPv4` and `IPv6`
|
||||
|
||||
```bash
|
||||
# IPv4 ICMP Trace
|
||||
nexttrace 1.0.0.1
|
||||
|
||||
# Form printing (output all hops at one time, wait 20-40 seconds)
|
||||
nexttrace --table 1.0.0.1
|
||||
|
||||
# IPv6 ICMP Trace
|
||||
nexttrace 2606:4700:4700::1111
|
||||
|
||||
# Path Visualization With the -M parameter, a map URL is returned
|
||||
nexttrace --map koreacentral.blob.core.windows.net
|
||||
# MapTrace URL: https://api.leo.moe/tracemap/html/c14e439e-3250-5310-8965-42a1e3545266.html
|
||||
```
|
||||
|
||||
PS: The routing visualization drawing module was written by [@tsosunchia](https://github.com/tsosunchia), and the specific code can be viewed at [tsosunchia/traceMap](https://github.com/tsosunchia/traceMap).
|
||||
|
||||
Note that in LeoMoeAPI 2.0, due to the addition of geographical location data, **we have deprecated the online query part of the OpenStreetMap API in the traceMap plugin and are using location information from our own database**.
|
||||
|
||||
The routing visualization function requires the geographical coordinates of each Hop, but third-party APIs generally do not provide this information, so this function is currently only supported when used with LeoMoeAPI.
|
||||
|
||||
`NextTrace` now supports quick testing, and friends who have a one-time backhaul routing test requirement can use it
|
||||
|
||||
```bash
|
||||
# IPv4 ICMP Fast Test (Beijing + Shanghai + Guangzhou + Hangzhou) in China Telecom / Unicom / Mobile / Education Network
|
||||
nexttrace -F
|
||||
|
||||
# You can also use TCP SYN for testing
|
||||
nexttrace -F -T
|
||||
```
|
||||
|
||||
`NextTrace` already supports route tracing for specified Network Devices
|
||||
|
||||
```bash
|
||||
# Use eth0 network interface
|
||||
nexttrace --dev eth0 2606:4700:4700::1111
|
||||
|
||||
# Use eth0 network interface's IP
|
||||
# When using the network interface's IP for route tracing, note that the IP type to be traced should be the same as network interface's IP type (e.g. both IPv4)
|
||||
nexttrace --source 204.98.134.56 9.9.9.9
|
||||
```
|
||||
|
||||
`NextTrace` can also use `TCP` and `UDP` protocols to perform `Traceroute` requests, but these protocols only supports `IPv4` now
|
||||
|
||||
```bash
|
||||
# TCP SYN Trace
|
||||
nexttrace -T www.bing.com
|
||||
|
||||
# You can specify the port by yourself [here is 443], the default port is 80
|
||||
nexttrace -T -p 443 1.0.0.1
|
||||
|
||||
# UDP Trace
|
||||
nexttrace -U 1.0.0.1
|
||||
|
||||
nexttrace -U -p 53 1.0.0.1
|
||||
```
|
||||
|
||||
`NextTrace` also supports some advanced functions, such as ttl control, concurrent probe packet count control, mode switching, etc.
|
||||
|
||||
```bash
|
||||
# Send 2 probe packets per hop
|
||||
nexttrace -q 2 www.hkix.net
|
||||
|
||||
# No concurrent probe packets, only one probe packet is sent at a time
|
||||
nexttrace -r 1 www.hkix.net
|
||||
|
||||
# Start Trace with TTL of 5, end at TTL of 10
|
||||
nexttrace -f 5 -m 10 www.decix.net
|
||||
|
||||
# Turn off the IP reverse parsing function
|
||||
nexttrace -n www.bbix.net
|
||||
|
||||
# Feature: print Route-Path diagram
|
||||
# Route-Path diagram example:
|
||||
# AS6453 Tata Communication「Singapore『Singapore』」
|
||||
# ╭╯
|
||||
# ╰AS9299 Philippine Long Distance Telephone Co.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS36776 Five9 Inc.「Philippines『Metro Manila』」
|
||||
# ╭╯
|
||||
# ╰AS37963 Aliyun「ALIDNS.COM『ALIDNS.COM』」
|
||||
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`)
|
||||
|
||||
```bash
|
||||
# You can specify the IP database by yourself [IP.SB here], if not specified, LeoMoeAPI will be used
|
||||
nexttrace -d 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
|
||||
## 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.
|
||||
```
|
||||
|
||||
`NextTrace` supports mixed parameters
|
||||
|
||||
```bash
|
||||
Example:
|
||||
nexttrace --data-provider LeoMoeAPI -m 20 -p 443 -q 5 -n 1.1.1.1
|
||||
nexttrace -T -q 2 -r 1 --table --route-path 2001:4860:4860::8888
|
||||
```
|
||||
|
||||
### IP Database
|
||||
|
||||
#### We use [bgp.tools](https://bgp.tools) as a data provider for routing tables.
|
||||
|
||||
NextTrace BackEnd is now open-source.
|
||||
|
||||
https://github.com/sjlleo/nexttrace-backend
|
||||
|
||||
All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
|
||||
|
||||
### For full usage list, please refer to the usage menu
|
||||
|
||||
```shell
|
||||
Usage of nexttrace:
|
||||
'nexttrace [options] <hostname>' or 'nexttrace <hostname> [option...]'
|
||||
Options:
|
||||
-T Use TCP SYN for tracerouting (default port is 80)
|
||||
-U Use UDP Package for tracerouting (default port is 53 in UDP)
|
||||
-V Print Version
|
||||
-b int
|
||||
Set The Begin TTL (default 1)
|
||||
-d string
|
||||
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com] (default "LeoMoeAPI")
|
||||
-f One-Key Fast Traceroute
|
||||
-m int
|
||||
Set the max number of hops (max TTL to be reached). (default 30)
|
||||
-n Disable IP Reverse DNS lookup
|
||||
-p int
|
||||
Set SYN Traceroute Port (default 80)
|
||||
-q int
|
||||
Set the number of probes per each hop. (default 3)
|
||||
-r int
|
||||
Set ParallelRequests number. It should be 1 when there is a multi-routing. (default 18)
|
||||
-report
|
||||
Route Path
|
||||
-table
|
||||
Output trace results as table
|
||||
```
|
||||
|
||||
## Project screenshot
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## NextTrace Enhanced
|
||||
|
||||
`NextTrace Enhanced` is an enhanced version for enthusiasts, `Enhanced` provides trace route calls in the form of Web API and a simple Looking Glass webpage with built-in visualization.
|
||||
|
||||
The `Enhanced` version supports many functions that the `lite` version does not have, such as the ability to customize the timeout period, and the ability to specify TTL as the starting point for route tracking, etc. For ordinary users, the `lite` version is usually enough.
|
||||
|
||||
https://github.com/OwO-Network/nexttrace-enhanced
|
||||
|
||||
#
|
||||
|
||||
## FAQ Frequently Asked Questions
|
||||
|
||||
If you encounter problems while installing or using it, we do not recommend you to choose creating an `issue` as a preference
|
||||
|
||||
206
README_zh_CN.md
206
README_zh_CN.md
@@ -4,16 +4,32 @@
|
||||
|
||||
</div>
|
||||
|
||||
## NextTrace
|
||||
<h1 align="center">
|
||||
<br>NextTrace<br>
|
||||
</h1>
|
||||
|
||||
一款追求轻量的开源可视化路由跟踪工具,使用 Golang 开发。
|
||||
|
||||
如果您对 NextTrace 项目本身感兴趣,可以阅读 [有关 NextTrace 的一些碎碎念](https://leo.moe/annoucement/nexttrace.html) 或许可以帮您解决疑惑。
|
||||
<h4 align="center">一款追求轻量化的开源可视化路由跟踪工具。</h4>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/sjlleo/nexttrace/actions">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/sjlleo/nexttrace/build.yml?branch=main&style=flat-square" alt="Github Actions">
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/github.com/sjlleo/nexttrace">
|
||||
<img src="https://goreportcard.com/badge/github.com/sjlleo/nexttrace?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/sjlleo/nexttrace/releases">
|
||||
<img src="https://img.shields.io/github/release/sjlleo/nexttrace/all.svg?style=flat-square">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
2022/12/18: 由于时间精力的关系,同时维护2个分支变得愈发困难,近期我将逐步停止 NextTrace Enhanced 版本的支持,如有觉得 NextTrace Enhanced 一些不错的功能,可以在 issue 里面提出来。待我重新有富裕时间时重新恢复对 `Enhanced` 版本的更新。
|
||||
|
||||
## How To Use
|
||||
|
||||
### Before Using
|
||||
|
||||
使用 NextTrace 之前,我们建议您先阅读 [#IP 数据以及精准度说明](https://github.com/sjlleo/nexttrace/blob/main/README_zh_CN.md#ip-%E6%95%B0%E6%8D%AE%E4%BB%A5%E5%8F%8A%E7%B2%BE%E5%87%86%E5%BA%A6%E8%AF%B4%E6%98%8E),在了解您自己的对数据精准度需求以后再进行抉择。
|
||||
|
||||
### Automated Install
|
||||
|
||||
```bash
|
||||
@@ -40,14 +56,14 @@ Windows 用户请直接前往 [Release](https://github.com/sjlleo/nexttrace/rele
|
||||
# IPv4 ICMP Trace
|
||||
nexttrace 1.0.0.1
|
||||
|
||||
# 表格打印(一次性输出全部跳数,需等待20-40秒)
|
||||
# 表格打印,使用 --table / -t 参数,将实时显示结果
|
||||
nexttrace --table 1.0.0.1
|
||||
|
||||
# IPv6 ICMP Trace
|
||||
nexttrace 2606:4700:4700::1111
|
||||
|
||||
# 路径可视化 使用 -M 参数,将返回一个地图 URL
|
||||
nexttrace -M koreacentral.blob.core.windows.net
|
||||
# 路径可视化 使用 --map / -M 参数,将返回一个地图 URL
|
||||
nexttrace --map koreacentral.blob.core.windows.net
|
||||
# MapTrace URL: https://api.leo.moe/tracemap/html/c14e439e-3250-5310-8965-42a1e3545266.html
|
||||
```
|
||||
|
||||
@@ -60,11 +76,11 @@ PS: 路由可视化的绘制模块由 [@tsosunchia](https://github.com/tsosunchi
|
||||
`NextTrace` 现已经支持快速测试,有一次性测试回程路由需求的朋友可以使用
|
||||
|
||||
```bash
|
||||
# 北上广(电信+联通+移动+教育网)IPv4 ICMP 快速测试
|
||||
nexttrace -F
|
||||
# 北上广(电信+联通+移动+教育网)IPv4 / IPv6 ICMP 快速测试
|
||||
nexttrace --fast-trace
|
||||
|
||||
# 也可以使用 TCP SYN 而非 ICMP 进行测试
|
||||
nexttrace -F -T
|
||||
# 也可以使用 TCP SYN 而非 ICMP 进行测试(不支持 IPv6)
|
||||
nexttrace --fast-trace --tcp
|
||||
```
|
||||
|
||||
`NextTrace` 已支持指定网卡进行路由跟踪
|
||||
@@ -72,43 +88,44 @@ nexttrace -F -T
|
||||
```bash
|
||||
# 请注意 Lite 版本此参数不能和快速测试联用,如有需要请使用 enhanced 版本
|
||||
# 使用 eth0 网卡
|
||||
nexttrace -D eth0 2606:4700:4700::1111
|
||||
nexttrace --dev eth0 2606:4700:4700::1111
|
||||
|
||||
# 使用 eth0 网卡IP
|
||||
# 网卡 IP 可以使用 ip a 或者 ifconfig 获取
|
||||
# 使用网卡IP进行路由跟踪时需要注意跟踪的IP类型应该和网卡IP类型一致(如都为 IPv4)
|
||||
nexttrace -S 204.98.134.56 9.9.9.9
|
||||
nexttrace --source 204.98.134.56 9.9.9.9
|
||||
```
|
||||
|
||||
`NextTrace` 也可以使用`TCP`和`UDP`协议发起`Traceroute`请求,不过目前只支持`IPv4`
|
||||
|
||||
```bash
|
||||
# TCP SYN Trace
|
||||
nexttrace -T www.bing.com
|
||||
nexttrace --tcp www.bing.com
|
||||
|
||||
# 可以自行指定端口[此处为443],默认80端口
|
||||
nexttrace -T -p 443 1.0.0.1
|
||||
nexttrace --tcp --port 443 1.0.0.1
|
||||
|
||||
# UDP Trace
|
||||
nexttrace -U 1.0.0.1
|
||||
nexttrace --udp 1.0.0.1
|
||||
|
||||
nexttrace -U -p 53 1.0.0.1
|
||||
# 可以自行指定端口[此处为5353],默认53端口
|
||||
nexttrace --udp --port 5353 1.0.0.1
|
||||
```
|
||||
|
||||
`NextTrace`也同样支持一些进阶功能,如 TTL 控制、并发数控制、模式切换等
|
||||
|
||||
```bash
|
||||
# 每一跳发送2个探测包
|
||||
nexttrace -q 2 www.hkix.net
|
||||
nexttrace --queries 2 www.hkix.net
|
||||
|
||||
# 无并发,每次只发送一个探测包
|
||||
nexttrace -r 1 www.hkix.net
|
||||
nexttrace --parallel-requests 1 www.hkix.net
|
||||
|
||||
# 从TTL为5开始发送探测包,直到TTL为10结束
|
||||
nexttrace -b 5 -m 10 www.decix.net
|
||||
nexttrace --first 5 --max-hops 10 www.decix.net
|
||||
|
||||
# 关闭IP反向解析功能
|
||||
nexttrace -n www.bbix.net
|
||||
nexttrace --no-rdns www.bbix.net
|
||||
|
||||
# 特色功能:打印Route-Path图
|
||||
# Route-Path图示例:
|
||||
@@ -126,62 +143,89 @@ nexttrace --route-path www.time.com.my
|
||||
|
||||
```bash
|
||||
# 可以自行指定IP数据库[此处为IP.SB],不指定则默认为LeoMoeAPI
|
||||
nexttrace -d IP.SB
|
||||
## 特别的:其中 ipinfo API 需要从ipinfo自行购买服务,如有需要可以clone本项目添加其提供的token自行编译
|
||||
nexttrace --data-provider IP.SB
|
||||
## 特别的:其中 ipinfo API 需要从 ipinfo 自行购买服务,如有需要可以 clone 本项目添加其提供的 token 自行编译
|
||||
## TOKEN填写路径:ipgeo/tokens.go
|
||||
|
||||
## 另外:由于IP.SB被滥用比较严重,会经常出现无法查询的问题,请知悉。
|
||||
## IPAPI.com限制调用较为严格,如有查询不到的情况,请几分钟后再试。
|
||||
```
|
||||
|
||||
`NextTrace`支持参数混合使用
|
||||
`NextTrace`支持使用混合参数和简略参数
|
||||
|
||||
```bash
|
||||
Example:
|
||||
nexttrace --data-provider LeoMoeAPI -m 20 -p 443 -q 5 --parallel-requests 20 -n 1.1.1.1
|
||||
nexttrace -T -q 2 --table --route-path 2001:4860:4860::8888
|
||||
nexttrace --data-provider IPAPI.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 -T -q 2 --parallel-requests 1 -t -R 2001:4860:4860::8888
|
||||
```
|
||||
|
||||
### IP 数据库
|
||||
|
||||
我们使用[bgp.tools](https://bgp.tools)作为路由表功能的数据提供者。
|
||||
|
||||
✨NextTrace `LeoMoeAPI` 的后端也开源啦
|
||||
|
||||
[GitHub - sjlleo/nexttrace-backend: NextTrace BackEnd](https://github.com/sjlleo/nexttrace-backend)
|
||||
|
||||
NextTrace 所有的的 IP 地理位置`API DEMO`可以参考[这里](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
|
||||
|
||||
### 全部用法详见 Usage 菜单
|
||||
|
||||
```shell
|
||||
Usage of nexttrace:
|
||||
'nexttrace [options] <hostname>' or 'nexttrace <hostname> [option...]'
|
||||
Options:
|
||||
-D string
|
||||
Use the following Network Devices as the source address in outgoing packets
|
||||
-S string
|
||||
Use the following IP address as the source address in outgoing packets
|
||||
-T Use TCP SYN for tracerouting (default port is 80)
|
||||
-U Use UDP Package for tracerouting (default port is 53 in UDP)
|
||||
-V Print Version
|
||||
-b int
|
||||
Set The Begin TTL (default 1)
|
||||
-d string
|
||||
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com] (default "LeoMoeAPI")
|
||||
-f One-Key Fast Traceroute
|
||||
-m int
|
||||
Set the max number of hops (max TTL to be reached). (default 30)
|
||||
-n Disable IP Reverse DNS lookup
|
||||
-p int
|
||||
Set SYN Traceroute Port (default 80)
|
||||
-q int
|
||||
Set the number of probes per each hop. (default 3)
|
||||
-r int
|
||||
Set ParallelRequests number. It should be 1 when there is a multi-routing. (default 18)
|
||||
-report
|
||||
Route Path
|
||||
-table
|
||||
Output trace results as table
|
||||
Usage: nexttrace [-h|--help] [-T|--tcp] [-U|--udp] [-F|--fast-trace] [-p|--port
|
||||
<integer>] [-q|--queries <integer>] [--parallel-requests
|
||||
<integer>] [-m|--max-hops <integer>] [-d|--data-provider
|
||||
(IP.SB|IPInfo|IPInsight|IPAPI.com)] [-n|--no-rdns]
|
||||
[-r|--route-path] [-o|--output] [-t|--table] [-c|--classic]
|
||||
[-f|--first <integer>] [-M|--map] [-v|--version] [-s|--source
|
||||
"<value>"] [-D|--dev "<value>"] [-R|--route] [-z|--send-time
|
||||
<integer>] [-i|--ttl-time <integer>]
|
||||
[IP Address or Domain name]
|
||||
Arguments:
|
||||
|
||||
-h --help Print help information
|
||||
-T --tcp Use TCP SYN for tracerouting (default port
|
||||
is 80)
|
||||
-U --udp Use UDP SYN for tracerouting (default port
|
||||
is 53)
|
||||
-F --fast-trace One-Key Fast Trace to China ISPs
|
||||
-p --port Set the destination port to use. It is
|
||||
either initial udp port value for
|
||||
"default"method (incremented by each
|
||||
probe, default is 33434), or initial seq
|
||||
for "icmp" (incremented as well, default
|
||||
from 1), or some constantdestination port
|
||||
for other methods (with default of 80 for
|
||||
"tcp", 53 for "udp", etc.)
|
||||
-q --queries Set the number of probes per each hop.
|
||||
Default: 3
|
||||
--parallel-requests Set ParallelRequests number. It should be
|
||||
1 when there is a multi-routing. Default:
|
||||
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
|
||||
domain names
|
||||
-r --route-path Print traceroute hop path by ASN and
|
||||
location
|
||||
-o --output Write trace result to file
|
||||
(RealTimePrinter ONLY)
|
||||
-t --table Output trace results as table
|
||||
-c --classic Classic Output trace results like
|
||||
BestTrace
|
||||
-f --first Start from the first_ttl hop (instead from
|
||||
1). Default: 1
|
||||
-M --map Print Trace Map. This will return a Trace
|
||||
Map URL
|
||||
-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
|
||||
source address in outgoing packets
|
||||
-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
|
||||
-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
|
||||
```
|
||||
|
||||
## 项目截图
|
||||
@@ -190,17 +234,21 @@ Options:
|
||||
|
||||

|
||||
|
||||
## 第三方 IP 数据库 API 开发接口
|
||||
|
||||
NextTrace 所有的的 IP 地理位置 `API DEMO` 可以参考[这里](https://github.com/sjlleo/nexttrace/blob/main/ipgeo/)
|
||||
|
||||
你可以在这里添加你自己的 API 接口,为了 NextTrace 能够正确显示你接口中的内容,请参考 `leo.go` 中所需要的信息
|
||||
|
||||
✨NextTrace `LeoMoeAPI` 的后端 Demo
|
||||
|
||||
[GitHub - sjlleo/nexttrace-backend: NextTrace BackEnd](https://github.com/sjlleo/nexttrace-backend)
|
||||
|
||||
## NextTrace Enhanced
|
||||
|
||||
`NextTrace Enhanced` 是面向发烧友的增强版,`Enhanced`提供Web API形式的路由跟踪调用,以及一个简单的自带可视化的Looking Glass网页。
|
||||
|
||||
`Enhanced` 版本支持很多`lite`版本没有的功能,如能够自定义设置超时时间,也能指定TTL作为起点进行路由跟踪等,对于普通用户来说,通常`lite`版本已经足够完成大部分需要。
|
||||
|
||||
**很遗憾,由于时间精力的关系,`Enhanced` 版本将在很长一段时间不会再收到新的更新补丁,我们将继续维护 `Standard` 版本。**
|
||||
|
||||
https://github.com/OwO-Network/nexttrace-enhanced
|
||||
|
||||
## Thanks
|
||||
## Credits
|
||||
|
||||
BGP.TOOLS 提供了本项目的一些数据支持,在此表示由衷地感谢。
|
||||
|
||||
@@ -214,6 +262,20 @@ BGP.TOOLS 提供了本项目的一些数据支持,在此表示由衷地感谢
|
||||
|
||||
[FFEE_CO](https://github.com/fkx4-p)
|
||||
|
||||
### Others
|
||||
## Others
|
||||
|
||||
其他第三方 API 尽管集成在本项目内,但是具体的 TOS 以及 AUP,请详见第三方 API 官网。如遇到 IP 数据错误,也请直接联系他们纠错。
|
||||
|
||||
## IP 数据以及精准度说明
|
||||
|
||||
NextTrace 有多个数据源可以选择,目前默认使用的 LeoMoeAPI 为我们项目维护的数据源。
|
||||
|
||||
LeoMoeAPI 早期数据主要来自 IPInsight、IPInfo,随着项目发展,越来越多的志愿者参与进了这个项目。目前 LeoMoeAPI 有近一半的数据是社区提供的,而另外一半主要来自于包含 IPInfo、IPData、BigDataCloud、IPGeoLocation 在内的多个第三方数据。
|
||||
|
||||
LeoMoeAPI 的骨干网数据有近 70% 是社区自发反馈又或者是项目组成员校准的,这给本项目的路由跟踪基础功能带来了一定的保证,但是全球骨干网的体量庞大,我们并无能力如 IPIP 等商业公司拥有海量监测节点,这使得 LeoMoeAPI 的数据精准度无法和形如 BestTrace(IPIP)相提并论。
|
||||
|
||||
LeoMoeAPI 已经尽力校准了比较常见的骨干网路由,这部分在测试的时候经常会命中,但是如果遇到封闭型 ISP 的路由,大概率可以遇到错误,此类数据不仅是我们,哪怕 IPInsight、IPInfo 也无法正确定位,目前只有 IPIP 能够标记正确,如对此类数据的精确性有着非常高的要求,请务必使用 BestTrace 作为首选。
|
||||
|
||||
我们不保证我们的数据一定会及时更新,也不保证数据的精确性,我们希望您在发现数据错误的时候可以前往 issue 页面提交错误报告,谢谢。
|
||||
|
||||
当您使用 LeoMoeAPI 即视为您已经完全了解 NextTrace LeoMoeAPI 的数据精确性,并且同意如果您引用 LeoMoeAPI 其中的数据从而引发的一切问题,均由您自己承担。
|
||||
|
||||
22
cmd/cmd.go
22
cmd/cmd.go
@@ -38,20 +38,24 @@ func Excute() {
|
||||
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]"})
|
||||
noRdns := parser.Flag("n", "no-rdns", &argparse.Options{Help: " Do not resolve IP addresses to their domain names"})
|
||||
routePath := parser.Flag("r", "route-path", &argparse.Options{Help: "Print traceroute hop path by ASN and location"})
|
||||
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"})
|
||||
report := parser.Flag("r", "report", &argparse.Options{Help: "output using report mode"})
|
||||
output := parser.Flag("o", "output", &argparse.Options{Help: "Write trace result to file (RealTimePrinter ONLY)"})
|
||||
tablePrint := parser.Flag("t", "table", &argparse.Options{Help: "Output trace results as table"})
|
||||
classicPrint := parser.Flag("c", "classic", &argparse.Options{Help: "Classic Output trace results like BestTrace"})
|
||||
beginHop := parser.Int("f", "first", &argparse.Options{Default: 1, Help: "Start from the first_ttl hop (instead from 1)"})
|
||||
maptrace := parser.Flag("M", "map", &argparse.Options{Help: "Print Trace Map. This will return a Trace Map URL"})
|
||||
maptrace := parser.Flag("M", "map", &argparse.Options{Help: "No Print Trace Map"})
|
||||
ver := parser.Flag("v", "version", &argparse.Options{Help: "Print version info and exit"})
|
||||
src_addr := parser.String("s", "source", &argparse.Options{Help: "Use source src_addr for outgoing packets"})
|
||||
src_dev := parser.String("D", "dev", &argparse.Options{Help: "Use the following Network Devices as the source address in outgoing packets"})
|
||||
router := parser.Flag("R", "route", &argparse.Options{Help: "Show Routing Table [Provided By BGP.Tools]"})
|
||||
packet_interval := parser.Int("z", "send-time", &argparse.Options{Default: 0, Help: "Set the time interval for sending every packet. Useful when some routers use rate-limit for ICMP messages."})
|
||||
ttl_interval := parser.Int("i", "ttl-time", &argparse.Options{Default: 500, Help: "Set the time interval for sending packets groups by TTL. Useful when some routers use rate-limit for ICMP messages."})
|
||||
packet_interval := parser.Int("z", "send-time", &argparse.Options{Default: 100, Help: "Set the time interval for sending every packet. Useful when some routers use rate-limit for ICMP messages"})
|
||||
ttl_interval := parser.Int("i", "ttl-time", &argparse.Options{Default: 500, Help: "Set the time interval for sending packets groups by TTL. Useful when some routers use rate-limit for ICMP messages"})
|
||||
str := parser.StringPositional(&argparse.Options{Help: "IP Address or domain name"})
|
||||
lang := parser.Selector("g", "language", []string{"en", "cn"}, &argparse.Options{Default: "cn",
|
||||
Help: "Choose the language for displaying [en, cn]"})
|
||||
|
||||
err := parser.Parse(os.Args)
|
||||
if err != nil {
|
||||
@@ -149,7 +153,9 @@ func Excute() {
|
||||
TTLInterval: *ttl_interval,
|
||||
NumMeasurements: *numMeasurements,
|
||||
ParallelRequests: *parallelRequests,
|
||||
Lang: *lang,
|
||||
RDns: !*noRdns,
|
||||
AlwaysWaitRDNS: *alwaysRdns,
|
||||
IPGeoSource: ipgeo.GetSource(*dataOrigin),
|
||||
Timeout: 1 * time.Second,
|
||||
}
|
||||
@@ -168,7 +174,9 @@ func Excute() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
conf.AsyncPrinter = printer.TracerouteTablePrinter
|
||||
if !*report {
|
||||
conf.AsyncPrinter = printer.TracerouteTablePrinter
|
||||
}
|
||||
}
|
||||
|
||||
res, err := trace.Traceroute(m, conf)
|
||||
@@ -186,7 +194,7 @@ func Excute() {
|
||||
r.Print()
|
||||
}
|
||||
|
||||
if *maptrace {
|
||||
if !*maptrace {
|
||||
r, _ := json.Marshal(res)
|
||||
tracemap.GetMapUrl(string(r))
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ var Shanghai = BackBoneCollection{
|
||||
Location: "上海",
|
||||
CT163: ISPCollection{
|
||||
ISPName: CT163,
|
||||
IP: "101.226.28.198",
|
||||
IP: "202.101.21.178",
|
||||
IPv6: "240e:18:2:153::89",
|
||||
},
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ func (f *FastTracer) tracert(location string, ispCollection ISPCollection) {
|
||||
NumMeasurements: 3,
|
||||
ParallelRequests: 18,
|
||||
RDns: true,
|
||||
PacketInterval: 100,
|
||||
TTLInterval: 500,
|
||||
IPGeoSource: ipgeo.GetSource("LeoMoeAPI"),
|
||||
Timeout: 1 * time.Second,
|
||||
}
|
||||
@@ -106,7 +108,7 @@ func FastTest(tm bool, outEnable bool) {
|
||||
var c string
|
||||
|
||||
oe = outEnable
|
||||
|
||||
fmt.Println("Hi,欢迎使用 Fast Trace 功能,请注意 Fast Trace 功能只适合新手使用\n因为国内网络复杂,我们设置的测试目标有限,建议普通用户自测以获得更加精准的路由情况")
|
||||
fmt.Println("请您选择要测试的 IP 类型\n1. IPv4\n2. IPv6")
|
||||
fmt.Print("请选择选项:")
|
||||
fmt.Scanln(&c)
|
||||
|
||||
86
ipgeo/ipfilter.go
Normal file
86
ipgeo/ipfilter.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package ipgeo
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func cidrRangeContains(cidrRange string, checkIP string) bool {
|
||||
_, ipNet, err := net.ParseCIDR(cidrRange)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
secondIP := net.ParseIP(checkIP)
|
||||
return ipNet.Contains(secondIP)
|
||||
}
|
||||
|
||||
// 被选到的返回 geodata, true 否则返回 nil, false
|
||||
func Filter(ip string) (*IPGeoData, bool) {
|
||||
//geodata := &IPGeoData{}
|
||||
asn := ""
|
||||
whois := ""
|
||||
isFiltered := false
|
||||
switch {
|
||||
//rfc1918
|
||||
case net.ParseIP(ip).IsPrivate():
|
||||
asn = ""
|
||||
whois = "RFC1918"
|
||||
isFiltered = true
|
||||
//IANA Reserved Address Space
|
||||
case cidrRangeContains("100.64.0.0/10", ip):
|
||||
asn = ""
|
||||
whois = "RFC6598"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("198.18.0.0/15", ip):
|
||||
asn = ""
|
||||
whois = "RFC2544"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("198.51.100.0/24", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("203.0.113.0/24", ip):
|
||||
asn = ""
|
||||
whois = "RFC5737"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("240.0.0.0/4", ip):
|
||||
asn = ""
|
||||
whois = "RFC1112"
|
||||
isFiltered = true
|
||||
//Defense Information System Network
|
||||
case cidrRangeContains("6.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("7.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("11.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("21.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("22.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("26.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("28.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("29.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("30.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("33.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("55.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("214.0.0.0/8", ip):
|
||||
fallthrough
|
||||
case cidrRangeContains("215.0.0.0/8", ip):
|
||||
asn = ""
|
||||
whois = "DOD"
|
||||
isFiltered = true
|
||||
default:
|
||||
}
|
||||
if !isFiltered {
|
||||
return nil, false
|
||||
} else {
|
||||
return &IPGeoData{
|
||||
Asnumber: asn,
|
||||
Whois: whois,
|
||||
}, true
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ changeMode() {
|
||||
|
||||
runBinrayFileHelp() {
|
||||
if [ -e ${downPath} ]; then
|
||||
${downPath} -V
|
||||
${downPath} --version
|
||||
echo -e "${Tips} 一切准备就绪!使用命令 nexttrace 1.1.1.1 开始您的第一次路由测试吧~ 更多进阶命令玩法可以用 nexttrace -h 查看哦\n 关于软件卸载,因为nexttrace是绿色版单文件,卸载只需输入命令 rm ${downPath} 即可"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -21,7 +21,44 @@ func Version() {
|
||||
}
|
||||
|
||||
func CopyRight() {
|
||||
fmt.Println("XGadget-lab Leo (leo.moe) & Tso (tsosunchia@gmail.com) & Vincent (vincent.moe) & zhshch (xzhsh.ch)")
|
||||
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"),
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "i@leo.moe"),
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Project Maintainer"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "Tso"),
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "tsosunchia@gmail.com"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "Vincent"),
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "i@vincent.moe"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "Leo"),
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "i@leo.moe"),
|
||||
color.New(color.FgCyan, color.Bold).Sprintf("%s", "Special Acknowledgement List"),
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", "NextTrace Major Contributor"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "zhshch"),
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "zhshch@athorx.com"),
|
||||
)
|
||||
|
||||
MoeQingOrgCopyRight()
|
||||
PluginCopyRight()
|
||||
}
|
||||
|
||||
func MoeQingOrgCopyRight() {
|
||||
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"),
|
||||
)
|
||||
}
|
||||
|
||||
func PluginCopyRight() {
|
||||
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"),
|
||||
)
|
||||
}
|
||||
|
||||
func PrintTraceRouteNav(ip net.IP, domain string, dataOrigin string) {
|
||||
|
||||
@@ -74,12 +74,13 @@ func formatIpGeoData(ip string, data *ipgeo.IPGeoData) string {
|
||||
|
||||
// TODO: 判断阿里云和腾讯云内网,数据不足,有待进一步完善
|
||||
// TODO: 移动IDC判断到Hop.fetchIPData函数,减少API调用
|
||||
if strings.HasPrefix(ip, "9.") {
|
||||
res = append(res, "LAN Address")
|
||||
} else if strings.HasPrefix(ip, "11.") {
|
||||
res = append(res, "LAN Address")
|
||||
} else if data.Country == "" {
|
||||
res = append(res, "LAN Address")
|
||||
//if strings.HasPrefix(ip, "9.") {
|
||||
// res = append(res, "LAN Address")
|
||||
//} else if strings.HasPrefix(ip, "11.") {
|
||||
// res = append(res, "LAN Address")
|
||||
//} else if data.Country == "" {
|
||||
// res = append(res, "LAN Address")
|
||||
if false {
|
||||
} else {
|
||||
// 有些IP的归属信息为空,这个时候将ISP的信息填入
|
||||
if data.Owner == "" {
|
||||
|
||||
@@ -61,9 +61,27 @@ func RealtimePrinter(res *trace.Result, ttl int) {
|
||||
}
|
||||
|
||||
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))
|
||||
// CMIN2, CUII, CN2, CUG 改为壕金色高亮
|
||||
switch {
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "58807":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "10099":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "4809":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "9929":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "23764":
|
||||
fallthrough
|
||||
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))
|
||||
default:
|
||||
fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber))
|
||||
}
|
||||
|
||||
} else {
|
||||
fmt.Printf(" %-8s", "*")
|
||||
}
|
||||
@@ -77,10 +95,55 @@ func RealtimePrinter(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]))
|
||||
|
||||
// CMIN2, CUII, CN2, CUG 改为壕金色高亮
|
||||
switch {
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "58807":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "10099":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "4809":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "9929":
|
||||
fallthrough
|
||||
case res.Hops[ttl][i].Geo.Asnumber == "23764":
|
||||
fallthrough
|
||||
case whoisFormat[0] == "[CNC-BACKBONE]":
|
||||
fallthrough
|
||||
case whoisFormat[0] == "[CUG-BACKBONE]":
|
||||
fallthrough
|
||||
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]))
|
||||
default:
|
||||
fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0]))
|
||||
}
|
||||
}
|
||||
|
||||
if len(res.Hops[ttl][i].Geo.Country) <= 1 {
|
||||
res.Hops[ttl][i].Geo.Country = "LAN Address"
|
||||
res.Hops[ttl][i].Geo.Country = "局域网"
|
||||
res.Hops[ttl][i].Geo.CountryEn = "LAN Address"
|
||||
}
|
||||
|
||||
if res.Hops[ttl][i].Lang == "en" {
|
||||
if res.Hops[ttl][i].Geo.Country == "Anycast" {
|
||||
|
||||
} else if res.Hops[ttl][i].Geo.Prov == "骨干网" {
|
||||
res.Hops[ttl][i].Geo.Prov = "BackBone"
|
||||
} else if res.Hops[ttl][i].Geo.ProvEn == "" {
|
||||
res.Hops[ttl][i].Geo.Country = res.Hops[ttl][i].Geo.CountryEn
|
||||
} else {
|
||||
if res.Hops[ttl][i].Geo.CityEn == "" {
|
||||
res.Hops[ttl][i].Geo.Country = res.Hops[ttl][i].Geo.ProvEn
|
||||
res.Hops[ttl][i].Geo.Prov = res.Hops[ttl][i].Geo.CountryEn
|
||||
res.Hops[ttl][i].Geo.City = ""
|
||||
} else {
|
||||
res.Hops[ttl][i].Geo.Country = res.Hops[ttl][i].Geo.CityEn
|
||||
res.Hops[ttl][i].Geo.Prov = res.Hops[ttl][i].Geo.ProvEn
|
||||
res.Hops[ttl][i].Geo.City = res.Hops[ttl][i].Geo.CountryEn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if net.ParseIP(ip).To4() != nil {
|
||||
|
||||
@@ -18,14 +18,14 @@ import (
|
||||
|
||||
type ICMPTracer struct {
|
||||
Config
|
||||
wg sync.WaitGroup
|
||||
res Result
|
||||
ctx context.Context
|
||||
inflightRequest map[int]chan Hop
|
||||
inflightRequestLock sync.Mutex
|
||||
icmpListen net.PacketConn
|
||||
final int
|
||||
finalLock sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
res Result
|
||||
ctx context.Context
|
||||
inflightRequest map[int]chan Hop
|
||||
inflightRequestRWLock sync.RWMutex
|
||||
icmpListen net.PacketConn
|
||||
final int
|
||||
finalLock sync.Mutex
|
||||
}
|
||||
|
||||
func (t *ICMPTracer) PrintFunc() {
|
||||
@@ -52,7 +52,9 @@ func (t *ICMPTracer) PrintFunc() {
|
||||
}
|
||||
|
||||
func (t *ICMPTracer) Execute() (*Result, error) {
|
||||
t.inflightRequestRWLock.Lock()
|
||||
t.inflightRequest = make(map[int]chan Hop)
|
||||
t.inflightRequestRWLock.Unlock()
|
||||
|
||||
if len(t.res.Hops) > 0 {
|
||||
return &t.res, ErrTracerouteExecuted
|
||||
@@ -75,9 +77,9 @@ func (t *ICMPTracer) Execute() (*Result, error) {
|
||||
t.wg.Add(1)
|
||||
go t.PrintFunc()
|
||||
for ttl := t.BeginHop; ttl <= t.MaxHops; ttl++ {
|
||||
t.inflightRequestLock.Lock()
|
||||
t.inflightRequestRWLock.Lock()
|
||||
t.inflightRequest[ttl] = make(chan Hop, t.NumMeasurements)
|
||||
t.inflightRequestLock.Unlock()
|
||||
t.inflightRequestRWLock.Unlock()
|
||||
if t.final != -1 && ttl > t.final {
|
||||
break
|
||||
}
|
||||
@@ -169,8 +171,8 @@ func (t *ICMPTracer) listenICMP() {
|
||||
}
|
||||
|
||||
func (t *ICMPTracer) handleICMPMessage(msg ReceivedMessage, icmpType int8, data []byte, ttl int) {
|
||||
t.inflightRequestLock.Lock()
|
||||
defer t.inflightRequestLock.Unlock()
|
||||
t.inflightRequestRWLock.RLock()
|
||||
defer t.inflightRequestRWLock.RUnlock()
|
||||
if _, ok := t.inflightRequest[ttl]; ok {
|
||||
t.inflightRequest[ttl] <- Hop{
|
||||
Success: true,
|
||||
@@ -270,7 +272,6 @@ func (t *ICMPTracer) send(ttl int) error {
|
||||
if err := t.icmpListen.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-t.ctx.Done():
|
||||
return nil
|
||||
|
||||
@@ -16,15 +16,15 @@ import (
|
||||
|
||||
type ICMPTracerv6 struct {
|
||||
Config
|
||||
wg sync.WaitGroup
|
||||
res Result
|
||||
ctx context.Context
|
||||
resCh chan Hop
|
||||
inflightRequest map[int]chan Hop
|
||||
inflightRequestLock sync.Mutex
|
||||
icmpListen net.PacketConn
|
||||
final int
|
||||
finalLock sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
res Result
|
||||
ctx context.Context
|
||||
resCh chan Hop
|
||||
inflightRequest map[int]chan Hop
|
||||
inflightRequestRWLock sync.RWMutex
|
||||
icmpListen net.PacketConn
|
||||
final int
|
||||
finalLock sync.Mutex
|
||||
}
|
||||
|
||||
func (t *ICMPTracerv6) PrintFunc() {
|
||||
@@ -53,7 +53,9 @@ func (t *ICMPTracerv6) PrintFunc() {
|
||||
}
|
||||
|
||||
func (t *ICMPTracerv6) Execute() (*Result, error) {
|
||||
t.inflightRequestRWLock.Lock()
|
||||
t.inflightRequest = make(map[int]chan Hop)
|
||||
t.inflightRequestRWLock.Unlock()
|
||||
|
||||
if len(t.res.Hops) > 0 {
|
||||
return &t.res, ErrTracerouteExecuted
|
||||
@@ -76,9 +78,9 @@ func (t *ICMPTracerv6) Execute() (*Result, error) {
|
||||
go t.listenICMP()
|
||||
go t.PrintFunc()
|
||||
for ttl := t.BeginHop; ttl <= t.MaxHops; ttl++ {
|
||||
t.inflightRequestLock.Lock()
|
||||
t.inflightRequestRWLock.Lock()
|
||||
t.inflightRequest[ttl] = make(chan Hop, t.NumMeasurements)
|
||||
t.inflightRequestLock.Unlock()
|
||||
t.inflightRequestRWLock.Unlock()
|
||||
if t.final != -1 && ttl > t.final {
|
||||
break
|
||||
}
|
||||
@@ -110,7 +112,9 @@ func (t *ICMPTracerv6) Execute() (*Result, error) {
|
||||
t.wg.Wait()
|
||||
t.res.reduce(t.final)
|
||||
if t.final != -1 {
|
||||
t.RealtimePrinter(&t.res, t.final-1)
|
||||
if t.RealtimePrinter != nil {
|
||||
t.RealtimePrinter(&t.res, t.final-1)
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < t.NumMeasurements; i++ {
|
||||
t.res.add(Hop{
|
||||
@@ -225,8 +229,8 @@ func (t *ICMPTracerv6) listenICMP() {
|
||||
}
|
||||
|
||||
func (t *ICMPTracerv6) handleICMPMessage(msg ReceivedMessage, icmpType int8, data []byte, ttl int) {
|
||||
t.inflightRequestLock.Lock()
|
||||
defer t.inflightRequestLock.Unlock()
|
||||
t.inflightRequestRWLock.RLock()
|
||||
defer t.inflightRequestRWLock.RUnlock()
|
||||
if _, ok := t.inflightRequest[ttl]; ok {
|
||||
t.inflightRequest[ttl] <- Hop{
|
||||
Success: true,
|
||||
|
||||
@@ -60,7 +60,10 @@ func (t *TCPTracer) Execute() (*Result, error) {
|
||||
var cancel context.CancelFunc
|
||||
t.ctx, cancel = context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
t.inflightRequestLock.Lock()
|
||||
t.inflightRequest = make(map[int]chan Hop)
|
||||
t.inflightRequestLock.Unlock()
|
||||
|
||||
t.final = -1
|
||||
|
||||
go t.listenICMP()
|
||||
@@ -161,7 +164,7 @@ func (t *TCPTracer) listenTCP() {
|
||||
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
|
||||
tcp, _ := tcpLayer.(*layers.TCP)
|
||||
// 取得目标主机的Sequence Number
|
||||
|
||||
t.inflightRequestLock.Lock()
|
||||
if ch, ok := t.inflightRequest[int(tcp.Ack-1)]; ok {
|
||||
// 最后一跳
|
||||
ch <- Hop{
|
||||
@@ -169,6 +172,7 @@ func (t *TCPTracer) listenTCP() {
|
||||
Address: msg.Peer,
|
||||
}
|
||||
}
|
||||
t.inflightRequestLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,10 @@ type Config struct {
|
||||
Quic bool
|
||||
IPGeoSource ipgeo.Source
|
||||
RDns bool
|
||||
AlwaysWaitRDNS bool
|
||||
PacketInterval int
|
||||
TTLInterval int
|
||||
Lang string
|
||||
RealtimePrinter func(res *Result, ttl int)
|
||||
AsyncPrinter func(res *Result)
|
||||
}
|
||||
@@ -115,32 +117,77 @@ type Hop struct {
|
||||
RTT time.Duration
|
||||
Error error
|
||||
Geo *ipgeo.IPGeoData
|
||||
Lang string
|
||||
}
|
||||
|
||||
func (h *Hop) fetchIPData(c Config) (err error) {
|
||||
timeout := time.Millisecond * 800
|
||||
// Debug Area
|
||||
// c.AlwaysWaitRDNS = true
|
||||
|
||||
// Initialize a rDNS Channel
|
||||
rDNSChan := make(chan []string)
|
||||
fetchDoneChan := make(chan bool)
|
||||
|
||||
if c.RDns && h.Hostname == "" {
|
||||
result := make(chan []string)
|
||||
// Create a rDNS Query go-routine
|
||||
go func() {
|
||||
r, err := net.LookupAddr(h.Address.String())
|
||||
if err != nil {
|
||||
result <- nil
|
||||
// No PTR Record
|
||||
rDNSChan <- nil
|
||||
} else {
|
||||
result <- r
|
||||
// One PTR Record is found
|
||||
rDNSChan <- r
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Create Data Fetcher go-routine
|
||||
go func() {
|
||||
// Start to fetch IP Geolocation data
|
||||
if c.IPGeoSource != nil && h.Geo == nil {
|
||||
res := false
|
||||
h.Lang = c.Lang
|
||||
h.Geo, res = ipgeo.Filter(h.Address.String())
|
||||
if !res {
|
||||
h.Geo, err = c.IPGeoSource(h.Address.String())
|
||||
}
|
||||
}
|
||||
// Fetch Done
|
||||
fetchDoneChan <- true
|
||||
}()
|
||||
|
||||
// Select Close Flag
|
||||
var selectClose bool
|
||||
if !c.AlwaysWaitRDNS {
|
||||
select {
|
||||
case ptr := <-result:
|
||||
case <-fetchDoneChan:
|
||||
// When fetch done signal recieved, stop waiting PTR record
|
||||
case ptr := <-rDNSChan:
|
||||
// process result
|
||||
if err == nil && len(ptr) > 0 {
|
||||
h.Hostname = ptr[0][:len(ptr[0])-1]
|
||||
}
|
||||
selectClose = true
|
||||
}
|
||||
} else {
|
||||
select {
|
||||
case ptr := <-rDNSChan:
|
||||
// process result
|
||||
if err == nil && len(ptr) > 0 {
|
||||
h.Hostname = ptr[0]
|
||||
}
|
||||
case <-time.After(timeout):
|
||||
// handle timeout
|
||||
// 1 second timeout
|
||||
case <-time.After(time.Second * 1):
|
||||
}
|
||||
selectClose = true
|
||||
}
|
||||
if c.IPGeoSource != nil && h.Geo == nil {
|
||||
h.Geo, err = c.IPGeoSource(h.Address.String())
|
||||
|
||||
// When Select Close, fetchDoneChan Reciever will also be closed
|
||||
if selectClose {
|
||||
// New a reciever to prevent channel congestion
|
||||
<-fetchDoneChan
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ func (t *UDPTracer) handleICMPMessage(msg ReceivedMessage, data []byte) {
|
||||
return
|
||||
}
|
||||
srcPort := util.GetUDPSrcPort(header)
|
||||
//t.inflightRequestLock.Lock()
|
||||
//defer t.inflightRequestLock.Unlock()
|
||||
t.inflightRequestLock.Lock()
|
||||
defer t.inflightRequestLock.Unlock()
|
||||
ch, ok := t.inflightRequest[int(srcPort)]
|
||||
if !ok {
|
||||
return
|
||||
|
||||
@@ -77,3 +77,11 @@ func DomainLookUp(host string, ipv4Only bool) net.IP {
|
||||
return ipSlice[index]
|
||||
}
|
||||
}
|
||||
|
||||
func GetenvDefault(key, defVal string) string {
|
||||
val, ok := os.LookupEnv(key)
|
||||
if ok {
|
||||
return val
|
||||
}
|
||||
return defVal
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
package wshandle
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
)
|
||||
|
||||
type WsConn struct {
|
||||
@@ -24,6 +29,8 @@ type WsConn struct {
|
||||
}
|
||||
|
||||
var wsconn *WsConn
|
||||
var hostP = util.GetenvDefault("NEXTTRACE_HOSTPORT", "api.leo.moe")
|
||||
var host, port, fast_ip string
|
||||
|
||||
func (c *WsConn) keepAlive() {
|
||||
go func() {
|
||||
@@ -31,7 +38,12 @@ func (c *WsConn) keepAlive() {
|
||||
for {
|
||||
<-time.After(time.Second * 54)
|
||||
if c.Connected {
|
||||
c.Conn.WriteMessage(websocket.TextMessage, []byte("ping"))
|
||||
err := c.Conn.WriteMessage(websocket.TextMessage, []byte("ping"))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
c.Connected = false
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -70,12 +82,12 @@ func (c *WsConn) messageSendHandler() {
|
||||
// 循环监听发送
|
||||
select {
|
||||
case <-c.Done:
|
||||
log.Println("发送协程已经退出")
|
||||
log.Println("go-routine has been returned")
|
||||
return
|
||||
case t := <-c.MsgSendCh:
|
||||
// log.Println(t)
|
||||
if !c.Connected {
|
||||
c.MsgReceiveCh <- `{"ip":"` + t + `", "asnumber":"API服务端异常"}`
|
||||
c.MsgReceiveCh <- `{"ip":"` + t + `", "asnumber":"API Server Error"}`
|
||||
} else {
|
||||
err := c.Conn.WriteMessage(websocket.TextMessage, []byte(t))
|
||||
if err != nil {
|
||||
@@ -104,10 +116,16 @@ func (c *WsConn) messageSendHandler() {
|
||||
}
|
||||
|
||||
func (c *WsConn) recreateWsConn() {
|
||||
u := url.URL{Scheme: "wss", Host: "api.leo.moe", Path: "/v2/ipGeoWs"}
|
||||
u := url.URL{Scheme: "wss", Host: fast_ip + ":" + port, Path: "/v2/ipGeoWs"}
|
||||
// log.Printf("connecting to %s", u.String())
|
||||
|
||||
ws, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
requestHeader := http.Header{
|
||||
"Host": []string{host},
|
||||
}
|
||||
dialer := websocket.DefaultDialer
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: host,
|
||||
}
|
||||
ws, _, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
|
||||
c.Conn = ws
|
||||
if err != nil {
|
||||
log.Println("dial:", err)
|
||||
@@ -128,11 +146,47 @@ func createWsConn() *WsConn {
|
||||
// 设置终端中断通道
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
// 解析域名
|
||||
hostArr := strings.Split(hostP, ":")
|
||||
// 判断是否有指定端口
|
||||
if len(hostArr) > 1 {
|
||||
// 判断是否为 IPv6
|
||||
if strings.HasPrefix(hostP, "[") {
|
||||
tmp := strings.Split(hostP, "]")
|
||||
host = tmp[0]
|
||||
host = host[1:]
|
||||
if port = tmp[1]; port != "" {
|
||||
port = port[1:]
|
||||
}
|
||||
} else {
|
||||
host, port = hostArr[0], hostArr[1]
|
||||
}
|
||||
} else {
|
||||
host = hostP
|
||||
}
|
||||
if port == "" {
|
||||
// 默认端口
|
||||
port = "443"
|
||||
}
|
||||
// 默认配置完成,开始寻找最优 IP
|
||||
fast_ip = GetFastIP(host, port)
|
||||
|
||||
u := url.URL{Scheme: "wss", Host: "api.leo.moe", Path: "/v2/ipGeoWs"}
|
||||
// 如果 host 是一个 IP 使用默认域名
|
||||
if valid := net.ParseIP(host); valid != nil {
|
||||
host = "api.leo.moe"
|
||||
}
|
||||
// 判断是否是一个 IP
|
||||
requestHeader := http.Header{
|
||||
"Host": []string{host},
|
||||
}
|
||||
dialer := websocket.DefaultDialer
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: host,
|
||||
}
|
||||
u := url.URL{Scheme: "wss", Host: fast_ip + ":" + port, Path: "/v2/ipGeoWs"}
|
||||
// log.Printf("connecting to %s", u.String())
|
||||
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
|
||||
|
||||
wsconn = &WsConn{
|
||||
Conn: c,
|
||||
|
||||
71
wshandle/latency.go
Normal file
71
wshandle/latency.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package wshandle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
var (
|
||||
result string
|
||||
results = make(chan string)
|
||||
)
|
||||
|
||||
func GetFastIP(domain string, port string) string {
|
||||
|
||||
ips, err := net.LookupIP(domain)
|
||||
if err != nil {
|
||||
log.Fatal("DNS resolution failed, please check your system DNS Settings")
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
go checkLatency(ip.String(), port)
|
||||
}
|
||||
|
||||
select {
|
||||
case result = <-results:
|
||||
case <-time.After(1 * time.Second):
|
||||
|
||||
}
|
||||
if result == "" {
|
||||
log.Fatal("IP connection has been timeout, please check your network")
|
||||
}
|
||||
res := strings.Split(result, "-")
|
||||
|
||||
if len(ips) > 1 {
|
||||
_, _ = fmt.Fprintf(color.Output, "%s prefered API IP - %s - %s\n",
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("[NextTrace API]"),
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", res[0]),
|
||||
color.New(color.FgCyan, color.Bold).Sprintf("%sms", res[1]),
|
||||
)
|
||||
}
|
||||
|
||||
return res[0]
|
||||
}
|
||||
|
||||
func checkLatency(ip string, port string) {
|
||||
start := time.Now()
|
||||
if !strings.Contains(ip, ".") {
|
||||
ip = "[" + ip + "]"
|
||||
}
|
||||
conn, err := net.DialTimeout("tcp", ip+":"+port, time.Second*1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func(conn net.Conn) {
|
||||
err := conn.Close()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}(conn)
|
||||
if result == "" {
|
||||
result = fmt.Sprintf("%s-%.2f", ip, float64(time.Since(start))/float64(time.Millisecond))
|
||||
results <- result
|
||||
return
|
||||
}
|
||||
}
|
||||
9
wshandle/latency_test.go
Normal file
9
wshandle/latency_test.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package wshandle
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetFastIP(t *testing.T) {
|
||||
GetFastIP("api.leo.moe", "443")
|
||||
}
|
||||
Reference in New Issue
Block a user