mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29ce61b24b | ||
|
|
701abc3447 | ||
|
|
f08778c862 | ||
|
|
8697325193 | ||
|
|
32b0f15e78 | ||
|
|
90e349eeed | ||
|
|
f275edba3a | ||
|
|
2974002c02 | ||
|
|
9b2fc9b570 | ||
|
|
960ab9687c | ||
|
|
07623ce4fd | ||
|
|
3164acfccf | ||
|
|
8b30ef39dd | ||
|
|
239b1c2f8d | ||
|
|
ed3c158e87 | ||
|
|
02348f08c0 | ||
|
|
9c7402accb | ||
|
|
a6848f8f23 | ||
|
|
29b7c668a4 | ||
|
|
86eacc006e | ||
|
|
81d6df8b82 | ||
|
|
dbe42d669c | ||
|
|
a7089e8d54 | ||
|
|
bcda750a66 | ||
|
|
1580c6111f | ||
|
|
a3ef1b2574 | ||
|
|
ba27ff967b | ||
|
|
b326d7bed6 | ||
|
|
b733ef2d82 | ||
|
|
2113264336 | ||
|
|
ba7d6ea87b | ||
|
|
db1e9e2b0c | ||
|
|
13aaa54067 | ||
|
|
db9b3fed9a | ||
|
|
7b145f4e64 | ||
|
|
d444ff3c62 | ||
|
|
f1ceaf7f86 | ||
|
|
d6536f7c69 | ||
|
|
ae2e6b3631 | ||
|
|
f63ef9552e | ||
|
|
ce1bae2125 | ||
|
|
9d3878efbe | ||
|
|
c940b9f19f | ||
|
|
2d6ae4ff4c | ||
|
|
7977383fec | ||
|
|
ae16731bbe | ||
|
|
e0ea009b2c | ||
|
|
c532dfd05c | ||
|
|
b967ee411d | ||
|
|
46ce56f3a7 | ||
|
|
bb522ed859 | ||
|
|
cdfe926c37 | ||
|
|
aa7cea4cf8 | ||
|
|
549dc549dd | ||
|
|
76fa8f2019 | ||
|
|
9e17f4a24f | ||
|
|
b06487e293 | ||
|
|
a0ab83c8ed | ||
|
|
9e5cd736c8 | ||
|
|
b11d2334c2 | ||
|
|
84a03e8a10 | ||
|
|
761d506613 | ||
|
|
c3ab3e6c1c | ||
|
|
96671d263c | ||
|
|
9228cdf307 | ||
|
|
12565941ab | ||
|
|
e33548d2ce | ||
|
|
5d766de52f | ||
|
|
ce46abd232 | ||
|
|
6179f1b8f0 | ||
|
|
3c12d99168 | ||
|
|
f3f99ac0aa | ||
|
|
cb7bc7450f | ||
|
|
74f46f5d24 | ||
|
|
2bc386355c | ||
|
|
1266f62aba | ||
|
|
8e837072c6 | ||
|
|
cf0639111d | ||
|
|
56cd0022f7 | ||
|
|
1407c499b9 | ||
|
|
f25662d481 | ||
|
|
4f94f01e87 | ||
|
|
1460ad67c0 | ||
|
|
d6dcfc8dc5 | ||
|
|
190b3ab94e | ||
|
|
87fa850d2d | ||
|
|
c71a26d018 | ||
|
|
79c39b655a | ||
|
|
580612ce08 | ||
|
|
141653a3e9 | ||
|
|
f59d7ff2f5 | ||
|
|
87f153cdf1 | ||
|
|
ebe2a0f8e9 | ||
|
|
ca2a7a8dc8 | ||
|
|
b68b768a65 | ||
|
|
efbede8ca1 | ||
|
|
b1edef305f | ||
|
|
54242cfa8b | ||
|
|
2d4de9e4c1 | ||
|
|
d75a384d70 | ||
|
|
f6fbf3803f |
@@ -26,15 +26,15 @@ for pl in ${PLATFORMS}; do
|
||||
echo "build => ${TARGET}"
|
||||
if [ "${DEBUG_MODE}" == "debug" ]; then
|
||||
go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
|
||||
-ldflags "-X 'github.com/xgadget-lab/nexttrace/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.CommitID=${COMMIT_SHA1}'\
|
||||
-ldflags "-X 'github.com/nxtrace/NTrace-core/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.CommitID=${COMMIT_SHA1}'\
|
||||
-w -s"
|
||||
else
|
||||
go build -trimpath -o ${TARGET} \
|
||||
-ldflags "-X 'github.com/xgadget-lab/nexttrace/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.CommitID=${COMMIT_SHA1}'\
|
||||
-ldflags "-X 'github.com/nxtrace/NTrace-core/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.CommitID=${COMMIT_SHA1}'\
|
||||
-w -s"
|
||||
fi
|
||||
done
|
||||
@@ -46,15 +46,15 @@ done
|
||||
echo "build => ${TARGET}"
|
||||
if [ "${DEBUG_MODE}" == "debug" ]; then
|
||||
go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
|
||||
-ldflags "-X 'github.com/xgadget-lab/nexttrace/printer.version=${BUILD_VERSION}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/printer.buildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/printer.commitID=${COMMIT_SHA1}'\
|
||||
-ldflags "-X 'github.com/nxtrace/NTrace-core/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.CommitID=${COMMIT_SHA1}'\
|
||||
-w -s"
|
||||
else
|
||||
go build -trimpath -o ${TARGET} \
|
||||
-ldflags "-X 'github.com/xgadget-lab/nexttrace/printer.version=${BUILD_VERSION}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/printer.buildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/printer.commitID=${COMMIT_SHA1}'\
|
||||
-ldflags "-X 'github.com/nxtrace/NTrace-core/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.CommitID=${COMMIT_SHA1}'\
|
||||
-w -s"
|
||||
fi
|
||||
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -15,7 +15,7 @@ copyright: [v2fly](https://github.com/v2fly)
|
||||
|
||||
<!--
|
||||
除非特殊情况,请完整填写所有问题。不按模板发的 issue 将直接被关闭。
|
||||
如果你遇到的问题不是 nexttrace 的 bug,比如你不清楚如何配置,请在 https://github.com/xgadget-lab/nexttrace/discussions 进行讨论。
|
||||
如果你遇到的问题不是 nexttrace 的 bug,比如你不清楚如何配置,请在 https://github.com/nxtrace/NTrace-core/discussions 进行讨论。
|
||||
-->
|
||||
|
||||
## 你正在使用哪个版本的 nexttrace?
|
||||
|
||||
28
.github/workflows/build.yml
vendored
28
.github/workflows/build.yml
vendored
@@ -75,6 +75,12 @@ jobs:
|
||||
goarch: mipsle
|
||||
- goos: linux
|
||||
goarch: mips
|
||||
- goos: linux
|
||||
goarch: mipsle
|
||||
gomips: softfloat
|
||||
- goos: linux
|
||||
goarch: mips
|
||||
gomips: softfloat
|
||||
# END MIPS
|
||||
# BEGIN PPC
|
||||
- goos: linux
|
||||
@@ -104,10 +110,11 @@ jobs:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
GOARM: ${{ matrix.goarm }}
|
||||
GOMIPS: ${{ matrix.gomips }}
|
||||
CGO_ENABLED: 0
|
||||
steps:
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Show workflow information
|
||||
run: |
|
||||
if [ ! -z $GOARM ]; then
|
||||
@@ -117,7 +124,10 @@ jobs:
|
||||
if [ "$GOOS" == "windows" ]; then
|
||||
export _NAME="$_NAME.exe"
|
||||
fi
|
||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, RELEASE_NAME: $_NAME"
|
||||
if [ "$GOMIPS" == "softfloat" ]; then
|
||||
export _NAME="${_NAME}_softfolat"
|
||||
fi
|
||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||
echo "BUILD_VERSION=$(git describe --tags --always)" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
@@ -125,15 +135,15 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
- name: Get project dependencies
|
||||
run: go mod download
|
||||
- name: Build
|
||||
run: |
|
||||
go build -trimpath -o dist/${ASSET_NAME} \
|
||||
-ldflags "-X 'github.com/xgadget-lab/nexttrace/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/xgadget-lab/nexttrace/config.CommitID=${COMMIT_SHA1}'\
|
||||
-ldflags "-X 'github.com/nxtrace/NTrace-core/config.Version=${BUILD_VERSION}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.BuildDate=${BUILD_DATE}' \
|
||||
-X 'github.com/nxtrace/NTrace-core/config.CommitID=${COMMIT_SHA1}'\
|
||||
-w -s"
|
||||
- name: Upload files to Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -145,7 +155,7 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with: # 将下述可执行文件 release 上去
|
||||
draft: false # Release草稿
|
||||
draft: true # Release草稿
|
||||
files: |
|
||||
dist/*
|
||||
env:
|
||||
@@ -166,7 +176,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/nxtrace/homebrew-nexttrace.git
|
||||
- name: Exec scipt
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
@@ -183,7 +193,7 @@ jobs:
|
||||
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 remote set-url origin https://${{ secrets.gt_token }}@github.com/nxtrace/homebrew-nexttrace.git
|
||||
git push
|
||||
# env:
|
||||
# SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
|
||||
4
.github/workflows/publishNewFormula.yml
vendored
4
.github/workflows/publishNewFormula.yml
vendored
@@ -21,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/nxtrace/homebrew-nexttrace.git
|
||||
- name: Exec scipt
|
||||
run: |
|
||||
cd homebrew-nexttrace
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
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 remote set-url origin https://${{ secrets.gt_token }}@github.com/nxtrace/homebrew-nexttrace.git
|
||||
git push
|
||||
# env:
|
||||
# SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -31,13 +31,13 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
check-latest: true
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Test with unix
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
run: sudo go test -v -coverprofile='coverage.out' -covermode=count ./...
|
||||
- name: Test with windows
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: go test -v -coverprofile='coverage.out' -covermode=count ./...
|
||||
run: go test -v -coverprofile='coverage.out' -covermode=count ./...
|
||||
|
||||
123
README.md
123
README.md
@@ -4,47 +4,82 @@
|
||||
|
||||
</div>
|
||||
|
||||
## NextTrace
|
||||
<h1 align="center">
|
||||
<br>NextTrace<br>
|
||||
</h1>
|
||||
|
||||
An open source visual routing tool that pursues light weight, developed using Golang.
|
||||
<h4 align="center">An open source visual routing tool that pursues light weight, developed using Golang.</h4>
|
||||
|
||||
NextTrace is part of the [OwO Network](https://github.com/OwO-Network) project. The project is a joint initiative of Leo and Vincent.
|
||||
<p align="center">
|
||||
<a href="https://github.com/nxtrace/Ntrace-V1/actions">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/nxtrace/Ntrace-V1/build.yml?branch=main&style=flat-square" alt="Github Actions">
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/github.com/nxtrace/Ntrace-V1">
|
||||
<img src="https://goreportcard.com/badge/github.com/nxtrace/Ntrace-V1?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/nxtrace/Ntrace-V1/releases">
|
||||
<img src="https://img.shields.io/github/release/nxtrace/Ntrace-V1/all.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://telegram.dog/sjprojects">
|
||||
<img src="https://img.shields.io/endpoint?color=neon&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fnexttrace">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
If you like this project, [Donate us](https://afdian.net/a/sjlleo/plan) to help us to provide long-lasting API cost expenses.
|
||||
## IAAS Sponsor
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="https://dmit.io">
|
||||
<img src="https://www.dmit.io/templates/dmit_theme_2020/dmit/assets/images/dmit_logo_with_text_blue.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
|
||||
<a href="https://misaka.io" >
|
||||
<img src="https://www.jsdelivr.com/assets/8997e39e1f9d776502ab4d7cdff9d1608aa67aaf/img/globalping/sponsors/misaka.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
|
||||
<a href="https://skywolf.cloud" >
|
||||
<img src="https://hk.skywolf.cloud/assets/img/skywolf.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
We are extremely grateful to [DMIT](https://dmit.io) and [Misaka](https://misaka.io) and [Skywolf](https://skywolf.cloud) for providing the network infrastructure that powers this project.
|
||||
|
||||
## How To Use
|
||||
|
||||
Document Language: English | [简体中文](README_zh_CN.md)
|
||||
|
||||
⚠️ Please note: We welcome PR submissions from the community, but please submit your PRs to the [NTrace-V1](https://github.com/nxtrace/NTrace-V1) repository instead of [NTrace-core](https://github.com/nxtrace/NTrace-core) repository.<br>
|
||||
Regarding the NTrace-V1 and NTrace-core repositories:<br>
|
||||
Both will largely remain consistent with each other. All development work is done within the NTrace-V1 repository. The NTrace-V1 repository releases new versions first. After running stably for an undetermined period, we will synchronize that version to NTrace-core. This means that the NTrace-V1 repository serves as a "beta" or "testing" version.<br>
|
||||
Please note, there are exceptions to this synchronization. If a version of NTrace-V1 encounters a serious bug, NTrace-core will skip that flawed version and synchronize directly to the next version that resolves the issue.
|
||||
|
||||
### Automated Install
|
||||
|
||||
* Linux
|
||||
* One-click installation script
|
||||
* Download from GitHub
|
||||
|
||||
```shell
|
||||
bash -c "$(curl -Ls https://github.com/sjlleo/nexttrace/raw/main/nt_install.sh)"
|
||||
```
|
||||
* GHPROXY mirror (For use in Mainland China)
|
||||
|
||||
```shell
|
||||
bash -c "$(curl -Ls https://ghproxy.com/https://github.com/sjlleo/nexttrace/raw/main/nt_install.sh)"
|
||||
```
|
||||
```shell
|
||||
bash -c "$(curl http://nexttrace-io-leomoe-api-a0.shop/nt_install_v1.sh)"
|
||||
```
|
||||
* Arch Linux AUR installation command
|
||||
* Build from source
|
||||
|
||||
```shell
|
||||
yay -S nexttrace
|
||||
```
|
||||
* Directly download bin package (only supports amd64)
|
||||
|
||||
```shell
|
||||
yay -S nexttrace-bin
|
||||
```
|
||||
* The two types of AUR builds are maintained by huyz and ouuan, respectively
|
||||
* The AUR builds are maintained by ouuan
|
||||
* Linuxbrew's installation command
|
||||
|
||||
Same as the macOS Homebrew's installation method (homebrew-core version only supports amd64)
|
||||
* Deepin installation command
|
||||
|
||||
```shell
|
||||
apt install nexttrace
|
||||
```
|
||||
* Termux installation command
|
||||
|
||||
```shell
|
||||
pkg install nexttrace-enhanced
|
||||
```
|
||||
|
||||
* macOS
|
||||
* macOS Homebrew's installation command
|
||||
@@ -56,7 +91,7 @@ Document Language: English | [简体中文](README_zh_CN.md)
|
||||
* This repository's ACTIONS automatically built version (updates faster)
|
||||
|
||||
```shell
|
||||
brew tap xgadget-lab/nexttrace && brew install nexttrace
|
||||
brew tap nxtrace/nexttrace && brew install nxtrace/nexttrace/nexttrace
|
||||
```
|
||||
* The homebrew-core build is maintained by chenrui333, please note that this version's updates may lag behind the repository Action automatically version
|
||||
|
||||
@@ -75,7 +110,7 @@ Document Language: English | [简体中文](README_zh_CN.md)
|
||||
### Manual Install
|
||||
* Download the precompiled executable
|
||||
|
||||
For users not covered by the above methods, please go directly to [Release](https://github.com/sjlleo/nexttrace/releases/latest) to download the compiled binary executable.
|
||||
For users not covered by the above methods, please go directly to [Release](https://github.com/nxtrace/Ntrace-V1/releases/latest) to download the compiled binary executable.
|
||||
|
||||
* `Release` provides compiled binary executables for many systems and different architectures. If none are available, you can compile it yourself.
|
||||
* Some essential dependencies of this project are not fully implemented on `Windows` by `Golang`, so currently, `NextTrace` is in an experimental support phase on the `Windows` platform.
|
||||
@@ -85,7 +120,7 @@ Document Language: English | [简体中文](README_zh_CN.md)
|
||||
After installing Go >= 1.20 yourself, you can use the following command to install
|
||||
|
||||
```shell
|
||||
go install github.com/xgadget-lab/nexttrace@latest
|
||||
go install github.com/nxtrace/Ntrace-V1@latest
|
||||
```
|
||||
After installation, the executable is in the `$GOPATH/bin` directory. If you have not set `GOPATH`, it is in the `$HOME/go/bin` directory.
|
||||
|
||||
@@ -117,6 +152,10 @@ nexttrace 2606:4700:4700::1111
|
||||
# Disable Path Visualization With the -M parameter
|
||||
nexttrace koreacentral.blob.core.windows.net
|
||||
# MapTrace URL: https://api.leo.moe/tracemap/html/c14e439e-3250-5310-8965-42a1e3545266.html
|
||||
|
||||
# Disable MPLS display using the --disable-mpls / -e parameter or the NEXTTRACE_DISABLEMPLS environment variable
|
||||
nexttrace --disable-mpls example.com
|
||||
export NEXTTRACE_DISABLEMPLS=1
|
||||
```
|
||||
|
||||
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).
|
||||
@@ -133,6 +172,17 @@ nexttrace --fast-trace
|
||||
|
||||
# You can also use TCP SYN for testing
|
||||
nexttrace --fast-trace --tcp
|
||||
|
||||
# You can also quickly test through a customized IP/DOMAIN list file
|
||||
nexttrace --file /path/to/your/iplist.txt
|
||||
# CUSTOMIZED IP DOMAIN LIST FILE FORMAT
|
||||
## One IP/DOMAIN per line + space + description information (optional)
|
||||
## forExample:
|
||||
## 106.37.67.1 BEIJING-TELECOM
|
||||
## 240e:928:101:31a::1 BEIJING-TELECOM
|
||||
## bj.10086.cn BEIJING-MOBILE
|
||||
## 2409:8080:0:1::1
|
||||
## 223.5.5.5
|
||||
```
|
||||
|
||||
`NextTrace` already supports route tracing for specified Network Devices
|
||||
@@ -237,7 +287,7 @@ NextTrace `LeoMoeAPI` now utilizes the Proof of Work (POW) mechanism to prevent
|
||||
- [GitHub - tsosunchia/powclient: Proof of Work CLIENT for NextTrace](https://github.com/tsosunchia/powclient)
|
||||
- [GitHub - tsosunchia/powserver: Proof of Work SERVER for NextTrace](https://github.com/tsosunchia/powserver)
|
||||
|
||||
All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
|
||||
All NextTrace IP geolocation `API DEMO` can refer to [here](https://github.com/nxtrace/NTrace-core/blob/main/ipgeo/)
|
||||
|
||||
### For full usage list, please refer to the usage menu
|
||||
|
||||
@@ -286,6 +336,9 @@ Arguments:
|
||||
IPInfo, IPInsight, IP-API.com, Ip2region,
|
||||
IPInfoLocal, CHUNZHEN, disable-geoip].
|
||||
Default: LeoMoeAPI
|
||||
--pow-provider Choose PoW Provider [api.leo.moe, sakura]
|
||||
For China mainland users, please use
|
||||
sakura. Default: api.leo.moe
|
||||
-n --no-rdns Do not resolve IP addresses to their
|
||||
domain names
|
||||
-a --always-rdns Always resolve IP addresses to their
|
||||
@@ -304,6 +357,7 @@ Arguments:
|
||||
-f --first Start from the first_ttl hop (instead from
|
||||
1). Default: 1
|
||||
-M --map Disable Print Trace Map
|
||||
-e --disable-mpls Disable MPLS
|
||||
-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
|
||||
@@ -327,6 +381,7 @@ Arguments:
|
||||
aliyun, dnspod, google, cloudflare]
|
||||
-g --language Choose the language for displaying [en,
|
||||
cn]. Default: cn
|
||||
--file Read IP Address or domain name from file
|
||||
```
|
||||
|
||||
## Project screenshot
|
||||
@@ -335,14 +390,6 @@ Arguments:
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||
Please Notice that `NextTrace Enhanced` is currently not supported in English.
|
||||
|
||||
[https://github.com/OwO-Network/nexttrace-enhanced](https://github.com/OwO-Network/nexttrace-enhanced)
|
||||
|
||||
## OpenTrace
|
||||
|
||||
`OpenTrace` is the cross-platform `GUI` version of `NextTrace` developed by @Archeb, bringing a familiar but more powerful user experience.
|
||||
@@ -351,6 +398,12 @@ This software is still in the early stages of development and may have many flaw
|
||||
|
||||
[https://github.com/Archeb/opentrace](https://github.com/Archeb/opentrace)
|
||||
|
||||
## NEXTTRACE WEB API
|
||||
|
||||
`NextTraceWebApi` is a web-based server implementation of `NextTrace` in the `MTR` style, offering various deployment options including `Docker`.
|
||||
|
||||
[https://github.com/nxtrace/nexttracewebapi](https://github.com/nxtrace/nexttracewebapi)
|
||||
|
||||
## LeoMoeAPI Credit
|
||||
|
||||
NextTrace focuses on Golang Traceroute implementations, and its LeoMoeAPI geolocation information is not supported by raw data, so a commercial version is not possible.
|
||||
@@ -376,6 +429,8 @@ We hope you can give us as much feedback as possible on IP geolocation errors (s
|
||||
|
||||
## Credits
|
||||
|
||||
[sjlleo](https://github.com/sjlleo) The perpetual leader, founder, and core contributors of the NextTrace Project
|
||||
|
||||
[BGP.TOOLS](https://bgp.tools) provided some data support for this project. And we would like to express our sincere gratitude.
|
||||
|
||||
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
|
||||
@@ -393,12 +448,12 @@ We hope you can give us as much feedback as possible on IP geolocation errors (s
|
||||
Although other third-party APIs are integrated in this project, please refer to the official website of the third-party APIs for specific TOS and AUP. If you encounter IP data errors, please contact them directly to correct them.
|
||||
|
||||
For feedback related to corrections about IP information, we currently have two channels available:
|
||||
>- [IP 错误报告汇总帖](https://github.com/sjlleo/nexttrace/issues/41) in the GITHUB ISSUES section of this project (Recommended)
|
||||
>- [IP 错误报告汇总帖](https://github.com/nxtrace/NTrace-core/issues/41) in the GITHUB ISSUES section of this project (Recommended)
|
||||
>- This project's dedicated correction email: `correction@moeqing.com` (Please note that this email is only for correcting IP-related information. For other feedback, please submit an ISSUE)
|
||||
|
||||
How to obtain the freshly baked binary executable of the latest commit?
|
||||
> Please go to the most recent [Build & Release](https://github.com/sjlleo/nexttrace/actions/workflows/build.yml) workflow in GitHub Actions.
|
||||
> Please go to the most recent [Build & Release](https://github.com/nxtrace/Ntrace-V1/actions/workflows/build.yml) workflow in GitHub Actions.
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#sjlleo/nexttrace&Date)
|
||||
[](https://star-history.com/#nxtrace/NTrace-core&Date)
|
||||
|
||||
136
README_zh_CN.md
136
README_zh_CN.md
@@ -12,54 +12,85 @@
|
||||
<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 href="https://github.com/nxtrace/Ntrace-V1/actions">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/nxtrace/Ntrace-V1/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 href="https://goreportcard.com/report/github.com/nxtrace/Ntrace-V1">
|
||||
<img src="https://goreportcard.com/badge/github.com/nxtrace/Ntrace-V1?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 href="https://github.com/nxtrace/Ntrace-V1/releases">
|
||||
<img src="https://img.shields.io/github/release/nxtrace/Ntrace-V1/all.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://telegram.dog/sjprojects">
|
||||
<img src="https://img.shields.io/endpoint?color=neon&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fnexttrace">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
如果您喜欢这个项目,可以通过[爱发电支持](https://afdian.net/a/sjlleo/plan)我们项目的持续发展,您的捐助将用于服务器和 API 开支,非常感谢!
|
||||
## IAAS Sponsor
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="https://dmit.io">
|
||||
<img src="https://www.dmit.io/templates/dmit_theme_2020/dmit/assets/images/dmit_logo_with_text_blue.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
|
||||
<a href="https://misaka.io" >
|
||||
<img src="https://www.jsdelivr.com/assets/8997e39e1f9d776502ab4d7cdff9d1608aa67aaf/img/globalping/sponsors/misaka.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
|
||||
<a href="https://skywolf.cloud" >
|
||||
<img src="https://hk.skywolf.cloud/assets/img/skywolf.svg" width="170.7" height="62.9">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
我们非常感谢 [DMIT](https://dmit.io) 和 [Misaka](https://misaka.io) 和 [Skywolf](https://skywolf.cloud) 提供了支持本项目所需的网络基础设施。
|
||||
|
||||
## How To Use
|
||||
|
||||
Document Language: [English](README.md) | 简体中文
|
||||
|
||||
⚠️ 请注意:我们欢迎来自社区的PR提交,但是请将您的PR提交至 [NTrace-V1](https://github.com/nxtrace/NTrace-V1) 仓库,而不是 [NTrace-core](https://github.com/nxtrace/NTrace-core) 仓库。<br>
|
||||
关于NTrace-V1和NTrace-core两个仓库的说明:<br>
|
||||
二者将大体上保持一致。所有的开发工作均在NTrace-V1仓库中进行。NTrace-V1仓库首先发布新版本,在稳定运行一段时间后(时长不定),我们会把版本同步至NTrace-core。这意味着NTrace-V1仓库充当了一个“测试版”的角色。<br>
|
||||
请注意,版本同步也存在例外。如果NTrace-V1的某个版本出现了严重的bug,NTrace-core会跳过这一有缺陷的版本,直接同步到下一个修复了该问题的版本。
|
||||
|
||||
### 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),在了解您自己的对数据精准度需求以后再进行抉择。
|
||||
使用 NextTrace 之前,我们建议您先阅读 [#IP 数据以及精准度说明](https://github.com/nxtrace/NTrace-core/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),在了解您自己的对数据精准度需求以后再进行抉择。
|
||||
|
||||
[NextTrace 的Telegram频道](https://t.me/nexttrace)由项目成员负责,会传递一部分通知,也会发布一些成员自己分享的小工具。项目成员的意见可作为未来项目发展的可能方向,随着开发进度变化可能会有所改动,不代表未来一定会实装,正式定稿公告会发布于 Issue 中。
|
||||
|
||||
### Automated Install
|
||||
|
||||
* Linux
|
||||
* 一键安装脚本
|
||||
* Github下载
|
||||
|
||||
```shell
|
||||
bash -c "$(curl -Ls https://github.com/sjlleo/nexttrace/raw/main/nt_install.sh)"
|
||||
```
|
||||
* GHPROXY镜像(中国大陆使用)
|
||||
|
||||
```shell
|
||||
bash -c "$(curl -Ls https://ghproxy.com/https://github.com/sjlleo/nexttrace/raw/main/nt_install.sh)"
|
||||
```
|
||||
```shell
|
||||
bash -c "$(curl http://nexttrace-io-leomoe-api-a0.shop/nt_install_v1.sh)"
|
||||
```
|
||||
|
||||
* Arch Linux AUR 安装命令
|
||||
* 由源码构建
|
||||
|
||||
```shell
|
||||
yay -S nexttrace
|
||||
```
|
||||
* 直接下载bin包(仅支持amd64)
|
||||
|
||||
```shell
|
||||
yay -S nexttrace-bin`
|
||||
```
|
||||
* AUR 的2种构建分别由 huyz 和 ouuan 维护
|
||||
* AUR 的构建分别由 ouuan 维护
|
||||
* Linuxbrew 安装命令
|
||||
|
||||
同macOS Homebrew安装方法(homebrew-core版仅支持amd64)
|
||||
* Deepin 安装命令
|
||||
|
||||
```shell
|
||||
apt install nexttrace
|
||||
```
|
||||
* Termux 安装命令
|
||||
|
||||
```shell
|
||||
pkg install nexttrace-enhanced
|
||||
```
|
||||
|
||||
|
||||
* macOS
|
||||
* macOS Homebrew 安装命令
|
||||
@@ -71,7 +102,7 @@
|
||||
* 本仓库ACTIONS自动构建版(更新更快)
|
||||
|
||||
```shell
|
||||
brew tap xgadget-lab/nexttrace && brew install nexttrace
|
||||
brew tap nxtrace/nexttrace && brew install nxtrace/nexttrace/nexttrace
|
||||
```
|
||||
* homebrew-core 构建由 chenrui333 维护,请注意该版本更新可能会落后仓库Action自动构建版本
|
||||
|
||||
@@ -90,7 +121,7 @@
|
||||
### Manual Install
|
||||
* 下载预编译的可执行程序
|
||||
|
||||
对于以上方法没有涵盖的用户,请直接前往 [Release](https://github.com/sjlleo/nexttrace/releases/latest) 下载编译后的二进制可执行文件。
|
||||
对于以上方法没有涵盖的用户,请直接前往 [Release](https://github.com/nxtrace/Ntrace-V1/releases/latest) 下载编译后的二进制可执行文件。
|
||||
|
||||
* `Release`里面为很多系统以及不同架构提供了编译好的二进制可执行文件,如果没有可以自行编译。
|
||||
* 一些本项目的必要依赖在`Windows`上`Golang`底层实现不完全,所以目前`NextTrace`在`Windows`平台出于实验性支持阶段。
|
||||
@@ -100,7 +131,7 @@
|
||||
您可在自行安装Go >= 1.20后,使用以下命令安装
|
||||
|
||||
```shell
|
||||
go install github.com/xgadget-lab/nexttrace@latest
|
||||
go install github.com/nxtrace/Ntrace-V1@latest
|
||||
```
|
||||
安装后可执行文件在`$GOPATH/bin`目录下,如果您没有设置`GOPATH`,则在`$HOME/go/bin`目录下。
|
||||
|
||||
@@ -132,6 +163,10 @@ nexttrace 2606:4700:4700::1111
|
||||
# 禁用路径可视化 使用 --map / -M 参数
|
||||
nexttrace koreacentral.blob.core.windows.net
|
||||
# MapTrace URL: https://api.leo.moe/tracemap/html/c14e439e-3250-5310-8965-42a1e3545266.html
|
||||
|
||||
# 禁用MPLS显示 使用 --disable-mpls / -e 参数 或 NEXTTRACE_DISABLEMPLS 环境变量
|
||||
nexttrace --disable-mpls example.com
|
||||
export NEXTTRACE_DISABLEMPLS=1
|
||||
```
|
||||
|
||||
PS: 路由可视化的绘制模块由 [@tsosunchia](https://github.com/tsosunchia) 同学编写,具体代码可在 [tsosunchia/traceMap](https://github.com/tsosunchia/traceMap) 查看
|
||||
@@ -148,6 +183,17 @@ nexttrace --fast-trace
|
||||
|
||||
# 也可以使用 TCP SYN 而非 ICMP 进行测试
|
||||
nexttrace --fast-trace --tcp
|
||||
|
||||
# 也可以通过自定义的IP/DOMAIN列表文件进行快速测试
|
||||
nexttrace --file /path/to/your/iplist.txt
|
||||
# 自定义的IP/DOMAIN列表文件格式
|
||||
## 一行一个IP/DOMAIN + 空格 + 描述信息(可选)
|
||||
## 例如:
|
||||
## 106.37.67.1 北京电信
|
||||
## 240e:928:101:31a::1 北京电信
|
||||
## bj.10086.cn 北京移动
|
||||
## 2409:8080:0:1::1
|
||||
## 223.5.5.5
|
||||
```
|
||||
|
||||
`NextTrace` 已支持指定网卡进行路由跟踪
|
||||
@@ -288,6 +334,9 @@ Arguments:
|
||||
IPInfo, IPInsight, IP-API.com, Ip2region,
|
||||
IPInfoLocal, CHUNZHEN, disable-geoip].
|
||||
Default: LeoMoeAPI
|
||||
--pow-provider Choose PoW Provider [api.leo.moe, sakura]
|
||||
For China mainland users, please use
|
||||
sakura. Default: api.leo.moe
|
||||
-n --no-rdns Do not resolve IP addresses to their
|
||||
domain names
|
||||
-a --always-rdns Always resolve IP addresses to their
|
||||
@@ -306,6 +355,7 @@ Arguments:
|
||||
-f --first Start from the first_ttl hop (instead from
|
||||
1). Default: 1
|
||||
-M --map Disable Print Trace Map
|
||||
-e --disable-mpls Disable MPLS
|
||||
-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
|
||||
@@ -329,6 +379,7 @@ Arguments:
|
||||
aliyun, dnspod, google, cloudflare]
|
||||
-g --language Choose the language for displaying [en,
|
||||
cn]. Default: cn
|
||||
--file Read IP Address or domain name from file
|
||||
```
|
||||
|
||||
## 项目截图
|
||||
@@ -339,7 +390,7 @@ Arguments:
|
||||
|
||||
## 第三方 IP 数据库 API 开发接口
|
||||
|
||||
NextTrace 所有的的 IP 地理位置 `API DEMO` 可以参考[这里](https://github.com/sjlleo/nexttrace/blob/main/ipgeo/)
|
||||
NextTrace 所有的的 IP 地理位置 `API DEMO` 可以参考[这里](https://github.com/nxtrace/NTrace-core/blob/main/ipgeo/)
|
||||
|
||||
你可以在这里添加你自己的 API 接口,为了 NextTrace 能够正确显示你接口中的内容,请参考 `leo.go` 中所需要的信息
|
||||
|
||||
@@ -351,11 +402,14 @@ NextTrace `LeoMoeAPI`现已使用Proof of Work(POW)机制来防止滥用,其
|
||||
- [GitHub - tsosunchia/powclient: Proof of Work CLIENT for NextTrace](https://github.com/tsosunchia/powclient)
|
||||
- [GitHub - tsosunchia/powserver: Proof of Work SERVER for NextTrace](https://github.com/tsosunchia/powserver)
|
||||
|
||||
```go
|
||||
|
||||
## NextTrace Enhanced
|
||||
|
||||
[https://github.com/OwO-Network/nexttrace-enhanced](https://github.com/OwO-Network/nexttrace-enhanced)
|
||||
对于中国大陆用户,可以使用 [Nya Labs](https://natfrp.com) 提供的位于大陆的POW服务器优化访问速度
|
||||
```shell
|
||||
#使用方法任选其一
|
||||
#1. 在环境变量中设置
|
||||
export NEXTTRACE_POWPROVIDER=sakura
|
||||
#2. 在命令行中设置
|
||||
nexttrace --pow-provider sakura
|
||||
```
|
||||
|
||||
## OpenTrace
|
||||
|
||||
@@ -365,8 +419,16 @@ NextTrace `LeoMoeAPI`现已使用Proof of Work(POW)机制来防止滥用,其
|
||||
|
||||
[https://github.com/Archeb/opentrace](https://github.com/Archeb/opentrace)
|
||||
|
||||
## NEXTTRACE WEB API
|
||||
|
||||
`NextTraceWebApi`是一个`MTR`风格的`NextTrace`网页版服务端实现,提供了包括`Docker`在内多种部署方式。
|
||||
|
||||
[https://github.com/nxtrace/nexttracewebapi](https://github.com/nxtrace/nexttracewebapi)
|
||||
|
||||
## Credits
|
||||
|
||||
[sjlleo](https://github.com/sjlleo) NextTrace 项目永远的领导者、创始人及核心贡献者
|
||||
|
||||
[BGP.TOOLS](https://bgp.tools) 提供了本项目的一些数据支持,在此表示由衷地感谢。
|
||||
|
||||
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
|
||||
@@ -384,12 +446,12 @@ NextTrace `LeoMoeAPI`现已使用Proof of Work(POW)机制来防止滥用,其
|
||||
其他第三方 API 尽管集成在本项目内,但是具体的 TOS 以及 AUP,请详见第三方 API 官网。如遇到 IP 数据错误,也请直接联系他们纠错。
|
||||
|
||||
如何获取最新commit的新鲜出炉的二进制可执行文件?
|
||||
>请前往GitHub Actions中最新一次 [Build & Release](https://github.com/sjlleo/nexttrace/actions/workflows/build.yml) workflow.
|
||||
>请前往GitHub Actions中最新一次 [Build & Release](https://github.com/nxtrace/Ntrace-V1/actions/workflows/build.yml) workflow.
|
||||
|
||||
## IP 数据以及精准度说明
|
||||
|
||||
对于IP相关信息的纠错反馈,我们目前开放了两个渠道:
|
||||
>- 本项目的GITHUB ISSUES区中的[IP 错误报告汇总帖](https://github.com/sjlleo/nexttrace/issues/41)
|
||||
>- 本项目的GITHUB ISSUES区中的[IP 错误报告汇总帖](https://github.com/nxtrace/NTrace-core/issues/41)
|
||||
>- 本项目的纠错专用邮箱: `correction@moeqing.com` (请注意此邮箱仅供IP相关信息纠错专用,其他反馈请发送ISSUE)
|
||||
|
||||
NextTrace 有多个数据源可以选择,目前默认使用的 LeoMoeAPI 为我们项目维护的数据源。
|
||||
@@ -447,3 +509,9 @@ LAX,US,California,Los Anegles
|
||||
```
|
||||
|
||||
需要注意的是,NextTrace 支持自动匹配 CSV 中的城市名,如果您的 PTR 记录中有 `losangeles`,您可以只添加上面一条记录就可以正常识别并读取。
|
||||
|
||||
rkflow in GitHub Actions.
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#nxtrace/NTrace-core&Date)
|
||||
|
||||
61
cmd/cmd.go
61
cmd/cmd.go
@@ -12,17 +12,17 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/akamensky/argparse"
|
||||
"github.com/nxtrace/NTrace-core/config"
|
||||
fastTrace "github.com/nxtrace/NTrace-core/fast_trace"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/printer"
|
||||
"github.com/nxtrace/NTrace-core/reporter"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
"github.com/nxtrace/NTrace-core/tracelog"
|
||||
"github.com/nxtrace/NTrace-core/tracemap"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"github.com/nxtrace/NTrace-core/wshandle"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
"github.com/xgadget-lab/nexttrace/config"
|
||||
fastTrace "github.com/xgadget-lab/nexttrace/fast_trace"
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/printer"
|
||||
"github.com/xgadget-lab/nexttrace/reporter"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/xgadget-lab/nexttrace/tracelog"
|
||||
"github.com/xgadget-lab/nexttrace/tracemap"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/xgadget-lab/nexttrace/wshandle"
|
||||
)
|
||||
|
||||
func Excute() {
|
||||
@@ -41,6 +41,8 @@ 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{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal", "chunzhen", "LeoMoeAPI", "leomoeapi", "disable-geoip"}, &argparse.Options{Default: "LeoMoeAPI",
|
||||
Help: "Choose IP Geograph Data Provider [IP.SB, IPInfo, IPInsight, IP-API.com, Ip2region, IPInfoLocal, CHUNZHEN, disable-geoip]"})
|
||||
powProvider := parser.Selector("", "pow-provider", []string{"api.leo.moe", "sakura"}, &argparse.Options{Default: "api.leo.moe",
|
||||
Help: "Choose PoW Provider [api.leo.moe, sakura] For China mainland users, please use sakura"})
|
||||
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"})
|
||||
@@ -53,6 +55,7 @@ func Excute() {
|
||||
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)"})
|
||||
disableMaptrace := parser.Flag("M", "map", &argparse.Options{Help: "Disable Print Trace Map"})
|
||||
disableMPLS := parser.Flag("e", "disable-mpls", &argparse.Options{Help: "Disable MPLS"})
|
||||
ver := parser.Flag("v", "version", &argparse.Options{Help: "Print version info and exit"})
|
||||
srcAddr := parser.String("s", "source", &argparse.Options{Help: "Use source src_addr for outgoing packets"})
|
||||
srcDev := parser.String("D", "dev", &argparse.Options{Help: "Use the following Network Devices as the source address in outgoing packets"})
|
||||
@@ -66,6 +69,7 @@ func Excute() {
|
||||
Help: "Use DoT Server for DNS Parse [dnssb, aliyun, dnspod, google, cloudflare]"})
|
||||
lang := parser.Selector("g", "language", []string{"en", "cn"}, &argparse.Options{Default: "cn",
|
||||
Help: "Choose the language for displaying [en, cn]"})
|
||||
file := parser.String("", "file", &argparse.Options{Help: "Read IP Address or domain name from file"})
|
||||
|
||||
err := parser.Parse(os.Args)
|
||||
if err != nil {
|
||||
@@ -88,7 +92,7 @@ func Excute() {
|
||||
*port = 80
|
||||
}
|
||||
|
||||
if *fast_trace {
|
||||
if *fast_trace || *file != "" {
|
||||
var paramsFastTrace = fastTrace.ParamsFastTrace{
|
||||
SrcDev: *srcDev,
|
||||
SrcAddr: *srcAddr,
|
||||
@@ -99,6 +103,7 @@ func Excute() {
|
||||
Lang: *lang,
|
||||
PktSize: *packetSize,
|
||||
Timeout: time.Duration(*timeout) * time.Millisecond,
|
||||
File: *file,
|
||||
}
|
||||
|
||||
fastTrace.FastTest(*tcp, *output, paramsFastTrace)
|
||||
@@ -155,6 +160,9 @@ func Excute() {
|
||||
// defer wg.Done()
|
||||
if strings.ToUpper(*dataOrigin) == "LEOMOEAPI" {
|
||||
val, ok := os.LookupEnv("NEXTTRACE_DATAPROVIDER")
|
||||
if strings.ToUpper(*powProvider) != "API.LEO.MOE" {
|
||||
util.PowProviderParam = *powProvider
|
||||
}
|
||||
if ok {
|
||||
*dataOrigin = val
|
||||
} else {
|
||||
@@ -170,32 +178,44 @@ func Excute() {
|
||||
//
|
||||
//go func() {
|
||||
// defer wg.Done()
|
||||
err = nil
|
||||
if *udp {
|
||||
if *ipv6Only {
|
||||
fmt.Println("[Info] IPv6 UDP Traceroute is not supported right now.")
|
||||
os.Exit(0)
|
||||
}
|
||||
ip = util.DomainLookUp(domain, "4", *dot, *jsonPrint)
|
||||
ip, err = util.DomainLookUp(domain, "4", *dot, *jsonPrint)
|
||||
} else {
|
||||
if *ipv6Only {
|
||||
ip = util.DomainLookUp(domain, "6", *dot, *jsonPrint)
|
||||
ip, err = util.DomainLookUp(domain, "6", *dot, *jsonPrint)
|
||||
} else if *ipv4Only {
|
||||
ip = util.DomainLookUp(domain, "4", *dot, *jsonPrint)
|
||||
ip, err = util.DomainLookUp(domain, "4", *dot, *jsonPrint)
|
||||
} else {
|
||||
ip = util.DomainLookUp(domain, "all", *dot, *jsonPrint)
|
||||
ip, err = util.DomainLookUp(domain, "all", *dot, *jsonPrint)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
//}()
|
||||
//
|
||||
//wg.Wait()
|
||||
|
||||
if *srcDev != "" {
|
||||
dev, _ := net.InterfaceByName(*srcDev)
|
||||
|
||||
if addrs, err := dev.Addrs(); err == nil {
|
||||
for _, addr := range addrs {
|
||||
if (addr.(*net.IPNet).IP.To4() == nil) == (ip.To4() == nil) {
|
||||
*srcAddr = addr.(*net.IPNet).IP.String()
|
||||
// 检查是否是内网IP
|
||||
if !(net.ParseIP(*srcAddr).IsPrivate() ||
|
||||
net.ParseIP(*srcAddr).IsLoopback() ||
|
||||
net.ParseIP(*srcAddr).IsLinkLocalUnicast() ||
|
||||
net.ParseIP(*srcAddr).IsLinkLocalMulticast()) {
|
||||
// 若不是则跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +225,7 @@ func Excute() {
|
||||
printer.PrintTraceRouteNav(ip, domain, *dataOrigin, *maxHops, *packetSize)
|
||||
}
|
||||
|
||||
var m trace.Method = ""
|
||||
var m trace.Method
|
||||
|
||||
switch {
|
||||
case *tcp:
|
||||
@@ -274,6 +294,10 @@ func Excute() {
|
||||
}
|
||||
}
|
||||
|
||||
if *disableMPLS {
|
||||
util.DisableMPLS = "1"
|
||||
}
|
||||
|
||||
res, err := trace.Traceroute(m, conf)
|
||||
|
||||
if err != nil {
|
||||
@@ -294,7 +318,8 @@ func Excute() {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
if !*disableMaptrace && strings.ToUpper(*dataOrigin) == "LEOMOEAPI" {
|
||||
if !*disableMaptrace &&
|
||||
(util.StringInSlice(strings.ToUpper(*dataOrigin), []string{"LEOMOEAPI", "IPINFO", "IPINFO", "IP-API.COM", "IPAPI.COM"})) {
|
||||
url, err := tracemap.GetMapUrl(string(r))
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
|
||||
@@ -175,12 +175,12 @@ var Hefei = BackBoneCollection{
|
||||
// 中国科学技术大学 教育网
|
||||
EDU: ISPCollection{
|
||||
ISPName: EDU,
|
||||
IP: "ipv4.hef-4538.nexttrace-io-fasttrace-endpoint.win.",
|
||||
IPv6: "ipv6.hef-4538.nexttrace-io-fasttrace-endpoint.win.",
|
||||
IP: "ipv4.hfe-4538.nexttrace-io-fasttrace-endpoint.win.",
|
||||
IPv6: "ipv6.hfe-4538.nexttrace-io-fasttrace-endpoint.win.",
|
||||
},
|
||||
// 中国科学技术大学 科技网
|
||||
CST: ISPCollection{
|
||||
ISPName: "中国科学技术大学 科技网 AS7497",
|
||||
IP: "ipv4.hef-7497.nexttrace-io-fasttrace-endpoint.win.",
|
||||
IP: "ipv4.hfe-7497.nexttrace-io-fasttrace-endpoint.win.",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,56 +2,60 @@ package fastTrace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/printer"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/xgadget-lab/nexttrace/tracelog"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/xgadget-lab/nexttrace/wshandle"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/printer"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
"github.com/nxtrace/NTrace-core/tracelog"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"github.com/nxtrace/NTrace-core/wshandle"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
)
|
||||
|
||||
var pFastTracer ParamsFastTrace
|
||||
//var pFastTracer ParamsFastTrace
|
||||
|
||||
func (f *FastTracer) tracert_v6(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 func(fp *os.File) {
|
||||
err := fp.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(fp)
|
||||
|
||||
log.SetOutput(fp)
|
||||
log.SetFlags(0)
|
||||
fmt.Printf("%s『%s %s 』%s\n", printer.YELLOW_PREFIX, location, ispCollection.ISPName, printer.RESET_PREFIX)
|
||||
log.Printf("『%s %s 』\n", location, ispCollection.ISPName)
|
||||
fmt.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IPv6, pFastTracer.MaxHops, pFastTracer.PktSize)
|
||||
log.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IPv6, pFastTracer.MaxHops, pFastTracer.PktSize)
|
||||
ip := util.DomainLookUp(ispCollection.IPv6, "6", "", true)
|
||||
fmt.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IPv6, f.ParamsFastTrace.MaxHops, f.ParamsFastTrace.PktSize)
|
||||
|
||||
ip, err := util.DomainLookUp(ispCollection.IPv6, "6", "", true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var conf = trace.Config{
|
||||
BeginHop: pFastTracer.BeginHop,
|
||||
BeginHop: f.ParamsFastTrace.BeginHop,
|
||||
DestIP: ip,
|
||||
DestPort: 80,
|
||||
MaxHops: pFastTracer.MaxHops,
|
||||
MaxHops: f.ParamsFastTrace.MaxHops,
|
||||
NumMeasurements: 3,
|
||||
ParallelRequests: 18,
|
||||
RDns: pFastTracer.RDns,
|
||||
AlwaysWaitRDNS: pFastTracer.AlwaysWaitRDNS,
|
||||
RDns: f.ParamsFastTrace.RDns,
|
||||
AlwaysWaitRDNS: f.ParamsFastTrace.AlwaysWaitRDNS,
|
||||
PacketInterval: 100,
|
||||
TTLInterval: 500,
|
||||
IPGeoSource: ipgeo.GetSource("LeoMoeAPI"),
|
||||
Timeout: pFastTracer.Timeout,
|
||||
PktSize: pFastTracer.PktSize,
|
||||
Lang: pFastTracer.Lang,
|
||||
Timeout: f.ParamsFastTrace.Timeout,
|
||||
SrcAddr: f.ParamsFastTrace.SrcAddr,
|
||||
PktSize: f.ParamsFastTrace.PktSize,
|
||||
Lang: f.ParamsFastTrace.Lang,
|
||||
}
|
||||
|
||||
if oe {
|
||||
fp, err := os.OpenFile("/tmp/trace.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func(fp *os.File) {
|
||||
err := fp.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(fp)
|
||||
log.SetOutput(fp)
|
||||
log.SetFlags(0)
|
||||
log.Printf("『%s %s 』\n", location, ispCollection.ISPName)
|
||||
log.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IPv6, f.ParamsFastTrace.MaxHops, f.ParamsFastTrace.PktSize)
|
||||
conf.RealtimePrinter = tracelog.RealtimePrinter
|
||||
} else {
|
||||
conf.RealtimePrinter = printer.RealtimePrinter
|
||||
@@ -63,7 +67,7 @@ func (f *FastTracer) tracert_v6(location string, ispCollection ISPCollection) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
println()
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func (f *FastTracer) testAll_v6() {
|
||||
@@ -103,20 +107,28 @@ func (f *FastTracer) testEDU_v6() {
|
||||
f.tracert_v6(TestIPsCollection.Hangzhou.Location, TestIPsCollection.Hangzhou.EDU)
|
||||
}
|
||||
|
||||
func (f *FastTracer) testFast_v6() {
|
||||
f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CT163)
|
||||
f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CU169)
|
||||
f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CM)
|
||||
f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.EDU)
|
||||
}
|
||||
|
||||
func FastTestv6(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
var c string
|
||||
|
||||
oe = outEnable
|
||||
pFastTracer = paramsFastTrace
|
||||
|
||||
fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网")
|
||||
fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网\n6. 全部")
|
||||
fmt.Print("请选择选项:")
|
||||
_, err := fmt.Scanln(&c)
|
||||
if err != nil {
|
||||
c = "1"
|
||||
}
|
||||
|
||||
ft := FastTracer{}
|
||||
ft := FastTracer{
|
||||
ParamsFastTrace: paramsFastTrace,
|
||||
}
|
||||
|
||||
// 建立 WebSocket 连接
|
||||
w := wshandle.New()
|
||||
@@ -135,7 +147,7 @@ func FastTestv6(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
|
||||
switch c {
|
||||
case "1":
|
||||
ft.testAll_v6()
|
||||
ft.testFast_v6()
|
||||
case "2":
|
||||
ft.testCT_v6()
|
||||
case "3":
|
||||
@@ -144,7 +156,9 @@ func FastTestv6(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
ft.testCM_v6()
|
||||
case "5":
|
||||
ft.testEDU_v6()
|
||||
default:
|
||||
case "6":
|
||||
ft.testAll_v6()
|
||||
default:
|
||||
ft.testFast_v6()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package fastTrace
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/printer"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/xgadget-lab/nexttrace/tracelog"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/xgadget-lab/nexttrace/wshandle"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/printer"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
"github.com/nxtrace/NTrace-core/tracelog"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"github.com/nxtrace/NTrace-core/wshandle"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -30,29 +32,25 @@ type ParamsFastTrace struct {
|
||||
Lang string
|
||||
PktSize int
|
||||
Timeout time.Duration
|
||||
File string
|
||||
}
|
||||
|
||||
type IpListElement struct {
|
||||
Ip string
|
||||
Desc string
|
||||
Version4 bool // true for IPv4, false for IPv6
|
||||
}
|
||||
|
||||
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 func(fp *os.File) {
|
||||
err := fp.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(fp)
|
||||
|
||||
log.SetOutput(fp)
|
||||
log.SetFlags(0)
|
||||
fmt.Printf("%s『%s %s 』%s\n", printer.YELLOW_PREFIX, location, ispCollection.ISPName, printer.RESET_PREFIX)
|
||||
log.Printf("『%s %s 』\n", location, ispCollection.ISPName)
|
||||
fmt.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IP, f.ParamsFastTrace.MaxHops, f.ParamsFastTrace.PktSize)
|
||||
log.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IP, f.ParamsFastTrace.MaxHops, f.ParamsFastTrace.PktSize)
|
||||
ip := util.DomainLookUp(ispCollection.IP, "4", "", true)
|
||||
|
||||
ip, err := util.DomainLookUp(ispCollection.IP, "4", "", true)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
var conf = trace.Config{
|
||||
BeginHop: f.ParamsFastTrace.BeginHop,
|
||||
DestIP: ip,
|
||||
@@ -72,6 +70,21 @@ func (f *FastTracer) tracert(location string, ispCollection ISPCollection) {
|
||||
}
|
||||
|
||||
if oe {
|
||||
fp, err := os.OpenFile("/tmp/trace.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func(fp *os.File) {
|
||||
err := fp.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(fp)
|
||||
|
||||
log.SetOutput(fp)
|
||||
log.SetFlags(0)
|
||||
log.Printf("『%s %s 』\n", location, ispCollection.ISPName)
|
||||
log.Printf("traceroute to %s, %d hops max, %d byte packets\n", ispCollection.IP, f.ParamsFastTrace.MaxHops, f.ParamsFastTrace.PktSize)
|
||||
conf.RealtimePrinter = tracelog.RealtimePrinter
|
||||
} else {
|
||||
conf.RealtimePrinter = printer.RealtimePrinter
|
||||
@@ -82,13 +95,19 @@ func (f *FastTracer) tracert(location string, ispCollection ISPCollection) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
println()
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func FastTest(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
// tm means tcp mode
|
||||
var c string
|
||||
pFastTrace := paramsFastTrace
|
||||
oe = outEnable
|
||||
|
||||
if paramsFastTrace.File != "" {
|
||||
testFile(paramsFastTrace, tm)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Hi,欢迎使用 Fast Trace 功能,请注意 Fast Trace 功能只适合新手使用\n因为国内网络复杂,我们设置的测试目标有限,建议普通用户自测以获得更加精准的路由情况")
|
||||
fmt.Println("请您选择要测试的 IP 类型\n1. IPv4\n2. IPv6")
|
||||
fmt.Print("请选择选项:")
|
||||
@@ -97,22 +116,47 @@ func FastTest(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
c = "1"
|
||||
}
|
||||
if c == "2" {
|
||||
if paramsFastTrace.SrcDev != "" {
|
||||
dev, _ := net.InterfaceByName(paramsFastTrace.SrcDev)
|
||||
if addrs, err := dev.Addrs(); err == nil {
|
||||
for _, addr := range addrs {
|
||||
if (addr.(*net.IPNet).IP.To4() == nil) == true {
|
||||
paramsFastTrace.SrcAddr = addr.(*net.IPNet).IP.String()
|
||||
// 检查是否是内网IP
|
||||
if !(net.ParseIP(paramsFastTrace.SrcAddr).IsPrivate() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLoopback() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLinkLocalUnicast() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLinkLocalMulticast()) {
|
||||
// 若不是则跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FastTestv6(tm, outEnable, paramsFastTrace)
|
||||
return
|
||||
}
|
||||
|
||||
if pFastTrace.SrcDev != "" {
|
||||
dev, _ := net.InterfaceByName(pFastTrace.SrcDev)
|
||||
if paramsFastTrace.SrcDev != "" {
|
||||
dev, _ := net.InterfaceByName(paramsFastTrace.SrcDev)
|
||||
if addrs, err := dev.Addrs(); err == nil {
|
||||
for _, addr := range addrs {
|
||||
if addr.(*net.IPNet).IP.To4() != nil {
|
||||
pFastTrace.SrcAddr = addr.(*net.IPNet).IP.String()
|
||||
if (addr.(*net.IPNet).IP.To4() == nil) == false {
|
||||
paramsFastTrace.SrcAddr = addr.(*net.IPNet).IP.String()
|
||||
// 检查是否是内网IP
|
||||
if !(net.ParseIP(paramsFastTrace.SrcAddr).IsPrivate() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLoopback() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLinkLocalUnicast() ||
|
||||
net.ParseIP(paramsFastTrace.SrcAddr).IsLinkLocalMulticast()) {
|
||||
// 若不是则跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网")
|
||||
fmt.Println("您想测试哪些ISP的路由?\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网\n6. 全部")
|
||||
fmt.Print("请选择选项:")
|
||||
_, err = fmt.Scanln(&c)
|
||||
if err != nil {
|
||||
@@ -120,7 +164,7 @@ func FastTest(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
}
|
||||
|
||||
ft := FastTracer{
|
||||
ParamsFastTrace: pFastTrace,
|
||||
ParamsFastTrace: paramsFastTrace,
|
||||
}
|
||||
|
||||
// 建立 WebSocket 连接
|
||||
@@ -140,7 +184,7 @@ func FastTest(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
|
||||
switch c {
|
||||
case "1":
|
||||
ft.testAll()
|
||||
ft.testFast()
|
||||
case "2":
|
||||
ft.testCT()
|
||||
case "3":
|
||||
@@ -149,11 +193,178 @@ func FastTest(tm bool, outEnable bool, paramsFastTrace ParamsFastTrace) {
|
||||
ft.testCM()
|
||||
case "5":
|
||||
ft.testEDU()
|
||||
default:
|
||||
case "6":
|
||||
ft.testAll()
|
||||
default:
|
||||
ft.testFast()
|
||||
}
|
||||
}
|
||||
|
||||
func testFile(paramsFastTrace ParamsFastTrace, tm bool) {
|
||||
// 建立 WebSocket 连接
|
||||
w := wshandle.New()
|
||||
w.Interrupt = make(chan os.Signal, 1)
|
||||
signal.Notify(w.Interrupt, os.Interrupt)
|
||||
defer func() {
|
||||
w.Conn.Close()
|
||||
}()
|
||||
|
||||
var tracerouteMethod trace.Method
|
||||
if !tm {
|
||||
tracerouteMethod = trace.ICMPTrace
|
||||
fmt.Println("您将默认使用ICMP协议进行路由跟踪,如果您想使用TCP SYN进行路由跟踪,可以加入 -T 参数")
|
||||
} else {
|
||||
tracerouteMethod = trace.TCPTrace
|
||||
}
|
||||
|
||||
filePath := paramsFastTrace.File
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file:", err)
|
||||
return
|
||||
}
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(file)
|
||||
var ipList []IpListElement
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.SplitN(line, " ", 2)
|
||||
|
||||
var ip, desc string
|
||||
if len(parts) == 2 {
|
||||
ip = parts[0]
|
||||
desc = parts[1]
|
||||
} else if len(parts) == 1 {
|
||||
ip = parts[0]
|
||||
desc = ip // Set the description to the IP if no description is provided
|
||||
} else {
|
||||
fmt.Printf("Ignoring invalid line: %s\n", line)
|
||||
continue
|
||||
}
|
||||
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
netIp, err := util.DomainLookUp(ip, "all", "", true)
|
||||
if err != nil {
|
||||
fmt.Printf("Ignoring invalid IP: %s\n", ip)
|
||||
continue
|
||||
}
|
||||
if len(parts) == 1 {
|
||||
desc = ip
|
||||
}
|
||||
ip = netIp.String()
|
||||
}
|
||||
|
||||
ipElem := IpListElement{
|
||||
Ip: ip,
|
||||
Desc: desc,
|
||||
Version4: strings.Contains(ip, "."),
|
||||
}
|
||||
|
||||
ipList = append(ipList, ipElem)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Println("Error reading file:", err)
|
||||
}
|
||||
|
||||
for _, ip := range ipList {
|
||||
fmt.Printf("%s『%s』%s\n", printer.YELLOW_PREFIX, ip.Desc, printer.RESET_PREFIX)
|
||||
fmt.Printf("traceroute to %s, %d hops max, %d byte packets\n", ip.Ip, paramsFastTrace.MaxHops, paramsFastTrace.PktSize)
|
||||
var srcAddr string
|
||||
if ip.Version4 {
|
||||
if paramsFastTrace.SrcDev != "" {
|
||||
dev, _ := net.InterfaceByName(paramsFastTrace.SrcDev)
|
||||
if addrs, err := dev.Addrs(); err == nil {
|
||||
for _, addr := range addrs {
|
||||
if (addr.(*net.IPNet).IP.To4() == nil) == false {
|
||||
srcAddr = addr.(*net.IPNet).IP.String()
|
||||
// 检查是否是内网IP
|
||||
if !(net.ParseIP(srcAddr).IsPrivate() ||
|
||||
net.ParseIP(srcAddr).IsLoopback() ||
|
||||
net.ParseIP(srcAddr).IsLinkLocalUnicast() ||
|
||||
net.ParseIP(srcAddr).IsLinkLocalMulticast()) {
|
||||
// 若不是则跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if paramsFastTrace.SrcDev != "" {
|
||||
dev, _ := net.InterfaceByName(paramsFastTrace.SrcDev)
|
||||
if addrs, err := dev.Addrs(); err == nil {
|
||||
for _, addr := range addrs {
|
||||
if (addr.(*net.IPNet).IP.To4() == nil) == true {
|
||||
srcAddr = addr.(*net.IPNet).IP.String()
|
||||
// 检查是否是内网IP
|
||||
if !(net.ParseIP(srcAddr).IsPrivate() ||
|
||||
net.ParseIP(srcAddr).IsLoopback() ||
|
||||
net.ParseIP(srcAddr).IsLinkLocalUnicast() ||
|
||||
net.ParseIP(srcAddr).IsLinkLocalMulticast()) {
|
||||
// 若不是则跳出
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var conf = trace.Config{
|
||||
BeginHop: paramsFastTrace.BeginHop,
|
||||
DestIP: net.ParseIP(ip.Ip),
|
||||
DestPort: 80,
|
||||
MaxHops: paramsFastTrace.MaxHops,
|
||||
NumMeasurements: 3,
|
||||
ParallelRequests: 18,
|
||||
RDns: paramsFastTrace.RDns,
|
||||
AlwaysWaitRDNS: paramsFastTrace.AlwaysWaitRDNS,
|
||||
PacketInterval: 100,
|
||||
TTLInterval: 500,
|
||||
IPGeoSource: ipgeo.GetSource("LeoMoeAPI"),
|
||||
Timeout: paramsFastTrace.Timeout,
|
||||
SrcAddr: srcAddr,
|
||||
PktSize: paramsFastTrace.PktSize,
|
||||
Lang: paramsFastTrace.Lang,
|
||||
}
|
||||
|
||||
if oe {
|
||||
fp, err := os.OpenFile("/tmp/trace.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer func(fp *os.File) {
|
||||
err := fp.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(fp)
|
||||
|
||||
log.SetOutput(fp)
|
||||
log.SetFlags(0)
|
||||
log.Printf("『%s』\n", ip.Desc)
|
||||
log.Printf("traceroute to %s, %d hops max, %d byte packets\n", ip.Ip, paramsFastTrace.MaxHops, paramsFastTrace.PktSize)
|
||||
conf.RealtimePrinter = tracelog.RealtimePrinter
|
||||
} else {
|
||||
conf.RealtimePrinter = printer.RealtimePrinter
|
||||
}
|
||||
|
||||
_, err := trace.Traceroute(tracerouteMethod, conf)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (f *FastTracer) testAll() {
|
||||
f.testCT()
|
||||
println()
|
||||
@@ -197,3 +408,10 @@ func (f *FastTracer) testEDU() {
|
||||
// 科技网暂时算在EDU里面,等拿到了足够多的数据再分离出去,单独用于测试
|
||||
f.tracert(TestIPsCollection.Hefei.Location, TestIPsCollection.Hefei.CST)
|
||||
}
|
||||
|
||||
func (f *FastTracer) testFast() {
|
||||
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CT163)
|
||||
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CU169)
|
||||
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CM)
|
||||
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.EDU)
|
||||
}
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
package fastTrace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"testing"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/xgadget-lab/nexttrace/wshandle"
|
||||
)
|
||||
|
||||
func TestTrace(t *testing.T) {
|
||||
pFastTrace := ParamsFastTrace{
|
||||
SrcDev: "",
|
||||
SrcAddr: "",
|
||||
BeginHop: 1,
|
||||
MaxHops: 30,
|
||||
RDns: false,
|
||||
AlwaysWaitRDNS: false,
|
||||
Lang: "",
|
||||
PktSize: 52,
|
||||
}
|
||||
ft := FastTracer{ParamsFastTrace: pFastTrace}
|
||||
// 建立 WebSocket 连接
|
||||
w := wshandle.New()
|
||||
w.Interrupt = make(chan os.Signal, 1)
|
||||
signal.Notify(w.Interrupt, os.Interrupt)
|
||||
defer func() {
|
||||
w.Conn.Close()
|
||||
}()
|
||||
fmt.Println("TCP v4")
|
||||
ft.TracerouteMethod = trace.TCPTrace
|
||||
//pFastTrace := ParamsFastTrace{
|
||||
// SrcDev: "",
|
||||
// SrcAddr: "",
|
||||
// BeginHop: 1,
|
||||
// MaxHops: 30,
|
||||
// RDns: false,
|
||||
// AlwaysWaitRDNS: false,
|
||||
// Lang: "",
|
||||
// PktSize: 52,
|
||||
//}
|
||||
//ft := FastTracer{ParamsFastTrace: pFastTrace}
|
||||
//// 建立 WebSocket 连接
|
||||
//w := wshandle.New()
|
||||
//w.Interrupt = make(chan os.Signal, 1)
|
||||
//signal.Notify(w.Interrupt, os.Interrupt)
|
||||
//defer func() {
|
||||
// w.Conn.Close()
|
||||
//}()
|
||||
//fmt.Println("TCP v4")
|
||||
//ft.TracerouteMethod = trace.TCPTrace
|
||||
//ft.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.EDU)
|
||||
//fmt.Println("TCP v6")
|
||||
//ft.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.EDU)
|
||||
|
||||
38
go.mod
38
go.mod
@@ -1,46 +1,50 @@
|
||||
module github.com/xgadget-lab/nexttrace
|
||||
module github.com/nxtrace/NTrace-core
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
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.16.0
|
||||
github.com/oschwald/maxminddb-golang v1.12.0
|
||||
github.com/spf13/viper v1.17.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||
github.com/tsosunchia/powclient v0.1.1
|
||||
golang.org/x/net v0.10.0
|
||||
golang.org/x/sync v0.2.0
|
||||
github.com/tsosunchia/powclient v0.1.4
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sync v0.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/spf13/afero v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.10.0 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/lionsoul2014/ip2region v2.11.1+incompatible
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible
|
||||
github.com/rodaine/table v1.1.0
|
||||
github.com/tidwall/gjson v1.14.4
|
||||
github.com/tidwall/gjson v1.17.0
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
75
go.sum
75
go.sum
@@ -49,8 +49,9 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -60,6 +61,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
@@ -137,11 +139,13 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/lionsoul2014/ip2region v2.11.1+incompatible h1:FEqj5PvIP6YwnGt3RYndGQaiftEIJJGpw4BCB76nvfM=
|
||||
github.com/lionsoul2014/ip2region v2.11.1+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible h1:+VRsGcrHz8ewXI/2UzTptJlACsxD/p4xCxuql4u2nKU=
|
||||
github.com/lionsoul2014/ip2region v2.11.2+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@@ -153,55 +157,59 @@ 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.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rodaine/table v1.1.0 h1:/fUlCSdjamMY8VifdQRIu3VWZXYLY7QHFkVorS8NTr4=
|
||||
github.com/rodaine/table v1.1.0/go.mod h1:Qu3q5wi1jTQD6B6HsP6szie/S4w1QUQ8pq22pz9iL8g=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
|
||||
github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
|
||||
github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
|
||||
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
|
||||
github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
|
||||
github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
|
||||
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tsosunchia/powclient v0.1.1 h1:Llv7vFNXTvpxrd2JjnAkpGz95gjVu6A2891RQCML3Rc=
|
||||
github.com/tsosunchia/powclient v0.1.1/go.mod h1:Pm4MP3QqN74SfNskPpFIEyT+NQrcABGoXkkeRwjlMEE=
|
||||
github.com/tsosunchia/powclient v0.1.4 h1:iAXUOiGPLJJTnzVSD0PY+4kBWm+SEMQZzd5ntEk1t0c=
|
||||
github.com/tsosunchia/powclient v0.1.4/go.mod h1:Pm4MP3QqN74SfNskPpFIEyT+NQrcABGoXkkeRwjlMEE=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -212,6 +220,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -229,6 +239,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -284,8 +296,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -305,8 +317,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -345,8 +357,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -356,8 +368,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -501,8 +513,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
|
||||
@@ -2,7 +2,7 @@ package ipgeo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/dn42"
|
||||
"github.com/nxtrace/NTrace-core/dn42"
|
||||
)
|
||||
|
||||
func LtdCodeToCountryOrAreaName(Code string) string {
|
||||
|
||||
@@ -23,14 +23,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)
|
||||
|
||||
@@ -2,17 +2,19 @@ package ipgeo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func IPApiCom(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, error) {
|
||||
url := "http://ip-api.com/json/" + ip + "?fields=status,message,country,regionName,city,isp,as"
|
||||
url := "http://ip-api.com/json/" + ip + "?fields=status,message,country,regionName,city,isp,district,as,lat,lon"
|
||||
client := &http.Client{
|
||||
// 2 秒超时
|
||||
Timeout: timeout,
|
||||
@@ -32,12 +34,27 @@ func IPApiCom(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, e
|
||||
}
|
||||
|
||||
re := regexp.MustCompile("[0-9]+")
|
||||
var country = res.Get("country").String()
|
||||
var prov = res.Get("region").String()
|
||||
var city = res.Get("city").String()
|
||||
var district = res.Get("district").String()
|
||||
if util.StringInSlice(country, []string{"Hong Kong", "Taiwan", "Macao"}) {
|
||||
district = prov + " " + city + " " + district
|
||||
city = country
|
||||
prov = ""
|
||||
country = "China"
|
||||
}
|
||||
lat, _ := strconv.ParseFloat(res.Get("lat").String(), 32)
|
||||
lng, _ := strconv.ParseFloat(res.Get("lon").String(), 32)
|
||||
|
||||
return &IPGeoData{
|
||||
Asnumber: re.FindString(res.Get("as").String()),
|
||||
Country: res.Get("country").String(),
|
||||
City: res.Get("city").String(),
|
||||
Prov: res.Get("regionName").String(),
|
||||
Country: country,
|
||||
City: city,
|
||||
Prov: prov,
|
||||
District: district,
|
||||
Owner: res.Get("isp").String(),
|
||||
Lat: lat,
|
||||
Lng: lng,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -20,16 +20,40 @@ func Filter(ip string) (*IPGeoData, bool) {
|
||||
whois := ""
|
||||
isFiltered := false
|
||||
switch {
|
||||
//rfc1918
|
||||
case net.ParseIP(ip).IsPrivate():
|
||||
case cidrRangeContains("0.0.0.0/8", ip):
|
||||
asn = ""
|
||||
whois = "RFC1918"
|
||||
whois = "RFC1122"
|
||||
isFiltered = true
|
||||
//IANA Reserved Address Space
|
||||
case cidrRangeContains("100.64.0.0/10", ip):
|
||||
asn = ""
|
||||
whois = "RFC6598"
|
||||
isFiltered = true
|
||||
//127.0.0.0/8
|
||||
case cidrRangeContains("127.0.0.0/8", ip):
|
||||
asn = ""
|
||||
whois = "RFC1122"
|
||||
isFiltered = true
|
||||
//169.254.0.0/16
|
||||
case cidrRangeContains("169.254.0.0/16", ip):
|
||||
asn = ""
|
||||
whois = "RFC3927"
|
||||
isFiltered = true
|
||||
//192.0.0.0/24
|
||||
case cidrRangeContains("192.0.0.0/24", ip):
|
||||
asn = ""
|
||||
whois = "RFC6890"
|
||||
isFiltered = true
|
||||
//192.0.2.0/24
|
||||
case cidrRangeContains("192.0.2.0/24", ip):
|
||||
asn = ""
|
||||
whois = "RFC5737"
|
||||
isFiltered = true
|
||||
//192.88.99.0/24
|
||||
case cidrRangeContains("192.88.99.0/24", ip):
|
||||
asn = ""
|
||||
whois = "RFC3068"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("198.18.0.0/15", ip):
|
||||
asn = ""
|
||||
whois = "RFC2544"
|
||||
@@ -40,10 +64,68 @@ func Filter(ip string) (*IPGeoData, bool) {
|
||||
asn = ""
|
||||
whois = "RFC5737"
|
||||
isFiltered = true
|
||||
//224.0.0.0/4
|
||||
case cidrRangeContains("224.0.0.0/4", ip):
|
||||
asn = ""
|
||||
whois = "RFC5771"
|
||||
isFiltered = true
|
||||
//255.255.255.255/32
|
||||
case cidrRangeContains("255.255.255.255/32", ip):
|
||||
asn = ""
|
||||
whois = "RFC0919"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("240.0.0.0/4", ip):
|
||||
asn = ""
|
||||
whois = "RFC1112"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("fe80::/10", ip):
|
||||
asn = ""
|
||||
whois = "RFC4291"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("ff00::/8", ip):
|
||||
asn = ""
|
||||
whois = "RFC4291"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("fec0::/10", ip):
|
||||
asn = ""
|
||||
whois = "RFC3879"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("fe00::/9", ip):
|
||||
asn = ""
|
||||
whois = "RFC4291"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("64:ff9b::/96", ip):
|
||||
asn = ""
|
||||
whois = "RFC6052"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("0::/96", ip):
|
||||
asn = ""
|
||||
whois = "RFC4291"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("64:ff9b:1::/48", ip):
|
||||
asn = ""
|
||||
whois = "RFC6052"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("2001:db8::/32", ip):
|
||||
asn = ""
|
||||
whois = "RFC3849"
|
||||
isFiltered = true
|
||||
case cidrRangeContains("2002::/16", ip):
|
||||
asn = ""
|
||||
whois = "RFC3056"
|
||||
isFiltered = true
|
||||
case net.ParseIP(ip).IsPrivate():
|
||||
//rfc4193
|
||||
if cidrRangeContains("fc00::/7", ip) {
|
||||
asn = ""
|
||||
whois = "RFC4193"
|
||||
isFiltered = true
|
||||
//rfc1918
|
||||
} else {
|
||||
asn = ""
|
||||
whois = "RFC1918"
|
||||
isFiltered = true
|
||||
}
|
||||
//Defense Information System Network
|
||||
case cidrRangeContains("6.0.0.0/8", ip):
|
||||
fallthrough
|
||||
@@ -75,6 +157,12 @@ func Filter(ip string) (*IPGeoData, bool) {
|
||||
isFiltered = true
|
||||
default:
|
||||
}
|
||||
// 判断是否为v6 且不在2000::/3
|
||||
if net.ParseIP(ip).To4() == nil && !cidrRangeContains("2000::/3", ip) && !isFiltered {
|
||||
asn = ""
|
||||
whois = "INVALID"
|
||||
isFiltered = true
|
||||
}
|
||||
if !isFiltered {
|
||||
return nil, false
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,13 @@ func TestXxx(t *testing.T) {
|
||||
log.Println(process_id, ttl_r)
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
res, err := Filter("fd11::1")
|
||||
//打印whois信息
|
||||
fmt.Println(res.Whois)
|
||||
print(err)
|
||||
}
|
||||
|
||||
func reverseID(id string) (int64, int64, error) {
|
||||
ttl, _ := strconv.ParseInt(id[9:15], 2, 32)
|
||||
//process ID
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package ipgeo
|
||||
|
||||
import (
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -10,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func IPInfo(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, error) {
|
||||
url := "https://ipinfo.io/" + ip + "?token=" + token.ipinfo
|
||||
url := "http://ipinfo.io/" + ip + "?token=" + token.ipinfo
|
||||
client := &http.Client{
|
||||
// 2 秒超时
|
||||
Timeout: timeout,
|
||||
@@ -28,11 +30,6 @@ func IPInfo(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, err
|
||||
|
||||
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"
|
||||
}
|
||||
// ISO-3166 转换
|
||||
var countryMap = map[string]string{
|
||||
"AF": "Afghanistan",
|
||||
@@ -285,7 +282,26 @@ func IPInfo(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, err
|
||||
"ZM": "Zambia",
|
||||
"ZW": "Zimbabwe",
|
||||
}
|
||||
var country = res.Get("country").String()
|
||||
var prov = res.Get("region").String()
|
||||
var city = res.Get("city").String()
|
||||
var district = ""
|
||||
if util.StringInSlice(country, []string{"TW", "MO", "HK"}) {
|
||||
district = prov + " " + city
|
||||
city = countryMap[country]
|
||||
prov = ""
|
||||
country = "CN"
|
||||
}
|
||||
country = countryMap[country]
|
||||
|
||||
var anycast = false
|
||||
if res.Get("anycast").String() == "true" {
|
||||
country = "ANYCAST"
|
||||
prov = "ANYCAST"
|
||||
city = ""
|
||||
anycast = true
|
||||
}
|
||||
|
||||
i := strings.Index(res.Get("org").String(), " ")
|
||||
var owner string
|
||||
if i == -1 {
|
||||
@@ -300,11 +316,24 @@ func IPInfo(ip string, timeout time.Duration, _ string, _ bool) (*IPGeoData, err
|
||||
asnumber = strings.Fields(strings.TrimPrefix(res.Get("org").String(), "AS"))[0]
|
||||
}
|
||||
|
||||
//"loc": "34.0522,-118.2437",
|
||||
var lat, lng float64
|
||||
if res.Get("loc").String() != "" {
|
||||
lat, _ = strconv.ParseFloat(strings.Split(res.Get("loc").String(), ",")[0], 32)
|
||||
lng, _ = strconv.ParseFloat(strings.Split(res.Get("loc").String(), ",")[1], 32)
|
||||
}
|
||||
if anycast {
|
||||
lat, lng = 0, 0
|
||||
}
|
||||
|
||||
return &IPGeoData{
|
||||
Asnumber: asnumber,
|
||||
Country: country,
|
||||
City: res.Get("city").String(),
|
||||
Prov: res.Get("region").String(),
|
||||
City: city,
|
||||
Prov: prov,
|
||||
District: district,
|
||||
Owner: owner,
|
||||
Lat: lat,
|
||||
Lng: lng,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nxtrace/NTrace-core/wshandle"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/xgadget-lab/nexttrace/wshandle"
|
||||
)
|
||||
|
||||
/***
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ipgeo
|
||||
|
||||
import "github.com/xgadget-lab/nexttrace/util"
|
||||
import "github.com/nxtrace/NTrace-core/util"
|
||||
|
||||
type tokenData struct {
|
||||
ipinsight string
|
||||
|
||||
2
main.go
2
main.go
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/xgadget-lab/nexttrace/cmd"
|
||||
"github.com/nxtrace/NTrace-core/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -93,12 +93,7 @@ checkWgetPackage() {
|
||||
downloadBinrayFile() {
|
||||
echo -e "${Info} 获取最新版的 NextTrace 发行版文件信息"
|
||||
# 简单说明一下,Github提供了一个API,可以获取最新发行版本的二进制文件下载地址(对应的是browser_download_url),根据刚刚测得的osDistribution、archParam,获取对应的下载地址
|
||||
latestURL=$(curl -s https://api.github.com/repos/sjlleo/nexttrace/releases/latest | grep -i "browser_download_url.*${osDistribution}.*${archParam}" | awk -F '"' '{print $4}')
|
||||
|
||||
if [ "$countryCode" == "CN" ]; then
|
||||
echo -e "${Info} 检测到国内环境,正在使用镜像下载"
|
||||
latestURL="https://ghproxy.com/"$latestURL
|
||||
fi
|
||||
latestURL=$(curl -sL http://nexttrace-io-leomoe-api-a0.shop/latest_v1.json | grep -i "browser_download_url.*${osDistribution}.*${archParam}" | awk -F '"' '{print $4}')
|
||||
|
||||
echo -e "${Info} 正在下载 NextTrace 二进制文件..."
|
||||
wget -O ${Temp_path} ${latestURL} &> /dev/null
|
||||
@@ -130,8 +125,6 @@ checkSystemDistribution
|
||||
checkSystemArch
|
||||
checkWgetPackage
|
||||
|
||||
# Download Procedure
|
||||
getLocation
|
||||
downloadBinrayFile
|
||||
|
||||
# Run Procedure
|
||||
|
||||
17
pow/pow.go
17
pow/pow.go
@@ -2,8 +2,8 @@ package pow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"github.com/tsosunchia/powclient"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
@@ -19,10 +19,17 @@ func GetToken(fastIp string, host string, port string) (string, error) {
|
||||
getTokenParams.SNI = host
|
||||
getTokenParams.Host = host
|
||||
getTokenParams.UserAgent = util.UserAgent
|
||||
var err error
|
||||
proxyUrl := util.GetProxy()
|
||||
if proxyUrl != nil {
|
||||
getTokenParams.Proxy = proxyUrl
|
||||
}
|
||||
var (
|
||||
token string
|
||||
err error
|
||||
)
|
||||
// 尝试三次RetToken,如果都失败了,异常退出
|
||||
for i := 0; i < 3; i++ {
|
||||
token, err := powclient.RetToken(getTokenParams)
|
||||
token, err = powclient.RetToken(getTokenParams)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -32,7 +39,7 @@ func GetToken(fastIp string, host string, port string) (string, error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("RetToken failed 3 times, exit")
|
||||
fmt.Println("RetToken failed 3 times, please try again after a while, exit")
|
||||
os.Exit(1)
|
||||
return "", nil
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func TestGetToken(t *testing.T) {
|
||||
// 计时开始
|
||||
start := time.Now()
|
||||
token, err := GetToken("103.120.18.35", "api.leo.moe", "443")
|
||||
token, err := GetToken("api.leo.moe", "api.leo.moe", "443")
|
||||
// 计时结束
|
||||
end := time.Now()
|
||||
fmt.Println("耗时:", end.Sub(start))
|
||||
|
||||
@@ -2,8 +2,8 @@ package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/xgadget-lab/nexttrace/config"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/config"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
"net"
|
||||
|
||||
"github.com/fatih/color"
|
||||
@@ -41,13 +41,14 @@ func CopyRight() {
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("%s", "zhshch@athorx.com"),
|
||||
)
|
||||
|
||||
MoeQingOrgCopyRight()
|
||||
PluginCopyRight()
|
||||
moeQingOrgCopyRight()
|
||||
sponsor()
|
||||
//PluginCopyRight()
|
||||
}
|
||||
|
||||
func MoeQingOrgCopyRight() {
|
||||
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.FgGreen, color.Bold).Sprintf("%s", "Supported by 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"),
|
||||
@@ -55,14 +56,23 @@ func MoeQingOrgCopyRight() {
|
||||
)
|
||||
}
|
||||
|
||||
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 sponsor() {
|
||||
fmt.Fprintf(color.Output, "%s\n%s\n%s\n%s\n",
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", "Sponsored by the following entities"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "DMIT.io"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "Misaka.io"),
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("%s", "Skywolf.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, maxHops int, packetSize int) {
|
||||
fmt.Println("IP Geo Data Provider: " + dataOrigin)
|
||||
|
||||
@@ -75,8 +85,18 @@ func PrintTraceRouteNav(ip net.IP, domain string, dataOrigin string, maxHops int
|
||||
|
||||
func applyLangSetting(h *trace.Hop) {
|
||||
if len(h.Geo.Country) <= 1 {
|
||||
h.Geo.Country = "局域网"
|
||||
h.Geo.CountryEn = "LAN Address"
|
||||
//打印h.geo
|
||||
if h.Geo.Whois != "" {
|
||||
h.Geo.Country = h.Geo.Whois
|
||||
} else {
|
||||
if h.Geo.Source != "LeoMoeAPI" {
|
||||
h.Geo.Country = "网络故障"
|
||||
h.Geo.CountryEn = "Network Error"
|
||||
} else {
|
||||
h.Geo.Country = "未知"
|
||||
h.Geo.CountryEn = "Unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if h.Lang == "en" {
|
||||
@@ -98,4 +118,5 @@ func applyLangSetting(h *trace.Hop) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
type HopInfo int
|
||||
|
||||
@@ -3,7 +3,7 @@ package printer
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
func EasyPrinter(res *trace.Result, ttl int) {
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
)
|
||||
|
||||
// var dataOrigin string
|
||||
@@ -47,6 +47,9 @@ func HopPrinter(h trace.Hop, info HopInfo) {
|
||||
if h.Geo != nil {
|
||||
txt += " " + formatIpGeoData(h.Address.String(), h.Geo)
|
||||
}
|
||||
for _, v := range h.MPLS {
|
||||
txt += " " + v
|
||||
}
|
||||
switch info {
|
||||
case IXP:
|
||||
fmt.Print(CYAN_PREFIX)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
func RealtimePrinter(res *trace.Result, ttl int) {
|
||||
@@ -98,7 +98,13 @@ func RealtimePrinter(res *trace.Result, ttl int) {
|
||||
}
|
||||
|
||||
if whoisFormat[0] != "" {
|
||||
whoisFormat[0] = "[" + whoisFormat[0] + "]"
|
||||
//如果以RFC或DOD开头那么为空
|
||||
if !(strings.HasPrefix(whoisFormat[0], "RFC") ||
|
||||
strings.HasPrefix(whoisFormat[0], "DOD")) {
|
||||
whoisFormat[0] = "[" + whoisFormat[0] + "]"
|
||||
} else {
|
||||
whoisFormat[0] = ""
|
||||
}
|
||||
}
|
||||
|
||||
// CMIN2, CUII, CN2, CUG 改为壕金色高亮
|
||||
@@ -160,6 +166,11 @@ func RealtimePrinter(res *trace.Result, ttl int) {
|
||||
)
|
||||
}
|
||||
}
|
||||
for _, v := range res.Hops[ttl][i].MPLS {
|
||||
fmt.Fprintf(color.Output, "%s",
|
||||
color.New(color.FgHiBlack, color.Bold).Sprintf("\n %s", v),
|
||||
)
|
||||
}
|
||||
fmt.Println()
|
||||
blockDisplay = true
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
func RealtimePrinterWithRouter(res *trace.Result, ttl int) {
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/rodaine/table"
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
type Reporter interface {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
var testResult = &trace.Result{
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace/internal"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
@@ -31,6 +30,8 @@ type ICMPTracer struct {
|
||||
fetchLock sync.Mutex
|
||||
}
|
||||
|
||||
var psize = 52
|
||||
|
||||
func (t *ICMPTracer) PrintFunc() {
|
||||
defer t.wg.Done()
|
||||
var ttl = t.Config.BeginHop - 1
|
||||
@@ -65,7 +66,7 @@ func (t *ICMPTracer) Execute() (*Result, error) {
|
||||
|
||||
var err error
|
||||
|
||||
t.icmpListen, err = internal.ListenICMP("ip4:1", t.SrcAddr)
|
||||
t.icmpListen, err = net.ListenPacket("ip4:1", t.SrcAddr)
|
||||
if err != nil {
|
||||
return &t.res, err
|
||||
}
|
||||
@@ -119,6 +120,7 @@ func (t *ICMPTracer) Execute() (*Result, error) {
|
||||
|
||||
func (t *ICMPTracer) listenICMP() {
|
||||
lc := NewPacketListener(t.icmpListen, t.ctx)
|
||||
psize = t.Config.PktSize
|
||||
go lc.Start()
|
||||
for {
|
||||
select {
|
||||
@@ -176,10 +178,13 @@ func (t *ICMPTracer) listenICMP() {
|
||||
func (t *ICMPTracer) handleICMPMessage(msg ReceivedMessage, icmpType int8, data []byte, ttl int) {
|
||||
t.inflightRequestRWLock.RLock()
|
||||
defer t.inflightRequestRWLock.RUnlock()
|
||||
|
||||
mpls := extractMPLS(msg, data)
|
||||
if _, ok := t.inflightRequest[ttl]; ok {
|
||||
t.inflightRequest[ttl] <- Hop{
|
||||
Success: true,
|
||||
Address: msg.Peer,
|
||||
MPLS: mpls,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +207,7 @@ func gernerateID(ttl_int int) int {
|
||||
id += "0"
|
||||
}
|
||||
|
||||
res, _ := strconv.ParseInt(id, 2, 64)
|
||||
res, _ := strconv.ParseInt(id, 2, 32)
|
||||
return int(res)
|
||||
}
|
||||
|
||||
@@ -257,7 +262,7 @@ func (t *ICMPTracer) send(ttl int) error {
|
||||
Body: &icmp.Echo{
|
||||
ID: id,
|
||||
//Data: []byte("HELLO-R-U-THERE"),
|
||||
Data: bytes.Repeat([]byte{1}, t.Config.PktSize),
|
||||
Data: append(bytes.Repeat([]byte{1}, t.Config.PktSize-4), 0x00, 0x00, 0x4f, 0xff),
|
||||
Seq: ttl,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace/internal"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv6"
|
||||
@@ -66,7 +65,7 @@ func (t *ICMPTracerv6) Execute() (*Result, error) {
|
||||
|
||||
var err error
|
||||
|
||||
t.icmpListen, err = internal.ListenICMP("ip6:58", t.SrcAddr)
|
||||
t.icmpListen, err = net.ListenPacket("ip6:58", t.SrcAddr)
|
||||
if err != nil {
|
||||
return &t.res, err
|
||||
}
|
||||
@@ -138,6 +137,7 @@ func (t *ICMPTracerv6) Execute() (*Result, error) {
|
||||
|
||||
func (t *ICMPTracerv6) listenICMP() {
|
||||
lc := NewPacketListener(t.icmpListen, t.ctx)
|
||||
psize = t.Config.PktSize
|
||||
go lc.Start()
|
||||
for {
|
||||
select {
|
||||
@@ -234,10 +234,13 @@ func (t *ICMPTracerv6) listenICMP() {
|
||||
func (t *ICMPTracerv6) handleICMPMessage(msg ReceivedMessage, icmpType int8, data []byte, ttl int) {
|
||||
t.inflightRequestRWLock.RLock()
|
||||
defer t.inflightRequestRWLock.RUnlock()
|
||||
|
||||
mpls := extractMPLS(msg, data)
|
||||
if _, ok := t.inflightRequest[ttl]; ok {
|
||||
t.inflightRequest[ttl] <- Hop{
|
||||
Success: true,
|
||||
Address: msg.Peer,
|
||||
MPLS: mpls,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +257,7 @@ func (t *ICMPTracerv6) send(ttl int) error {
|
||||
Body: &icmp.Echo{
|
||||
ID: id,
|
||||
//Data: []byte("HELLO-R-U-THERE"),
|
||||
Data: bytes.Repeat([]byte{1}, t.Config.PktSize),
|
||||
Data: append(bytes.Repeat([]byte{1}, t.Config.PktSize-4), 0x00, 0x00, 0x4f, 0xff),
|
||||
Seq: ttl,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// ListenICMP 会造成指定出口IP功能不可使用
|
||||
func ListenICMP(network string, laddr string) (net.PacketConn, error) {
|
||||
if os.Getuid() == 0 { // root
|
||||
return net.ListenPacket(network, laddr)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
@@ -257,7 +257,7 @@ func (t *TCPTracer) send(ttl int) error {
|
||||
t.inflightRequest[int(sequenceNumber)] = hopCh
|
||||
t.inflightRequestLock.Unlock()
|
||||
/*
|
||||
// 这里属于 2个Sender,N个Reciever的情况,在哪里关闭Channel都容易导致Panic
|
||||
// 这里属于 2个Sender,N个Receiver的情况,在哪里关闭Channel都容易导致Panic
|
||||
defer func() {
|
||||
t.inflightRequestLock.Lock()
|
||||
close(hopCh)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv6"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
)
|
||||
|
||||
func HopPrinter(h Hop) {
|
||||
|
||||
119
trace/trace.go
119
trace/trace.go
@@ -2,12 +2,15 @@ package trace
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/ipgeo"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/ipgeo"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -124,6 +127,7 @@ type Hop struct {
|
||||
Error error
|
||||
Geo *ipgeo.IPGeoData
|
||||
Lang string
|
||||
MPLS []string
|
||||
}
|
||||
|
||||
func (h *Hop) fetchIPData(c Config) (err error) {
|
||||
@@ -137,7 +141,7 @@ func (h *Hop) fetchIPData(c Config) (err error) {
|
||||
h.Hostname = r[0][:len(r[0])-1]
|
||||
ip = h.Address.String() + "," + h.Hostname
|
||||
}
|
||||
h.Geo, err = c.IPGeoSource(ip, c.Timeout, c.Lang, c.Maptrace)
|
||||
h.Geo, _ = c.IPGeoSource(ip, c.Timeout, c.Lang, c.Maptrace)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -217,11 +221,116 @@ func (h *Hop) fetchIPData(c Config) (err error) {
|
||||
selectClose = true
|
||||
}
|
||||
|
||||
// When Select Close, fetchDoneChan Reciever will also be closed
|
||||
// When Select Close, fetchDoneChan Received will also be closed
|
||||
if selectClose {
|
||||
// New a reciever to prevent channel congestion
|
||||
// New a receiver to prevent channel congestion
|
||||
<-fetchDoneChan
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func extractMPLS(msg ReceivedMessage, data []byte) []string {
|
||||
if util.DisableMPLS != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if psize != 52 {
|
||||
return nil
|
||||
}
|
||||
|
||||
extensionOffset := 20 + 8 + psize
|
||||
|
||||
if len(data) <= extensionOffset {
|
||||
return nil
|
||||
}
|
||||
|
||||
extensionBody := data[extensionOffset:]
|
||||
if len(extensionBody) < 8 || len(extensionBody)%8 != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
tmp := fmt.Sprintf("%x", msg.Msg[:*msg.N])
|
||||
|
||||
index := strings.Index(tmp, strings.Repeat("01", psize-4)+"00004fff")
|
||||
if index == -1 {
|
||||
return nil
|
||||
}
|
||||
tmp = tmp[index+psize*2:]
|
||||
//由于限制长度了
|
||||
index1 := strings.Index(tmp, "00002000")
|
||||
l := len(tmp[index1+4:])/8 - 2
|
||||
//fmt.Printf("l:%d\n", l)
|
||||
|
||||
if l < 1 {
|
||||
return nil
|
||||
}
|
||||
//去掉扩展头和MPLS头
|
||||
tmp = tmp[index1+4+8*2:]
|
||||
//fmt.Print(tmp)
|
||||
|
||||
var retStrList []string
|
||||
for i := 0; i < l; i++ {
|
||||
label, err := strconv.ParseInt(tmp[i*8+0:i*8+5], 16, 32)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
strSlice := fmt.Sprintf("%s", []byte(tmp[i*8+5:i*8+6]))
|
||||
//fmt.Printf("\nstrSlice: %s\n", strSlice)
|
||||
|
||||
num, err := strconv.ParseUint(strSlice, 16, 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
binaryStr := fmt.Sprintf("%04s", strconv.FormatUint(num, 2))
|
||||
|
||||
//fmt.Printf("\nbinaryStr: %s\n", binaryStr)
|
||||
tc, err := strconv.ParseInt(binaryStr[:3], 2, 32)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
s := binaryStr[3:]
|
||||
|
||||
ttlMpls, err := strconv.ParseInt(tmp[i*8+6:i*8+8], 16, 32)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
//if i > 0 {
|
||||
// retStr += "\n "
|
||||
//}
|
||||
|
||||
retStrList = append(retStrList, fmt.Sprintf("[MPLS: Lbl %d, TC %d, S %s, TTL %d]", label, tc, s, ttlMpls))
|
||||
}
|
||||
|
||||
//label, err := strconv.ParseInt(tmp[len(tmp)-8:len(tmp)-3], 16, 32)
|
||||
//if err != nil {
|
||||
// return ""
|
||||
//}
|
||||
//
|
||||
//strSlice := fmt.Sprintf("%s", []byte(tmp[len(tmp)-3:len(tmp)-2]))
|
||||
////fmt.Printf("\nstrSlice: %s\n", strSlice)
|
||||
//
|
||||
//num, err := strconv.ParseUint(strSlice, 16, 64)
|
||||
//if err != nil {
|
||||
// return ""
|
||||
//}
|
||||
//binaryStr := fmt.Sprintf("%04s", strconv.FormatUint(num, 2))
|
||||
//
|
||||
////fmt.Printf("\nbinaryStr: %s\n", binaryStr)
|
||||
//tc, err := strconv.ParseInt(binaryStr[:3], 2, 32)
|
||||
//if err != nil {
|
||||
// return ""
|
||||
//}
|
||||
//s := binaryStr[3:]
|
||||
//
|
||||
//ttlMpls, err := strconv.ParseInt(tmp[len(tmp)-2:], 16, 32)
|
||||
//if err != nil {
|
||||
// return ""
|
||||
//}
|
||||
//
|
||||
//retStr := fmt.Sprintf("Lbl %d, TC %d, S %s, TTL %d", label, tc, s, ttlMpls)
|
||||
|
||||
return retStrList
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/xgadget-lab/nexttrace/trace"
|
||||
"github.com/nxtrace/NTrace-core/trace"
|
||||
)
|
||||
|
||||
func RealtimePrinter(res *trace.Result, ttl int) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -35,6 +35,10 @@ func GetMapUrl(r string) (string, error) {
|
||||
},
|
||||
},
|
||||
}
|
||||
proxyUrl := util.GetProxy()
|
||||
if proxyUrl != nil {
|
||||
client.Transport.(*http.Transport).Proxy = http.ProxyURL(proxyUrl)
|
||||
}
|
||||
req, err := http.NewRequest("POST", tracemapUrl, strings.NewReader(r))
|
||||
if err != nil {
|
||||
return "", errors.New("an issue occurred while connecting to the tracemap API")
|
||||
@@ -62,7 +66,7 @@ func GetMapUrl(r string) (string, error) {
|
||||
func PrintMapUrl(r string) {
|
||||
_, 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(r)),
|
||||
color.New(color.FgBlue, color.Bold).Sprintf("%s", r),
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -13,8 +13,8 @@ func TestDNS(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDomainLookUp(t *testing.T) {
|
||||
ips := DomainLookUp("pek-4134.nexttrace-io-fasttrace-endpoint.win.", "all", "", false)
|
||||
ips, _ := DomainLookUp("pek-4134.nexttrace-io-fasttrace-endpoint.win.", "all", "", false)
|
||||
fmt.Println(ips)
|
||||
ips = DomainLookUp("pek-4134.nexttrace-io-fasttrace-endpoint.win.", "4", "", false)
|
||||
ips, _ = DomainLookUp("pek-4134.nexttrace-io-fasttrace-endpoint.win.", "4", "", false)
|
||||
fmt.Println(ips)
|
||||
}
|
||||
|
||||
108
util/latency.go
108
util/latency.go
@@ -1,22 +1,35 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type ResponseInfo struct {
|
||||
IP string
|
||||
Latency string
|
||||
Content string
|
||||
}
|
||||
|
||||
var (
|
||||
result string
|
||||
results = make(chan string)
|
||||
results = make(chan ResponseInfo)
|
||||
timeout = 5 * time.Second
|
||||
)
|
||||
var FastIpCache = ""
|
||||
|
||||
func GetFastIP(domain string, port string, enableOutput bool) string {
|
||||
proxyUrl := GetProxy()
|
||||
if proxyUrl != nil {
|
||||
return "api.leo.moe"
|
||||
}
|
||||
if FastIpCache != "" {
|
||||
return FastIpCache
|
||||
}
|
||||
@@ -26,50 +39,83 @@ func GetFastIP(domain string, port string, enableOutput bool) string {
|
||||
log.Fatal("DNS resolution failed, please check your system DNS Settings")
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
go checkLatency(ip.String(), port)
|
||||
if len(ips) == 0 {
|
||||
// 添加默认IP 45.88.195.154
|
||||
ips = append(ips, net.ParseIP("45.88.195.154"))
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
go checkLatency(domain, ip.String(), port)
|
||||
}
|
||||
|
||||
var result ResponseInfo
|
||||
|
||||
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, "-")
|
||||
//等待5s没有结果 视为连不上API了
|
||||
case <-time.After(timeout):
|
||||
log.Println("IP connection has been timeout, please check your network")
|
||||
|
||||
if len(ips) > 1 {
|
||||
if enableOutput {
|
||||
_, _ = 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]),
|
||||
)
|
||||
}
|
||||
}
|
||||
FastIpCache = res[0]
|
||||
return res[0]
|
||||
|
||||
//if len(ips) > 0 {
|
||||
if enableOutput {
|
||||
_, _ = fmt.Fprintf(color.Output, "%s preferred API IP - %s - %s - %s",
|
||||
color.New(color.FgWhite, color.Bold).Sprintf("[NextTrace API]"),
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", result.IP),
|
||||
color.New(color.FgCyan, color.Bold).Sprintf("%sms", result.Latency),
|
||||
color.New(color.FgGreen, color.Bold).Sprintf("%s", result.Content),
|
||||
)
|
||||
}
|
||||
//}
|
||||
FastIpCache = result.IP
|
||||
return result.IP
|
||||
}
|
||||
|
||||
func checkLatency(ip string, port string) {
|
||||
func checkLatency(domain string, ip string, port string) {
|
||||
start := time.Now()
|
||||
if !strings.Contains(ip, ".") {
|
||||
ip = "[" + ip + "]"
|
||||
}
|
||||
conn, err := net.DialTimeout("tcp", ip+":"+port, time.Second*1)
|
||||
|
||||
// 自定义DialContext以使用指定的IP连接
|
||||
transport := &http.Transport{
|
||||
//DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// return net.DialTimeout(network, addr, 1*time.Second)
|
||||
//},
|
||||
TLSClientConfig: &tls.Config{
|
||||
ServerName: domain,
|
||||
},
|
||||
TLSHandshakeTimeout: timeout,
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
//此处虽然是 https://domain/ 但是实际上会使用指定的IP连接
|
||||
req, err := http.NewRequest("GET", "https://"+ip+":"+port+"/", nil)
|
||||
if err != nil {
|
||||
// !!! 此处不要给results返回任何值
|
||||
//results <- ResponseInfo{IP: ip, Latency: "error", Content: ""}
|
||||
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
|
||||
req.Host = domain
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
//results <- ResponseInfo{IP: ip, Latency: "error", Content: ""}
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
//results <- ResponseInfo{IP: ip, Latency: "error", Content: ""}
|
||||
return
|
||||
}
|
||||
bodyString := string(bodyBytes)
|
||||
|
||||
latency := fmt.Sprintf("%.2f", float64(time.Since(start))/float64(time.Millisecond))
|
||||
results <- ResponseInfo{IP: ip, Latency: latency, Content: bodyString}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetFastIP(t *testing.T) {
|
||||
GetFastIP("api.leo.moe", "443", true)
|
||||
}
|
||||
//github action test 不支持v6 这里会报错
|
||||
//func TestGetFastIP(t *testing.T) {
|
||||
// GetFastIP("api.leo.moe", "443", true)
|
||||
//}
|
||||
|
||||
54
util/util.go
54
util/util.go
@@ -2,10 +2,12 @@ package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/xgadget-lab/nexttrace/config"
|
||||
"github.com/nxtrace/NTrace-core/config"
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -18,6 +20,8 @@ var Uninterrupted = GetenvDefault("NEXTTRACE_UNINTERRUPTED", "")
|
||||
var EnvToken = GetenvDefault("NEXTTRACE_TOKEN", "")
|
||||
var UserAgent = fmt.Sprintf("NextTrace %s/%s/%s", config.Version, runtime.GOOS, runtime.GOARCH)
|
||||
var RdnsCache sync.Map
|
||||
var PowProviderParam = ""
|
||||
var DisableMPLS = GetenvDefault("NEXTTRACE_DISABLEMPLS", "")
|
||||
|
||||
func LookupAddr(addr string) ([]string, error) {
|
||||
// 如果在缓存中找到,直接返回
|
||||
@@ -72,7 +76,7 @@ func LocalIPPortv6(dstip net.IP) (net.IP, int) {
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
func DomainLookUp(host string, ipVersion string, dotServer string, disableOutput bool) net.IP {
|
||||
func DomainLookUp(host string, ipVersion string, dotServer string, disableOutput bool) (net.IP, error) {
|
||||
// ipVersion: 4, 6, all
|
||||
var (
|
||||
r *net.Resolver
|
||||
@@ -98,8 +102,7 @@ func DomainLookUp(host string, ipVersion string, dotServer string, disableOutput
|
||||
ips = append(ips, net.ParseIP(v))
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("Domain " + host + " Lookup Fail.")
|
||||
os.Exit(1)
|
||||
return nil, errors.New("DNS lookup failed")
|
||||
}
|
||||
|
||||
//var ipv6Flag = false
|
||||
@@ -125,7 +128,7 @@ func DomainLookUp(host string, ipVersion string, dotServer string, disableOutput
|
||||
}
|
||||
|
||||
if (len(ips) == 1) || (disableOutput) {
|
||||
return ips[0]
|
||||
return ips[0], nil
|
||||
} else {
|
||||
fmt.Println("Please Choose the IP You Want To TraceRoute")
|
||||
for i, ip := range ips {
|
||||
@@ -144,13 +147,17 @@ func DomainLookUp(host string, ipVersion string, dotServer string, disableOutput
|
||||
fmt.Println("Your Option is invalid")
|
||||
os.Exit(3)
|
||||
}
|
||||
return ips[index]
|
||||
return ips[index], nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetenvDefault(key, defVal string) string {
|
||||
val, ok := os.LookupEnv(key)
|
||||
if ok {
|
||||
_, ok := os.LookupEnv("NEXTTRACE_DEBUG")
|
||||
if ok {
|
||||
fmt.Println("ENV", key, "detected as", val)
|
||||
}
|
||||
return val
|
||||
}
|
||||
return defVal
|
||||
@@ -182,3 +189,38 @@ func GetHostAndPort() (host string, port string) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetProxy() *url.URL {
|
||||
proxyURLStr := GetenvDefault("NEXTTRACE_PROXY", "")
|
||||
if proxyURLStr == "" {
|
||||
return nil
|
||||
}
|
||||
proxyURL, err := url.Parse(proxyURLStr)
|
||||
if err != nil {
|
||||
log.Println("Failed to parse proxy URL:", err)
|
||||
return nil
|
||||
}
|
||||
return proxyURL
|
||||
}
|
||||
|
||||
func GetPowProvider() string {
|
||||
var powProvider = ""
|
||||
if PowProviderParam == "" {
|
||||
powProvider = GetenvDefault("NEXTTRACE_POWPROVIDER", "api.leo.moe")
|
||||
} else {
|
||||
powProvider = PowProviderParam
|
||||
}
|
||||
if powProvider == "sakura" {
|
||||
return "pow.nexttrace.owo.13a.com"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func StringInSlice(val string, list []string) bool {
|
||||
for _, v := range list {
|
||||
if v == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package wshandle
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"github.com/xgadget-lab/nexttrace/pow"
|
||||
"github.com/xgadget-lab/nexttrace/util"
|
||||
"github.com/nxtrace/NTrace-core/pow"
|
||||
"github.com/nxtrace/NTrace-core/util"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -127,7 +127,11 @@ func (c *WsConn) recreateWsConn() {
|
||||
// 无环境变量 token
|
||||
if cacheToken == "" {
|
||||
// 无cacheToken, 重新获取 token
|
||||
jwtToken, err = pow.GetToken(fastIp, host, port)
|
||||
if util.GetPowProvider() == "" {
|
||||
jwtToken, err = pow.GetToken(fastIp, host, port)
|
||||
} else {
|
||||
jwtToken, err = pow.GetToken(util.GetPowProvider(), util.GetPowProvider(), port)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
@@ -148,6 +152,10 @@ func (c *WsConn) recreateWsConn() {
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: host,
|
||||
}
|
||||
proxyUrl := util.GetProxy()
|
||||
if proxyUrl != nil {
|
||||
dialer.Proxy = http.ProxyURL(proxyUrl)
|
||||
}
|
||||
ws, _, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
|
||||
c.Conn = ws
|
||||
if err != nil {
|
||||
@@ -171,6 +179,7 @@ func (c *WsConn) recreateWsConn() {
|
||||
}
|
||||
|
||||
func createWsConn() *WsConn {
|
||||
proxyUrl := util.GetProxy()
|
||||
//fmt.Println("正在连接 WS")
|
||||
// 设置终端中断通道
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
@@ -178,6 +187,7 @@ func createWsConn() *WsConn {
|
||||
host, port = util.GetHostAndPort()
|
||||
// 如果 host 是一个 IP 使用默认域名
|
||||
if valid := net.ParseIP(host); valid != nil {
|
||||
fastIp = host
|
||||
host = "api.leo.moe"
|
||||
} else {
|
||||
// 默认配置完成,开始寻找最优 IP
|
||||
@@ -186,7 +196,11 @@ func createWsConn() *WsConn {
|
||||
jwtToken, ua := envToken, []string{"Privileged Client"}
|
||||
err := error(nil)
|
||||
if envToken == "" {
|
||||
jwtToken, err = pow.GetToken(fastIp, host, port)
|
||||
if util.GetPowProvider() == "" {
|
||||
jwtToken, err = pow.GetToken(fastIp, host, port)
|
||||
} else {
|
||||
jwtToken, err = pow.GetToken(util.GetPowProvider(), util.GetPowProvider(), port)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
@@ -204,6 +218,9 @@ func createWsConn() *WsConn {
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
ServerName: host,
|
||||
}
|
||||
if proxyUrl != nil {
|
||||
dialer.Proxy = http.ProxyURL(proxyUrl)
|
||||
}
|
||||
u := url.URL{Scheme: "wss", Host: fastIp + ":" + port, Path: "/v3/ipGeoWs"}
|
||||
// log.Printf("connecting to %s", u.String())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user