Compare commits

...

35 Commits
v1.3.9 ... main

Author SHA1 Message Date
tsosunchia
cefed2a481 Merge pull request #314 from nxtrace/main
Some checks failed
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
SYNC
2025-07-26 20:44:24 +08:00
tsosunchia
bc5a370f3b fix bug: 三网快速测试选的广州/上海,结果测的是北京的 https://github.com/nxtrace/NTrace-core/issues/313
Signed-off-by: tsosunchia <59512455+tsosunchia@users.noreply.github.com>
2025-07-26 20:40:36 +08:00
tsosunchia
96e06e306c Merge pull request #312 from nxtrace/main
SYNC
2025-07-26 17:14:10 +08:00
tsosunchia
ac14ef4a7a 更新依赖
Signed-off-by: tsosunchia <59512455+tsosunchia@users.noreply.github.com>
2025-07-19 22:08:21 +08:00
tsosunchia
bb192699ef Merge pull request #92 from nxtrace/dependabot/go_modules/golang.org/x/net-0.42.0
chore(deps): bump golang.org/x/net from 0.41.0 to 0.42.0
2025-07-19 21:47:00 +08:00
dependabot[bot]
b0b05f476b chore(deps): bump golang.org/x/net from 0.41.0 to 0.42.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.41.0 to 0.42.0.
- [Commits](https://github.com/golang/net/compare/v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-19 13:45:53 +00:00
tsosunchia
53de171bdb Merge pull request #93 from nxtrace/dependabot/go_modules/golang.org/x/sync-0.16.0
chore(deps): bump golang.org/x/sync from 0.15.0 to 0.16.0
2025-07-19 21:44:18 +08:00
dependabot[bot]
547906525a chore(deps): bump golang.org/x/sync from 0.15.0 to 0.16.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 18:21:07 +00:00
tsosunchia
b4d2038895 SNI和DNS不再分离,统一使用api.nxtrace.org 2025-07-08 11:30:21 +08:00
tsosunchia
adf8bb7076 更新依赖 2025-07-05 17:17:59 +08:00
tsosunchia
3defedd27c SNI和DNS不再分离,统一使用api.nxtrace.org 2025-07-05 16:48:43 +08:00
tsosunchia
4eeef8ddb8 Merge pull request #90 from nxtrace/dependabot/go_modules/github.com/go-viper/mapstructure/v2-2.3.0
chore(deps): bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0
2025-07-05 13:46:37 +08:00
dependabot[bot]
35b67d9502 chore(deps): bump github.com/go-viper/mapstructure/v2
Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-27 16:53:59 +00:00
tsosunchia
a5f888d1bc Merge pull request #308 from nxtrace/main
Some checks failed
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
SYNC
2025-06-26 15:23:53 +08:00
tsosunchia
4d38c38cf7 update README: AIWEN TECH Support 2025-06-26 15:22:03 +08:00
tsosunchia
d0e8e67d0a update README: AIWEN TECH Support 2025-06-26 15:14:32 +08:00
tsosunchia
26b176ccb0 Merge pull request #89 from nxtrace/dependabot/go_modules/golang.org/x/net-0.41.0
chore(deps): bump golang.org/x/net from 0.39.0 to 0.41.0
2025-06-12 21:52:21 +08:00
dependabot[bot]
e2b23bb8e0 chore(deps): bump golang.org/x/net from 0.39.0 to 0.41.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.39.0 to 0.41.0.
- [Commits](https://github.com/golang/net/compare/v0.39.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 13:49:58 +00:00
tsosunchia
8c3a682e15 Merge pull request #88 from nxtrace/dependabot/go_modules/golang.org/x/sync-0.15.0
chore(deps): bump golang.org/x/sync from 0.13.0 to 0.15.0
2025-06-12 21:48:24 +08:00
dependabot[bot]
21e1c03596 chore(deps): bump golang.org/x/sync from 0.13.0 to 0.15.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.13.0 to 0.15.0.
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-09 14:51:40 +00:00
tsosunchia
ef57db1c09 Merge pull request #305 from nxtrace/main
Some checks failed
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
SYNC
2025-06-05 10:38:32 +08:00
tsosunchia
93c0f8558b 更新 nt_install.sh
https://github.com/nxtrace/NTrace-core/issues/300
2025-04-28 10:02:47 +08:00
SaltyFishEd
7bfccf9da4 feat(geoip): overwrite the owner field when asn.domain exists for ipdb.one datasource
feat(geoip): add asn.asname as whois field for ipdb.one datasource
2025-04-27 00:25:47 +08:00
SaltyFishEd
b5673b65a1 feat(geoip): support geoip data from ipdb.one 2025-04-18 14:43:56 +08:00
tsosunchia
946095458b update README 脚本安装命令修改 2025-04-16 17:18:52 +08:00
tsosunchia
28b329e365 update README 2025-04-16 09:44:22 +08:00
tsosunchia
c27dd3703a Merge pull request #85 from Yunlq/main
add support for custom source ports and optimize some code
2025-04-16 09:06:02 +08:00
Yunlq
b20c4b74cc add support for custom source ports and optimize some code 2025-04-16 02:54:19 +08:00
tsosunchia
deca060a9d Merge pull request #299 from nxtrace/main
Some checks failed
Build & Release / build (amd64, freebsd) (push) Has been cancelled
Build & Release / build (amd64, linux) (push) Has been cancelled
Build & Release / build (amd64, openbsd) (push) Has been cancelled
Build & Release / build (amd64, windows) (push) Has been cancelled
Build & Release / build (arm, 5, linux) (push) Has been cancelled
Build & Release / build (arm, 6, linux) (push) Has been cancelled
Build & Release / build (arm, 7, freebsd) (push) Has been cancelled
Build & Release / build (arm, 7, linux) (push) Has been cancelled
Build & Release / build (arm, 7, openbsd) (push) Has been cancelled
Build & Release / build (arm, 7, windows) (push) Has been cancelled
Build & Release / build (arm64, android) (push) Has been cancelled
Build & Release / build (arm64, darwin) (push) Has been cancelled
Build & Release / build (arm64, freebsd) (push) Has been cancelled
Build & Release / build (arm64, linux) (push) Has been cancelled
Build & Release / build (arm64, openbsd) (push) Has been cancelled
Build & Release / build (arm64, windows) (push) Has been cancelled
Build & Release / build (mips, linux) (push) Has been cancelled
Build & Release / build (mips, softfloat, linux) (push) Has been cancelled
Build & Release / build (mips64, linux) (push) Has been cancelled
Build & Release / build (mips64le, linux) (push) Has been cancelled
Build & Release / build (mipsle, linux) (push) Has been cancelled
Build & Release / build (mipsle, softfloat, linux) (push) Has been cancelled
Build & Release / build (ppc64, linux) (push) Has been cancelled
Build & Release / build (ppc64le, linux) (push) Has been cancelled
Build & Release / build (riscv64, linux) (push) Has been cancelled
Build & Release / build (s390x, linux) (push) Has been cancelled
Test / test (macos-latest) (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
Test / test (windows-latest) (push) Has been cancelled
Build & Release / publish-new-formula (push) Has been cancelled
update README
2025-04-15 16:53:14 +08:00
tsosunchia
fedf2946e0 update README
Signed-off-by: tsosunchia <59512455+tsosunchia@users.noreply.github.com>
2025-04-15 16:52:32 +08:00
tsosunchia
d0f5862258 Merge pull request #298 from nxtrace/main
SYNC
2025-04-15 16:37:57 +08:00
tsosunchia
0f8a646d71 fasttrace 增加上海/广州单独测试选项 2025-04-15 16:08:11 +08:00
tsosunchia
dccc41b995 udp mode增加mutex 以避免固定端口时的端口竞争问题 2025-04-15 15:43:41 +08:00
tsosunchia
9af629b6f9 ipgeo/leo.go 优化 receiveParse 的单例调用(WebSocket 连接的并发控制) 2025-04-15 13:36:42 +08:00
tsosunchia
d6de649e60 handleICMPMessage 采用更健壮的方案处理ICMPv6头部,之前使用了一个固定的偏移量来从 ICMPv6 错误消息中提取 UDP 源端口,现在改为动态计算偏移量 2025-04-15 13:16:15 +08:00
21 changed files with 509 additions and 80 deletions

View File

@@ -58,7 +58,7 @@ Please note, there are exceptions to this synchronization. If a version of NTrac
* Linux
* One-click installation script
```shell
curl nxtrace.org/nt |bash
curl -sL nxtrace.org/nt |bash
```
* Install nxtrace from the APT repository
@@ -210,7 +210,7 @@ nexttrace --dev eth0 2606:4700:4700::1111
nexttrace --source 204.98.134.56 9.9.9.9
```
`NextTrace` can also use `TCP` and `UDP` protocols to perform `Traceroute` requests, but `UDP` protocols only supports `IPv4` now
`NextTrace` can also use `TCP` and `UDP` protocols to perform `Traceroute` requests
```bash
# TCP SYN Trace
@@ -222,7 +222,12 @@ nexttrace --tcp --port 443 2001:4860:4860::8888
# UDP Trace
nexttrace --udp 1.0.0.1
nexttrace --udp --port 53 1.0.0.1
# You can specify the target port yourself [here it is 5353], the default is port 33494
nexttrace --udp --port 5353 1.0.0.1
# For TCP/UDP Trace, you can specify the source port; by default, a fixed random port is used
# (if you need to use a different random source port for each packet, please set the ENV variable NEXTTRACE_RANDOMPORT)
nexttrace --tcp --source-port 14514 www.bing.com
```
`NextTrace` also supports some advanced functions, such as ttl control, concurrent probe packet count control, mode switching, etc.
@@ -383,6 +388,8 @@ Arguments:
-e --disable-mpls Disable MPLS
-v --version Print version info and exit
-s --source Use source src_addr for outgoing packets
--source-port Use source port src_port for outgoing
packets
-D --dev Use the following Network Devices as the
source address in outgoing packets
-z --send-time Set how many [milliseconds] between
@@ -453,6 +460,12 @@ The LeoMoeAPI data is subject to copyright restrictions from multiple data sourc
We hope you can give us as much feedback as possible on IP geolocation errors (see issue) so that it can be calibrated in the first place and others can benefit from it.
## AIWEN TECH Support
This project is sponsored by [AIWEN TECH](https://www.ipplus360.com). Were pleased to enhance the accuracy and completeness of this projects GEOIP lookups using `AIWEN TECH City-Level IP Database`, and to make it freely available to the public.
<img src="https://www.ipplus360.com/img/LOGO.c86cd0e1.svg" title="" alt="AIWEN TECH IP Geolocation Data" width="331">
## JetBrain Support
This Project uses [JetBrain Open-Source Project License](https://jb.gg/OpenSourceSupport). We Proudly Develop By `Goland`.

View File

@@ -65,7 +65,7 @@ Document Language: [English](README.md) | 简体中文
* Linux
* 一键安装脚本
```shell
curl nxtrace.org/nt | bash
curl -sL nxtrace.org/nt | bash
```
* 从 nxtrace的APT源安装
@@ -220,20 +220,23 @@ nexttrace --dev eth0 2606:4700:4700::1111
nexttrace --source 204.98.134.56 9.9.9.9
```
`NextTrace` 也可以使用`TCP`和`UDP`协议发起`Traceroute`请求,不过目前`UDP`只支持`IPv4`
`NextTrace` 也可以使用`TCP`和`UDP`协议发起`Traceroute`请求
```bash
# TCP SYN Trace
nexttrace --tcp www.bing.com
# 可以自行指定端口[此处为443]默认80端口
# 可以自行指定目标端口[此处为443]默认80端口
nexttrace --tcp --port 443 2001:4860:4860::8888
# UDP Trace
nexttrace --udp 1.0.0.1
# 可以自行指定端口[此处为5353]默认33494端口
# 可以自行指定目标端口[此处为5353]默认33494端口
nexttrace --udp --port 5353 1.0.0.1
# TCP/UDP Trace 可以自行指定源端口,默认使用随机一个固定的端口(如需每次发包随机使用不同的源端口,请设置`ENV` `NEXTTRACE_RANDOMPORT`)
nexttrace --tcp --source-port 14514 www.bing.com
```
`NextTrace`也同样支持一些进阶功能,如 TTL 控制、并发数控制、模式切换等
@@ -377,6 +380,8 @@ Arguments:
-e --disable-mpls Disable MPLS
-v --version Print version info and exit
-s --source Use source src_addr for outgoing packets
--source-port Use source port src_port for outgoing
packets
-D --dev Use the following Network Devices as the
source address in outgoing packets
-z --send-time Set how many [milliseconds] between
@@ -452,6 +457,12 @@ nexttrace --pow-provider sakura
[https://github.com/nxtrace/NextTraceroute](https://github.com/nxtrace/NextTraceroute)
<a href='https://play.google.com/store/apps/details?id=com.surfaceocean.nexttraceroute&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' width="128" height="48" src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png'/></a>
## AIWEN TECH Support
本项目受 [埃文科技](https://www.ipplus360.com) 赞助。 很高兴使用`埃文科技城市级IP库`增强本项目 GEOIP 查询的准确性与完整性,并免费提供给公众。
<img src="https://www.ipplus360.com/img/LOGO.c86cd0e1.svg" title="" alt="埃文科技 IP 定位数据" width="331">
## JetBrain Support
本项目受 [JetBrain Open-Source Project License](https://jb.gg/OpenSourceSupport) 支持。 很高兴使用`Goland`作为我们的开发工具。

View File

@@ -39,7 +39,7 @@ func Excute() {
numMeasurements := parser.Int("q", "queries", &argparse.Options{Default: 3, Help: "Set the number of probes per each hop"})
parallelRequests := parser.Int("", "parallel-requests", &argparse.Options{Default: 18, Help: "Set ParallelRequests number. It should be 1 when there is a multi-routing"})
maxHops := parser.Int("m", "max-hops", &argparse.Options{Default: 30, Help: "Set the max number of hops (max TTL to be reached)"})
dataOrigin := parser.Selector("d", "data-provider", []string{"Ip2region", "ip2region", "IP.SB", "ip.sb", "IPInfo", "ipinfo", "IPInsight", "ipinsight", "IPAPI.com", "ip-api.com", "IPInfoLocal", "ipinfolocal", "chunzhen", "LeoMoeAPI", "leomoeapi", "disable-geoip"}, &argparse.Options{Default: "LeoMoeAPI",
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", "ipdb.one", "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.nxtrace.org", "sakura"}, &argparse.Options{Default: "api.nxtrace.org",
Help: "Choose PoW Provider [api.nxtrace.org, sakura] For China mainland users, please use sakura"})
@@ -57,12 +57,13 @@ func Excute() {
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"})
srcAddr := parser.String("s", "source", &argparse.Options{Help: "Use source address src_addr for outgoing packets"})
srcPort := parser.Int("", "source-port", &argparse.Options{Help: "Use source port src_port for outgoing packets"})
srcDev := parser.String("D", "dev", &argparse.Options{Help: "Use the following Network Devices as the source address in outgoing packets"})
//router := parser.Flag("R", "route", &argparse.Options{Help: "Show Routing Table [Provided By BGP.Tools]"})
packetInterval := parser.Int("z", "send-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending each packet.. Useful when some routers use rate-limit for ICMP messages"})
packetInterval := parser.Int("z", "send-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending each packet. Useful when some routers use rate-limit for ICMP messages"})
ttlInterval := parser.Int("i", "ttl-time", &argparse.Options{Default: 50, Help: "Set how many [milliseconds] between sending packets groups by TTL. Useful when some routers use rate-limit for ICMP messages"})
timeout := parser.Int("", "timeout", &argparse.Options{Default: 1000, Help: "The number of [milliseconds] to keep probe sockets open before giving up on the connection."})
timeout := parser.Int("", "timeout", &argparse.Options{Default: 1000, Help: "The number of [milliseconds] to keep probe sockets open before giving up on the connection"})
packetSize := parser.Int("", "psize", &argparse.Options{Default: 52, Help: "Set the payload size"})
str := parser.StringPositional(&argparse.Options{Help: "IP Address or domain name"})
dot := parser.Selector("", "dot-server", []string{"dnssb", "aliyun", "dnspod", "google", "cloudflare"}, &argparse.Options{
@@ -255,6 +256,7 @@ func Excute() {
var conf = trace.Config{
DN42: *dn42,
SrcAddr: *srcAddr,
SrcPort: *srcPort,
BeginHop: *beginHop,
DestIP: ip,
DestPort: *port,

View File

@@ -116,7 +116,7 @@ func (f *FastTracer) testEDU_v6() {
f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CST)
}
func (f *FastTracer) testFast_v6() {
func (f *FastTracer) testFastBJ_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)
@@ -124,12 +124,24 @@ func (f *FastTracer) testFast_v6() {
//f.tracert_v6(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CST)
}
func (f *FastTracer) testFastSH_v6() {
f.tracert_v6(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CT163)
f.tracert_v6(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CU169)
f.tracert_v6(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CM)
}
func (f *FastTracer) testFastGZ_v6() {
f.tracert_v6(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CT163)
f.tracert_v6(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CU169)
f.tracert_v6(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CM)
}
func FastTestv6(traceMode trace.Method, outEnable bool, paramsFastTrace ParamsFastTrace) {
var c string
oe = outEnable
fmt.Println("您想测试哪些ISP的路由\n1. 北京三网快速测试\n2. 全国电信\n3. 全国联通\n4. 全国移动\n5. 全国教育网\n6. 全国五网")
fmt.Println("您想测试哪些ISP的路由\n1. 北京三网快速测试\n2. 上海三网快速测试\n3. 广州三网快速测试\n4. 全国电信\n5. 全国联通\n6. 全国移动\n7. 全国教育网\n8. 全国五网")
fmt.Print("请选择选项:")
_, err := fmt.Scanln(&c)
if err != nil {
@@ -159,18 +171,22 @@ func FastTestv6(traceMode trace.Method, outEnable bool, paramsFastTrace ParamsFa
switch c {
case "1":
ft.testFast_v6()
ft.testFastBJ_v6()
case "2":
ft.testCT_v6()
ft.testFastSH_v6()
case "3":
ft.testCU_v6()
ft.testFastGZ_v6()
case "4":
ft.testCM_v6()
ft.testCT_v6()
case "5":
ft.testEDU_v6()
ft.testCU_v6()
case "6":
ft.testCM_v6()
case "7":
ft.testEDU_v6()
case "8":
ft.testAll_v6()
default:
ft.testFast_v6()
ft.testFastBJ_v6()
}
}

View File

@@ -162,7 +162,7 @@ func FastTest(traceMode trace.Method, outEnable bool, paramsFastTrace ParamsFast
}
}
fmt.Println("您想测试哪些ISP的路由\n1. 北京三网快速测试\n2. 全国电信\n3. 全国联通\n4. 全国移动\n5. 全国教育网\n6. 全国五网")
fmt.Println("您想测试哪些ISP的路由\n1. 北京三网快速测试\n2. 上海三网快速测试\n3. 广州三网快速测试\n4. 全国电信\n5. 全国联通\n6. 全国移动\n7. 全国教育网\n8. 全国五网")
fmt.Print("请选择选项:")
_, err = fmt.Scanln(&c)
if err != nil {
@@ -192,19 +192,23 @@ func FastTest(traceMode trace.Method, outEnable bool, paramsFastTrace ParamsFast
switch c {
case "1":
ft.testFast()
ft.testFastBJ()
case "2":
ft.testCT()
ft.testFastSH()
case "3":
ft.testCU()
ft.testFastGZ()
case "4":
ft.testCM()
ft.testCT()
case "5":
ft.testEDU()
ft.testCU()
case "6":
ft.testCM()
case "7":
ft.testEDU()
case "8":
ft.testAll()
default:
ft.testFast()
ft.testFastBJ()
}
}
@@ -430,10 +434,22 @@ func (f *FastTracer) testEDU() {
f.tracert(TestIPsCollection.Hefei.Location, TestIPsCollection.Hefei.CST)
}
func (f *FastTracer) testFast() {
func (f *FastTracer) testFastBJ() {
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)
//f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CST)
}
func (f *FastTracer) testFastSH() {
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CT163)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CU169)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CM)
}
func (f *FastTracer) testFastGZ() {
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CT163)
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CU169)
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CM)
}

16
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/nxtrace/NTrace-core
go 1.24.1
go 1.24.5
require (
github.com/akamensky/argparse v1.4.0
@@ -10,14 +10,14 @@ require (
github.com/stretchr/testify v1.10.0
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/tsosunchia/powclient v0.1.5
golang.org/x/net v0.39.0
golang.org/x/sync v0.13.0
golang.org/x/net v0.42.0
golang.org/x/sync v0.16.0
)
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
@@ -25,11 +25,11 @@ require (
github.com/sagikazarmark/locafero v0.9.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.14.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/spf13/cast v1.9.2 // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/text v0.27.0 // indirect
)
require (
@@ -40,6 +40,6 @@ require (
github.com/tidwall/gjson v1.18.0
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/sys v0.34.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

28
go.sum
View File

@@ -10,8 +10,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
@@ -49,10 +49,10 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -86,19 +86,19 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

265
ipgeo/ipdbone.go Normal file
View File

@@ -0,0 +1,265 @@
package ipgeo
import (
"errors"
"io"
"net/http"
"strconv"
"sync"
"time"
"github.com/nxtrace/NTrace-core/config"
"github.com/nxtrace/NTrace-core/util"
"github.com/tidwall/gjson"
)
// Language mapping for IPDB.One API
var LangMap = map[string]string{
"en": "en",
"cn": "zh",
}
// IPDBOneConfig holds the configuration for IPDB.One service
type IPDBOneConfig struct {
BaseURL string
ApiID string
ApiKey string
}
// GetDefaultConfig returns the default configuration with fallback values
func GetDefaultConfig() *IPDBOneConfig {
return &IPDBOneConfig{
BaseURL: util.GetenvDefault("IPDBONE_BASE_URL", "https://api.ipdb.one"),
ApiID: util.GetenvDefault("IPDBONE_API_ID", ""),
ApiKey: util.GetenvDefault("IPDBONE_API_KEY", ""),
}
}
// IPDBOneTokenCache manages the caching of auth tokens
type IPDBOneTokenCache struct {
token string
expiresAt time.Time
mutex sync.RWMutex
}
// GetToken retrieves cached token if valid, otherwise returns empty string
func (c *IPDBOneTokenCache) GetToken() string {
c.mutex.RLock()
defer c.mutex.RUnlock()
if c.token == "" || time.Now().After(c.expiresAt) {
return ""
}
return c.token
}
// SetToken updates the token with its expiration time
func (c *IPDBOneTokenCache) SetToken(token string, expiresIn time.Duration) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.token = token
c.expiresAt = time.Now().Add(expiresIn)
}
// IPDBOneClient handles communication with IPDB.One API
type IPDBOneClient struct {
config *IPDBOneConfig
tokenCache *IPDBOneTokenCache
tokenInit sync.Once
httpClient *http.Client
}
// NewIPDBOneClient creates a new client for IPDB.One with default configuration
func NewIPDBOneClient() *IPDBOneClient {
return &IPDBOneClient{
config: GetDefaultConfig(),
tokenCache: &IPDBOneTokenCache{},
httpClient: &http.Client{
Timeout: 3 * time.Second,
},
}
}
// fetchToken requests a new authentication token from the API
func (c *IPDBOneClient) fetchToken() error {
authURL := c.config.BaseURL + "/auth/requestToken/query"
req, err := http.NewRequest("GET", authURL, nil)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "NextTrace/"+config.Version)
req.Header.Set("x-api-id", c.config.ApiID)
req.Header.Set("x-api-key", c.config.ApiKey)
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
statusCode := gjson.Get(string(body), "code").Int()
statusMessage := gjson.Get(string(body), "message").String()
if statusCode != 200 {
return errors.New("failed to authenticate: " + statusMessage)
}
token := gjson.Get(string(body), "data.token").String()
if token == "" {
return errors.New("authentication failed: empty token received")
}
// Cache token with a 30-second expiration
c.tokenCache.SetToken(token, 30*time.Second)
return nil
}
// ensureToken makes sure a valid token is available, fetching a new one if needed
func (c *IPDBOneClient) ensureToken() error {
var initErr error
// Ensure API credentials are set
if c.config.ApiID == "" || c.config.ApiKey == "" {
return errors.New("api id or api key is not set")
}
// Initialize token the first time this is called
c.tokenInit.Do(func() {
initErr = c.fetchToken()
})
if initErr != nil {
return initErr
}
// If token expired or not available, get a new one
if c.tokenCache.GetToken() == "" {
return c.fetchToken()
}
return nil
}
// LookupIP queries the IP information from IPDB.One
func (c *IPDBOneClient) LookupIP(ip string, lang string) (*IPGeoData, error) {
// Ensure we have a valid token
if err := c.ensureToken(); err != nil {
return &IPGeoData{}, nil
}
// Map language code if needed
langCode, ok := LangMap[lang]
if !ok {
langCode = "en" // Default to English
}
// Query the IP information
queryURL := c.config.BaseURL + "/query/" + ip + "?lang=" + langCode
req, err := http.NewRequest("GET", queryURL, nil)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "NextTrace/"+config.Version)
req.Header.Set("Authorization", "Bearer "+c.tokenCache.GetToken())
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
statusCode := gjson.Get(string(body), "code").Int()
if statusCode != 200 {
return nil, errors.New("failed to get IP info: " + gjson.Get(string(body), "message").String())
}
return parseIPDBOneResponse(ip, body)
}
// parseIPDBOneResponse converts the API response to an IPGeoData struct
func parseIPDBOneResponse(ip string, responseBody []byte) (*IPGeoData, error) {
data := gjson.Get(string(responseBody), "data")
geoData := data.Get("geo")
routingData := data.Get("routing")
result := &IPGeoData{
IP: ip,
}
// Parse geo information if available
if geoData.Exists() {
coordinate := geoData.Get("coordinate")
if coordinate.Exists() && coordinate.Type != gjson.Null && coordinate.IsArray() && len(coordinate.Array()) >= 2 {
result.Lat = coordinate.Array()[0].Float()
result.Lng = coordinate.Array()[1].Float()
}
if geoData.Get("country").Exists() && geoData.Get("country").Type != gjson.Null {
result.Country = geoData.Get("country").String()
}
if geoData.Get("region").Exists() && geoData.Get("region").Type != gjson.Null {
result.Prov = geoData.Get("region").String()
}
if geoData.Get("city").Exists() && geoData.Get("city").Type != gjson.Null {
result.City = geoData.Get("city").String()
}
}
// Parse routing information if available
if routingData.Exists() {
asnData := routingData.Get("asn")
if asnData.Get("number").Exists() && asnData.Get("number").Type != gjson.Null {
result.Asnumber = strconv.FormatInt(asnData.Get("number").Int(), 10)
}
if routingData.Get("asn.name").Exists() && routingData.Get("asn.name").Type != gjson.Null {
result.Owner = routingData.Get("asn.name").String()
}
// Get domain, override owner
if routingData.Get("asn.domain").Exists() && routingData.Get("asn.domain").Type != gjson.Null {
result.Owner = routingData.Get("asn.domain").String()
}
// Get asname as Whois
if routingData.Get("asn.asname").Exists() && routingData.Get("asn.asname").Type != gjson.Null {
result.Whois = routingData.Get("asn.asname").String()
}
}
return result, nil
}
// Global client instance for backward compatibility
var defaultClient = NewIPDBOneClient()
// IPDBOne looks up IP information from IPDB.One (maintains backward compatibility)
func IPDBOne(ip string, timeout time.Duration, lang string, _ bool) (*IPGeoData, error) {
// Override timeout if specified
if timeout > 0 {
defaultClient.httpClient.Timeout = timeout
}
return defaultClient.LookupIP(ip, lang)
}

View File

@@ -52,6 +52,8 @@ func GetSource(s string) Source {
return Chunzhen
case "DISABLE-GEOIP":
return disableGeoIP
case "IPDB.ONE":
return IPDBOne
default:
return LeoIP
}

View File

@@ -83,6 +83,11 @@ func receiveParse() {
}
}
// 当前的实现中,每次调用 receiveParse() 都会锁定 WebSocket 连接
// 当前为单例模式,只启动一个 receiveParse 协程
var receiveParseOnce sync.Once
func LeoIP(ip string, timeout time.Duration, lang string, maptrace bool) (*IPGeoData, error) {
// TODO: 根据lang的值请求中文/英文API
// TODO: 根据maptrace的值决定是否请求经纬度信息
@@ -100,7 +105,10 @@ func LeoIP(ip string, timeout time.Duration, lang string, maptrace bool) (*IPGeo
// 发送请求
sendIPRequest(ip)
// 同步开启监听
go receiveParse()
// 确保 receiveParse 只启动一次
receiveParseOnce.Do(func() {
go receiveParse()
})
// 拥塞,等待数据返回
select {

View File

@@ -60,7 +60,7 @@ checkSystemDistribution() {
downloadBinrayFile() {
echo -e "${Info} 获取最新版的 NextTrace 发行版文件信息"
for i in {1..3}; do
downloadUrls=$(curl -sLf ${protocol}://www.nxtrace.org/api/dist/core/nexttrace_${osDistribution}_${archParam} --connect-timeout 1.5)
downloadUrls=$(curl -sLf ${protocol}://www.nxtrace.org/api/dist/core/nexttrace_${osDistribution}_${archParam} --connect-timeout 2)
if [ $? -eq 0 ]; then
break
fi
@@ -70,7 +70,7 @@ downloadBinrayFile() {
backupUrl=$(echo ${downloadUrls} | awk -F '|' '{print $2}')
echo -e "${Info} 正在尝试从 Primary 节点下载 NextTrace"
for i in {1..3}; do
curl -sLf ${primaryUrl} -o ${Temp_path} --connect-timeout 1.5
curl -sLf ${primaryUrl} -o ${Temp_path} --connect-timeout 2
if [ $? -eq 0 ]; then
changeMode
mv ${Temp_path} ${downPath}
@@ -84,7 +84,7 @@ downloadBinrayFile() {
fi
echo -e "${Error} 从 Primary 节点下载失败,正在尝试从 Backup 节点下载 NextTrace"
for i in {1..3}; do
curl -sLf ${backupUrl} -o ${Temp_path} --connect-timeout 1.5
curl -sLf ${backupUrl} -o ${Temp_path} --connect-timeout 2
if [ $? -eq 0 ]; then
changeMode
mv ${Temp_path} ${downPath}

View File

@@ -13,12 +13,17 @@ type ReceivedMessage struct {
Err error
}
// PacketListener 负责监听网络数据包并通过通道传递接收到的消息
type PacketListener struct {
ctx context.Context
Conn net.PacketConn
Messages chan ReceivedMessage
}
// NewPacketListener 创建一个新的数据包监听器
// conn: 用于接收数据包的连接
// ctx: 用于控制监听器生命周期的上下文
// 返回初始化好的 PacketListener 实例
func NewPacketListener(conn net.PacketConn, ctx context.Context) *PacketListener {
results := make(chan ReceivedMessage, 50)

View File

@@ -211,7 +211,12 @@ func (t *TCPTracer) send(ttl int) error {
}
// 随机种子
r := rand.New(rand.NewSource(time.Now().UnixNano()))
_, srcPort := util.LocalIPPort(t.DestIP)
_, srcPort := func() (net.IP, int) {
if util.EnvRandomPort == "" && t.SrcPort != 0 {
return nil, t.SrcPort
}
return util.LocalIPPort(t.DestIP)
}()
ipHeader := &layers.IPv4{
SrcIP: t.SrcIP,
DstIP: t.DestIP,

View File

@@ -200,7 +200,12 @@ func (t *TCPTracerIPv6) send(ttl int) error {
}
// 随机种子
r := rand.New(rand.NewSource(time.Now().UnixNano()))
_, srcPort := util.LocalIPPortv6(t.DestIP)
_, srcPort := func() (net.IP, int) {
if util.EnvRandomPort == "" && t.SrcPort != 0 {
return nil, t.SrcPort
}
return util.LocalIPPortv6(t.DestIP)
}()
ipHeader := &layers.IPv6{
SrcIP: t.SrcIP,
DstIP: t.DestIP,

View File

@@ -23,6 +23,7 @@ var (
type Config struct {
SrcAddr string
SrcPort int
BeginHop int
MaxHops int
NumMeasurements int

View File

@@ -32,6 +32,7 @@ type UDPTracer struct {
sem *semaphore.Weighted
fetchLock sync.Mutex
udpMutex sync.Mutex
}
func (t *UDPTracer) Execute() (*Result, error) {
@@ -148,7 +149,10 @@ func (t *UDPTracer) getUDPConn(try int) (net.IP, int, net.PacketConn, error) {
}
// Check environment variable to decide caching behavior
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
if util.EnvRandomPort == "" {
if t.SrcPort != 0 {
cachedLocalPort = t.SrcPort
}
// Use cached random port logic
if cachedLocalPort == 0 {
// First time: listen on a random port
@@ -192,6 +196,11 @@ func (t *UDPTracer) send(ttl int) error {
return nil
}
if util.EnvRandomPort == "" {
t.udpMutex.Lock()
defer t.udpMutex.Unlock()
}
srcIP, srcPort, udpConn, err := t.getUDPConn(0)
if err != nil {
return err

View File

@@ -32,6 +32,7 @@ type UDPTracerIPv6 struct {
sem *semaphore.Weighted
fetchLock sync.Mutex
udpMutex sync.Mutex
}
func (t *UDPTracerIPv6) Execute() (*Result, error) {
@@ -117,16 +118,77 @@ func (t *UDPTracerIPv6) listenICMP() {
}
}
// handleICMPMessage 处理 ICMPv6 消息并提取 UDP 源端口
//
// ICMPv6 错误消息格式:
// - ICMPv6 头部 (8 字节)
// - 原始 IPv6 包 (包含 IPv6 头部和 UDP 头部)
//
// 处理步骤:
// 1. 验证消息长度
// 2. 解析 ICMPv6 头部
// 3. 提取原始 IPv6 包
// 4. 处理可能的扩展头部
// 5. 提取 UDP 源端口
// 6. 发送结果到对应通道
func (t *UDPTracerIPv6) handleICMPMessage(msg ReceivedMessage) {
// 对于IPv6我们需要从ICMP消息中提取UDP源端口
// 这里假设UDP头部在ICMP消息的固定位置
if len(msg.Msg) < 48+8 {
// ICMPv6 错误消息至少需要包含 IPv6 头部(40字节)和部分 UDP 头部
if len(msg.Msg) < 48 {
return
}
// IPv6 ICMP错误消息包含原始数据包的IPv6头(40字节)和UDP头(8字节)
// 从UDP头部提取源端口(前2字节)
srcPort := int(uint16(msg.Msg[48])<<8 | uint16(msg.Msg[49]))
// 尝试解析 ICMPv6 消息包含原始数据包
var offset int = 8 // ICMPv6 头部长度
// 检查剩余长度是否足够包含 IPv6 头部
if len(msg.Msg) < offset+40 {
return
}
// 验证 IPv6 版本 (前4位应该是6)
if (msg.Msg[offset] >> 4) != 6 {
return
}
// 获取下一个头部类型
nextHeader := msg.Msg[offset+6]
// 跳过 IPv6 基本头部
offset += 40
// 处理可能的扩展头部
for nextHeader != 17 && offset+2 < len(msg.Msg) { // 17 是 UDP 协议号
switch nextHeader {
case 0: // Hop-by-Hop Options
case 43: // Routing
case 44: // Fragment
case 50: // ESP
case 51: // AH
case 60: // Destination Options
if offset+2 >= len(msg.Msg) {
return // 不够长,无法读取扩展头部长度
}
nextHeader = msg.Msg[offset]
headerLen := int(msg.Msg[offset+1])*8 + 8
offset += headerLen
default:
// 未知或不支持的扩展头部类型
return
}
}
// 确认下一个头部是 UDP (17)
if nextHeader != 17 {
return
}
// 确保有足够的数据来读取 UDP 源端口
if offset+2 > len(msg.Msg) {
return
}
// 从 UDP 头部提取源端口(前2字节)
srcPort := int(uint16(msg.Msg[offset])<<8 | uint16(msg.Msg[offset+1]))
t.inflightRequestLock.Lock()
defer t.inflightRequestLock.Unlock()
@@ -152,7 +214,10 @@ func (t *UDPTracerIPv6) getUDPConn(try int) (net.IP, int, net.PacketConn, error)
}
// Check environment variable to decide caching behavior
if util.GetenvDefault("NEXTTRACE_RANDOMPORT", "") == "" {
if util.EnvRandomPort == "" {
if t.SrcPort != 0 {
cachedLocalPortv6 = t.SrcPort
}
// Use cached random port logic
if cachedLocalPortv6 == 0 {
// First time: listen on a random port
@@ -196,6 +261,11 @@ func (t *UDPTracerIPv6) send(ttl int) error {
return nil
}
if util.EnvRandomPort == "" {
t.udpMutex.Lock()
defer t.udpMutex.Unlock()
}
srcIP, srcPort, udpConn, err := t.getUDPConn(0)
if err != nil {
return err

View File

@@ -23,7 +23,7 @@ func GetMapUrl(r string) (string, error) {
if len(strings.Split(fastIp, ":")) > 1 {
fastIp = "[" + fastIp + "]"
}
host = "origin-fallback.nxtrace.org"
host = "api.nxtrace.org"
} else {
// 默认配置完成,开始寻找最优 IP
fastIp = util.GetFastIP(host, port, false)

View File

@@ -30,7 +30,7 @@ var FastIpCache = ""
func GetFastIP(domain string, port string, enableOutput bool) string {
proxyUrl := GetProxy()
if proxyUrl != nil {
return "origin-fallback.nxtrace.org"
return "api.nxtrace.org"
}
if FastIpCache != "" {
return FastIpCache
@@ -38,7 +38,7 @@ func GetFastIP(domain string, port string, enableOutput bool) string {
var ips []net.IP
var err error
if domain == "origin-fallback.nxtrace.org" {
if domain == "api.nxtrace.org" {
ips, err = net.LookupIP("api.nxtrace.org")
} else {
ips, err = net.LookupIP(domain)
@@ -122,6 +122,7 @@ func checkLatency(domain string, ip string, port string) {
return
}
req.Host = domain
req.Header.Add("User-Agent", UserAgent)
resp, err := client.Do(req)
if err != nil {
//results <- ResponseInfo{IP: ip, Latency: "error", Content: ""}

View File

@@ -16,15 +16,16 @@ import (
"github.com/fatih/color"
)
var Uninterrupted = GetenvDefault("NEXTTRACE_UNINTERRUPTED", "")
var EnvToken = GetenvDefault("NEXTTRACE_TOKEN", "")
var EnvIPInfoLocalPath = GetenvDefault("NEXTTRACE_IPINFOLOCALPATH", "")
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", "")
var EnableHidDstIP = GetenvDefault("NEXTTRACE_ENABLEHIDDENDSTIP", "")
var EnvIPInfoLocalPath = GetenvDefault("NEXTTRACE_IPINFOLOCALPATH", "")
var EnvRandomPort = GetenvDefault("NEXTTRACE_RANDOMPORT", "")
var EnvToken = GetenvDefault("NEXTTRACE_TOKEN", "")
var Uninterrupted = GetenvDefault("NEXTTRACE_UNINTERRUPTED", "")
var DestIP string
var PowProviderParam = ""
var RdnsCache sync.Map
var UserAgent = fmt.Sprintf("NextTrace %s/%s/%s", config.Version, runtime.GOOS, runtime.GOARCH)
var cachedLocalIP net.IP
var cachedLocalPort int
var localIPOnce sync.Once
@@ -84,10 +85,10 @@ func getLocalIPPortv6(dstip net.IP) (net.IP, int) {
return nil, -1
}
// LocalIPPort returns the local IP and port based on our destination IP, with caching unless NEXTTRACE_RANDOMPORT is set.
// LocalIPPort returns the local IP and port based on our destination IP, with caching unless EnvRandomPort is set.
func LocalIPPort(dstip net.IP) (net.IP, int) {
// If NEXTTRACE_RANDOMPORT is set, bypass caching and return a new port every time.
if GetenvDefault("NEXTTRACE_RANDOMPORT", "") != "" {
// If EnvRandomPort is set, bypass caching and return a new port every time.
if EnvRandomPort != "" {
return getLocalIPPort(dstip)
}
@@ -102,9 +103,8 @@ func LocalIPPort(dstip net.IP) (net.IP, int) {
}
func LocalIPPortv6(dstip net.IP) (net.IP, int) {
// If NEXTTRACE_RANDOMPORT is set, bypass caching and return a new port every time.
// 该ENV仅对TCP Mode有效UDP Mode暂无办法固定Port
if GetenvDefault("NEXTTRACE_RANDOMPORT", "") != "" {
// If EnvRandomPort is set, bypass caching and return a new port every time.
if EnvRandomPort != "" {
return getLocalIPPortv6(dstip)
}
@@ -208,7 +208,7 @@ func GetenvDefault(key, defVal string) string {
}
func GetHostAndPort() (host string, port string) {
var hostP = GetenvDefault("NEXTTRACE_HOSTPORT", "origin-fallback.nxtrace.org")
var hostP = GetenvDefault("NEXTTRACE_HOSTPORT", "api.nxtrace.org")
// 解析域名
hostArr := strings.Split(hostP, ":")
// 判断是否有指定端口

View File

@@ -193,7 +193,7 @@ func createWsConn() *WsConn {
if len(strings.Split(fastIp, ":")) > 1 {
fastIp = "[" + fastIp + "]"
}
host = "origin-fallback.nxtrace.org"
host = "api.nxtrace.org"
} else {
// 默认配置完成,开始寻找最优 IP
fastIp = util.GetFastIP(host, port, true)