Compare commits

..

194 Commits

Author SHA1 Message Date
sjlleo
50cc9858d4 No Longer Needed 2022-06-06 15:29:24 +08:00
sjlleo
27f49f9cd0 Merge pull request #34 from xgadget-lab/dev/fast-test
add: 新功能,快速路由测试
2022-06-06 15:27:40 +08:00
sjlleo
e4320da08d add: 新功能,快速路由测试 2022-06-06 15:27:09 +08:00
zhshch2002
7f16a27580 update: macOS brew 安装命令 2022-06-06 11:02:21 +08:00
zhshch2002
7db77024a3 revert: .macos_compil.sh 2022-06-06 10:59:28 +08:00
zhshch2002
c4ea506c35 update: .macos_compil.sh 2022-06-06 10:32:09 +08:00
zhshch2002
39e2471845 add: macOS homebrew 编译脚本 2022-06-06 10:18:11 +08:00
sjlleo
18a9eefec9 Revert "Revert "update: 脚本运行不需要保存在本地""
This reverts commit 3f0b14341a.
2022-06-05 15:51:38 +08:00
sjlleo
1b743d1f17 Revert "update: 移除 wget 依赖"
This reverts commit 8f77050fca.
2022-06-05 15:51:10 +08:00
sjlleo
3f0b14341a Revert "update: 脚本运行不需要保存在本地"
This reverts commit 2ffd7fdb58.
2022-06-05 15:50:45 +08:00
sjlleo
2ffd7fdb58 update: 脚本运行不需要保存在本地 2022-06-05 14:33:30 +08:00
sjlleo
8f77050fca update: 移除 wget 依赖 2022-06-05 14:29:41 +08:00
sjlleo
65652bd4e2 fix: 小问题 2022-06-05 14:22:24 +08:00
sjlleo
4176407a8a update: 精简安装脚本 2022-06-05 14:19:00 +08:00
sjlleo
6bc4abeaf8 update: TCP/UDP路由跟踪时,将不会再显示IPv6 IP 2022-06-04 21:42:44 +08:00
sjlleo
af0d886a02 update: yaml.v2 should direct. 2022-06-04 21:41:49 +08:00
sjlleo
09fdd2ac37 update: 现在偏好设置支持自定义数据源、自定义显示模式,以及对部分描述不当的参数说明进行了修正 2022-06-04 21:25:56 +08:00
sjlleo
2b9d8176d4 update: 现在默认无需配置即可使用,对于高阶用户,可以使用-c生成属于自己的偏好 2022-06-04 20:28:58 +08:00
tsosunchia
ed2f89310f Update README.md 2022-06-04 17:15:23 +08:00
tsosunchia
bd5a8902d4 更改部分提示信息 2022-06-04 17:02:26 +08:00
tsosunchia
e2a1bfe8cf 把部分选项隐藏放进了--expert选项 2022-06-04 16:59:07 +08:00
zhshch2002
356b782b3d update: screenshot 2022-06-04 11:04:42 +08:00
zhshch2002
40922ae13a update: screenshot 2022-06-04 10:45:33 +08:00
tsosunchia
8e90795a54 Update nt_install.sh 2022-06-03 19:48:47 +08:00
sjlleo
bbbb2377e1 fix: 当有多个路由跟踪实例,且跟踪通一个IP的时候的干扰问题 2022-06-03 19:28:53 +08:00
sjlleo
efdfd9d612 fix: 修复一个多线程路由跟踪错乱的问题 2022-06-03 16:26:01 +08:00
sjlleo
016f06bafd cleanup 2022-06-02 21:51:50 +08:00
sjlleo
1049986ebc cleanup 2022-06-02 21:48:19 +08:00
tsosunchia
80a75288d2 由于9.0.0.0/8 以及11.0.0.0/8大量用于其他IDC业务,因此清除特殊标记 2022-06-02 20:38:43 +08:00
tsosunchia
986b8ce300 Merge remote-tracking branch 'refs/remotes/origin/main'
fetch README
2022-05-31 21:00:07 +08:00
tsosunchia
ab774406ac 减少一处警告 2022-05-31 20:59:56 +08:00
sjlleo
9604b7befe update: announcement 2022-05-31 20:48:39 +08:00
tsosunchia
dc6537005a fix some bugs 2022-05-31 19:41:12 +08:00
tsosunchia
839d227770 fix some bugs 2022-05-31 19:15:39 +08:00
tsosunchia
84e989e71b fix some bugs 2022-05-31 19:15:29 +08:00
tsosunchia
3b74b302cc fix some bugs 2022-05-31 18:35:59 +08:00
tsosunchia
9b0e58359f 改善脚本在国内环境下的表现 2022-05-31 18:27:22 +08:00
tsosunchia
f0d7151144 Update README.md 2022-05-31 18:21:31 +08:00
tsosunchia
3c65c29eff 改善脚本在国内环境下的表现 2022-05-31 18:14:51 +08:00
sjlleo
3aa4696fa9 add: 新增配置文件模块 2022-05-30 21:15:22 +08:00
sjlleo
b4abaffc7c update: 让截图大小适中 2022-05-28 11:09:45 +08:00
sjlleo
c96fb4efa3 update: IP Database Copyright的IP占比信息用表格显示 2022-05-28 10:47:03 +08:00
sjlleo
876de6bde1 update: 完善描述 2022-05-28 10:26:31 +08:00
tsosunchia
7dbec0c7a1 update README.md 增加提示 2022-05-28 02:52:27 +08:00
tsosunchia
d690f680f5 增加一些平台支持 2022-05-28 02:29:18 +08:00
tsosunchia
e96686013d 增加一些平台支持 2022-05-28 02:07:45 +08:00
tsosunchia
6726b55fc9 Update .cross_compile.sh 2022-05-28 01:58:23 +08:00
tsosunchia
9f29c75491 增加一些平台支持 2022-05-28 01:51:30 +08:00
tsosunchia
2f5bf3f195 优化提示 2022-05-28 00:40:37 +08:00
tsosunchia
5981e82ee3 fix some bugs 2022-05-28 00:31:58 +08:00
tsosunchia
80f7857a65 Merge pull request #30 from tsosunchia/main
fix some bugs
2022-05-27 23:44:14 +08:00
tsosunchia
700d38de1c fix some bugs 2022-05-27 23:43:21 +08:00
tsosunchia
2dbf3f04a4 Merge pull request #29 from tsosunchia/main
fix some bugs
2022-05-27 23:10:46 +08:00
tsosunchia
45df06ea80 fix some bugs 2022-05-27 23:10:07 +08:00
tsosunchia
98953048ce fix some bugs 2022-05-27 22:54:07 +08:00
tsosunchia
eddd4226b0 Merge pull request #28 from tsosunchia/main
修补BUG
2022-05-27 22:45:55 +08:00
tsosunchia
5afd9eb09e Merge remote-tracking branch 'refs/remotes/origin/main' 2022-05-27 22:43:55 +08:00
tsosunchia
70006aaa13 优化逻辑结构 2022-05-27 22:43:28 +08:00
tsosunchia
497fb647c0 Merge pull request #27 from tsosunchia/main
优化逻辑结构
2022-05-27 22:31:44 +08:00
tsosunchia
be8552c3cd 优化逻辑结构 2022-05-27 22:30:54 +08:00
sjlleo
f320fd6202 update: 优化逻辑,废弃 realtime 参数 2022-05-27 21:27:26 +08:00
sjlleo
a42c5e3734 update: ttl 从 1 开始 2022-05-27 21:26:47 +08:00
sjlleo
e6480c84e0 Revert "update: 优化打印逻辑,废除 realtime 参数"
This reverts commit 126115c04e.
2022-05-27 21:14:16 +08:00
sjlleo
126115c04e update: 优化打印逻辑,废除 realtime 参数 2022-05-27 21:08:30 +08:00
tsosunchia
ea7fd2af0f Update quicklytest.sh 2022-05-27 19:55:54 +08:00
tsosunchia
3fc81f4e71 Merge pull request #26 from tsosunchia/main
修补之前再部分macOS设备出现的颜色显示问题:替换macOS中bash-3.1不支持的部分指令
2022-05-27 19:37:55 +08:00
tsosunchia
0c2b77bd81 Merge branch 'main' into main 2022-05-27 19:37:48 +08:00
tsosunchia
ac33c086c6 修补之前再部分macOS设备出现的颜色显示问题:替换macOS中bash-3.1不支持的部分指令 2022-05-27 19:34:35 +08:00
zhshch2002
fadfdc87d4 fix: nt_install.sh red color 2022-05-27 19:31:38 +08:00
tsosunchia
eb77a2b69b Merge pull request #25 from tsosunchia/main
替换macOS中bash-3.1不支持的部分指令
2022-05-27 19:14:44 +08:00
tsosunchia
02e6c6e1bf 替换macOS中bash-3.1不支持的部分指令 2022-05-27 19:13:05 +08:00
tsosunchia
838af3b7a1 Merge pull request #24 from tsosunchia/main
替换macOS下bash-3.1不兼容的部分指令 issues#21
2022-05-27 19:10:10 +08:00
tsosunchia
7cd16036a6 替换macOS中bash-3.1不支持的部分指令 2022-05-27 19:08:04 +08:00
tsosunchia
2ef4f61d7b Merge branch 'xgadget-lab:main' into main 2022-05-27 18:32:46 +08:00
tsosunchia
688622738f 整理排版 2022-05-27 18:32:23 +08:00
tsosunchia
83fe583f2a Merge pull request #23 from tsosunchia/main
fix some bugs
2022-05-27 18:30:49 +08:00
tsosunchia
4b32594c17 fix some bugs 2022-05-27 18:30:18 +08:00
tsosunchia
927b6d4035 Merge pull request #22 from tsosunchia/main
修正macOS下缺少md5sum导致的运行问题  issues#21
2022-05-27 18:16:59 +08:00
tsosunchia
aa651f30cc Merge branch 'xgadget-lab:main' into main 2022-05-27 18:15:38 +08:00
tsosunchia
ffec9a93cd update nt_install.sh 修正macOS下缺少md5sum导致的运行问题 issues#21 2022-05-27 18:15:10 +08:00
sjlleo
59a744b3b5 update: 修正文档里面有一个route-path错位的问题 2022-05-27 18:13:37 +08:00
sjlleo
9656dfe172 fix: 修复潜在数组越界的问题 2022-05-27 17:19:58 +08:00
sjlleo
84c48dae99 update: 完善一下 ipapicom 2022-05-27 17:18:31 +08:00
tsosunchia
4eaac372f6 Merge pull request #20 from tsosunchia/main
add ip-api.com API
2022-05-27 13:11:26 +08:00
tsosunchia
c92d8a5172 add ip-api.com API 2022-05-27 13:09:06 +08:00
tsosunchia
acab410d4c Update nt_install.sh 2022-05-27 11:14:31 +08:00
tsosunchia
858555fd86 Merge pull request #19 from tsosunchia/main
update nt_install.sh 修正在macOS下可能出现的问题
2022-05-27 11:12:14 +08:00
tsosunchia
31e419b199 update nt_install.sh 修正在macOS下可能出现的问题 2022-05-27 11:11:51 +08:00
zhshch2002
1dddd43e67 fix: 错误默认端口号造成无法TCP Trace 2022-05-27 10:38:17 +08:00
tsosunchia
4148d0d4b1 Merge pull request #18 from tsosunchia/main
修改部分提示
2022-05-27 10:37:03 +08:00
tsosunchia
4f7977da8f 修改部分提示 2022-05-27 10:36:34 +08:00
zhshch2002
cfc8034cb4 update: 允许参数后置 2022-05-27 10:26:32 +08:00
tsosunchia
dbc0f87847 Merge pull request #17 from tsosunchia/main
修改部分提示内容
2022-05-27 10:20:57 +08:00
tsosunchia
74a320898f Merge remote-tracking branch 'refs/remotes/origin/main' 2022-05-27 10:19:40 +08:00
tsosunchia
329b3fdd6b 修改部分提示内容 2022-05-27 10:19:25 +08:00
tsosunchia
3fb88f4cf4 Merge branch 'xgadget-lab:main' into main 2022-05-27 10:12:59 +08:00
tsosunchia
1de84cac71 修改部分提示内容 2022-05-27 10:12:14 +08:00
sjlleo
83d093f5aa fix: 修复一个 report 奔溃的问题 2022-05-27 10:08:28 +08:00
sjlleo
8b03ca7a38 update mod 2022-05-27 09:58:23 +08:00
tsosunchia
7a847bf0d5 Merge pull request #16 from tsosunchia/main
update README.md 增加说明
2022-05-27 09:43:28 +08:00
tsosunchia
11fe41611c update README.md 增加说明 2022-05-27 09:43:09 +08:00
tsosunchia
71b24fb7a0 Update README.md 2022-05-27 00:45:27 +08:00
tsosunchia
0b08e4b4a4 Merge pull request #15 from tsosunchia/main
update quicklytest.sh 增加部分模式下的Route-Path打印
2022-05-26 23:31:35 +08:00
tsosunchia
2608c05da1 Update quicklytest.sh 2022-05-26 23:24:03 +08:00
tsosunchia
314bdd0cce Update quicklytest.sh
启用-report
2022-05-26 23:07:14 +08:00
tsosunchia
ea958059c6 Merge branch 'main' into main 2022-05-26 23:02:49 +08:00
tsosunchia
b59c349264 Update README.md 2022-05-26 22:55:21 +08:00
tsosunchia
030a487526 Update README.md 2022-05-26 22:45:48 +08:00
tsosunchia
cac6d33fde Update quicklytest.sh 2022-05-26 22:38:14 +08:00
tsosunchia
1725a65827 Update nt_install.sh 2022-05-26 22:38:01 +08:00
tsosunchia
4d886066a3 Update quicklytest.sh 2022-05-26 22:35:25 +08:00
tsosunchia
156043730d Update nt_install.sh 2022-05-26 22:17:40 +08:00
tsosunchia
91ad3bc539 Update nt_install.sh 2022-05-26 22:03:01 +08:00
tsosunchia
351da5f5a3 Update nt_install.sh 2022-05-26 21:57:42 +08:00
tsosunchia
f8fc90d7a5 Update quicklytest.sh 2022-05-26 21:50:15 +08:00
tsosunchia
9c75635acc Update nt_install.sh 2022-05-26 21:31:14 +08:00
sjlleo
b20b27fd20 update: 现在TCP SYN模式下也将打印路由跟踪结果 2022-05-26 21:29:17 +08:00
tsosunchia
cfc1dfdfe5 Update nt_install.sh
增加检查脚本更新功能
2022-05-26 21:28:12 +08:00
tsosunchia
97c4387af4 Update quicklytest.sh 2022-05-26 21:25:17 +08:00
tsosunchia
37b5202126 Update README.md 2022-05-26 21:08:39 +08:00
tsosunchia
afb6a3e1df Update quicklytest.sh
增加自动检测更新功能
2022-05-26 21:02:19 +08:00
tsosunchia
c9a3916cd0 Update quicklytest.sh 2022-05-26 20:58:05 +08:00
tsosunchia
89d56c437e Update quicklytest.sh 2022-05-26 20:43:06 +08:00
tsosunchia
6299dcd9a3 Update quicklytest.sh 2022-05-26 20:40:06 +08:00
tsosunchia
82f28a13f3 Update quicklytest.sh 2022-05-26 20:39:26 +08:00
tsosunchia
af732bc212 Update quicklytest.sh
增加脚本提示
2022-05-26 19:55:58 +08:00
tsosunchia
8d5f58bf15 Update quicklytest.sh 2022-05-26 19:46:54 +08:00
tsosunchia
8bd5654474 Update quicklytest.sh
增加TCP,UDP模式选项
2022-05-26 19:41:57 +08:00
tsosunchia
4de61823ee Update nt_install.sh
整理排版
2022-05-26 17:36:44 +08:00
tsosunchia
39ec016d0d Update nt_install.sh
重构结构
2022-05-26 17:30:09 +08:00
tsosunchia
67999411af fix some bugs 2022-05-25 23:52:14 +08:00
tsosunchia
7cc6b71727 fix some bugs 2022-05-25 23:40:13 +08:00
tsosunchia
16ba835537 Merge pull request #14 from tsosunchia/main
update quicklytest.sh some bugs fix
2022-05-25 18:50:09 +08:00
tsosunchia
1b7c3b8d0d update quicklytest.sh some bugs fix 2022-05-25 18:49:43 +08:00
tsosunchia
bd47935a2d Merge pull request #13 from tsosunchia/main
增删一些测试节点
2022-05-25 18:35:05 +08:00
tsosunchia
1f16001e4f 增删一些测试节点 2022-05-25 18:34:29 +08:00
sjlleo
f56e6cdba3 update: 整理排版 2022-05-25 18:15:26 +08:00
tsosunchia
ecd3df8ee8 Update quicklytest.sh
替换部分已不可使用的测试节点
2022-05-25 18:11:19 +08:00
zhshch2002
1658da1653 update: README.md img tag alt 2022-05-25 18:05:04 +08:00
zhshch2002
5110c9b990 fix: README.md typo 2022-05-25 18:04:13 +08:00
zhshch2002
aa446574f1 update: README.md screenshot.png 2022-05-25 18:02:47 +08:00
tsosunchia
2016990629 Update README.md 2022-05-25 17:50:17 +08:00
tsosunchia
e639b7b12d Merge pull request #11 from tsosunchia/main
update README.md 增加对quicklytest.sh的说明
2022-05-25 17:46:23 +08:00
tsosunchia
3cfe6598dd update README.md 增加对quicklytest.sh的说明 2022-05-25 17:45:56 +08:00
tsosunchia
59193cae47 Merge pull request #10 from tsosunchia/main
Some bugs fix
2022-05-25 17:30:40 +08:00
tsosunchia
1def15e805 some bugs fix 2022-05-25 17:30:13 +08:00
tsosunchia
1950032371 Merge branch 'xgadget-lab:main' into main 2022-05-25 17:25:58 +08:00
sjlleo
f81a0b3da3 update: 当 ip.sb 触发 cloudflare 5s 墙的时候 自动退出 2022-05-25 17:25:26 +08:00
tsosunchia
9e3d4186a1 Merge pull request #1 from xgadget-lab/main
add quicklytest.sh
2022-05-25 17:24:50 +08:00
tsosunchia
4737669436 add quicklytest.sh 修改自https://github.com/KANIKIG/worst_testrace 一个快速的脚本测试你的服务器到中国的路由 2022-05-25 17:22:40 +08:00
sjlleo
dbecfd880d update: 风控IP会直接退出,避免没有数据 2022-05-25 17:19:54 +08:00
tsosunchia
a67a4bc559 Update nt_install.sh 2022-05-25 17:08:56 +08:00
tsosunchia
077d72d5cd Update nt_install.sh 2022-05-25 17:03:35 +08:00
zhshch2002
d45b5eb032 update: 减少GitHub Actions重复运行 2022-05-25 16:56:13 +08:00
zhshch2002
5fe1110ab3 update: 减少GitHub Actions重复运行 2022-05-25 16:52:26 +08:00
tsosunchia
812c953976 Delete bug_cn.md 2022-05-25 16:08:42 +08:00
tsosunchia
f89505ab87 Update issue templates 2022-05-25 16:08:00 +08:00
tsosunchia
640eb8c02d Create bug_cn.md 2022-05-25 15:57:28 +08:00
tsosunchia
fc3462ff9e Merge pull request #9 from tsosunchia/main
update README.md 更改安装方法说明
2022-05-25 15:33:57 +08:00
tsosunchia
071a6b124a update README.md 更改安装方法说明 2022-05-25 15:33:13 +08:00
tsosunchia
45a8cf21f6 Merge pull request #8 from tsosunchia/main
add 添加定时更新任务功能
2022-05-25 15:18:53 +08:00
tsosunchia
1315efa4d2 Merge branch 'xgadget-lab:main' into main 2022-05-25 15:16:22 +08:00
tsosunchia
c2bd51faab add 自动添加定时更新任务功能 2022-05-25 15:16:02 +08:00
sjlleo
f1ce2bbb77 update: 为什么我们要尝试自己维护骨干网的IP数据库 2022-05-25 14:43:02 +08:00
sjlleo
a18bf1889b add: faq 2022-05-25 14:16:38 +08:00
tsosunchia
12c93de8c5 Merge pull request #6 from tsosunchia/main
Implement update function
2022-05-25 14:04:09 +08:00
tsosunchia
8280b62881 Merge remote-tracking branch 'refs/remotes/origin/main' 2022-05-25 14:02:40 +08:00
tsosunchia
608847b1cb Implement update function 2022-05-25 14:01:21 +08:00
tsosunchia
b4838ba402 Merge pull request #5 from tsosunchia/main
添加macOS BREW包管理器
2022-05-25 13:38:06 +08:00
tsosunchia
fbd70a8eb1 add BREW PACKAGE MANAGER 2022-05-25 13:36:54 +08:00
tsosunchia
fd1632fccb Merge branch 'xgadget-lab:main' into main 2022-05-25 13:18:06 +08:00
zhshch2002
4a725d2c48 revert: 96bb323f "update: test.yml" 2022-05-25 13:15:06 +08:00
zhshch2002
96bb323f72 update: test.yml 2022-05-25 13:09:30 +08:00
zhshch2002
961c29e499 fix: build sh version var 2022-05-25 13:04:18 +08:00
zhshch2002
870d1f3b5a update: get version from git 2022-05-25 12:56:47 +08:00
sjlleo
ebd435db53 refactor: report 支持多线程和rDNS反查 2022-05-25 10:48:47 +08:00
sjlleo
53b2249ce5 fix: 尝试性修复部分 CentOS 6、Debian8 下 wget 安装失败 2022-05-25 08:13:57 +08:00
sjlleo
7215a1e2b7 update: 更新 NextTrace 最新的 CLI 参数 2022-05-24 21:33:18 +08:00
sjlleo
24b06d2fd7 fix: strange error 2022-05-24 21:10:28 +08:00
sjlleo
f1f95dff29 fix: route-path 显示不全的问题 2022-05-24 21:05:59 +08:00
zhshch2002
0d9b8c8861 fix: typo 2022-05-24 18:27:22 +08:00
zhshch2002
290524b502 add: Version print 2022-05-24 18:14:31 +08:00
sjlleo
905ef267f2 improve 2022-05-24 11:57:50 +08:00
sjlleo
9720c19153 add: route report 2022-05-24 11:57:10 +08:00
sjlleo
f2c494441b Add files via upload 2022-05-24 11:45:02 +08:00
sjlleo
44aba64505 Delete screenshot2.png 2022-05-24 11:44:30 +08:00
sjlleo
c0be6774c1 Delete screenshot3.png 2022-05-24 11:44:19 +08:00
zhshch2002
23693895e4 update: GitHub actions build.yml 2022-05-24 11:22:13 +08:00
zhshch2002
7edebf938b remove: test for TestIPSB api 2022-05-24 11:20:23 +08:00
zhshch2002
d4a176f864 add: test github actions 2022-05-24 11:17:43 +08:00
zhshch2002
69388c956e remove: listener_channe, signal, taskgroup 2022-05-24 11:17:43 +08:00
sjlleo
738ff949b1 Special Version for my friends - missuo 2022-05-24 10:59:38 +08:00
sjlleo
b59f0eb9da update: rdns 功能介绍 2022-05-24 09:21:30 +08:00
tsosunchia
24eedfa3fe Update nt_install.sh 2022-05-23 23:24:42 +08:00
41 changed files with 1344 additions and 513 deletions

View File

@@ -5,7 +5,11 @@ set -e
DIST_PREFIX="nexttrace"
DEBUG_MODE=${2}
TARGET_DIR="dist"
PLATFORMS="darwin/amd64 darwin/arm64 linux/amd64 linux/arm64 linux/mips"
PLATFORMS="darwin/amd64 darwin/arm64 linux/386 linux/amd64 linux/arm64 linux/mips openbsd/amd64 openbsd/arm64 freebsd/amd64 freebsd/arm64"
BUILD_VERSION="$(git describe --tags --always)"
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
COMMIT_SHA1="$(git rev-parse --short HEAD)"
rm -rf ${TARGET_DIR}
mkdir ${TARGET_DIR}
@@ -21,16 +25,36 @@ for pl in ${PLATFORMS}; do
echo "build => ${TARGET}"
if [ "${DEBUG_MODE}" == "debug" ]; then
go build -trimpath -gcflags "all=-N -l" -o ${TARGET} \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${COMMIT_SHA1}'\
-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}'\
-w -s"
else
go build -trimpath -o ${TARGET} \
-ldflags "-X 'main.version=${BUILD_VERSION}' \
-X 'main.buildDate=${BUILD_DATE}' \
-X 'main.commitID=${COMMIT_SHA1}'\
-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}'\
-w -s"
fi
done
export GOOS='linux'
export GOARCH='arm'
export GOARM='7'
export TARGET=${TARGET_DIR}/${DIST_PREFIX}_${GOOS}_${GOARCH}v7
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}'\
-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}'\
-w -s"
fi

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
---
name: nexttrace 程序问题
about: "提交一个 nexttrace 的程序问题报告。"
copyright: [v2fly](https://github.com/v2fly)
---
<!--
除非特殊情况,请完整填写所有问题。不按模板发的 issue 将直接被关闭。
如果你遇到的问题不是 nexttrace 的 bug比如你不清楚如何配置请在 https://github.com/xgadget-lab/nexttrace/discussions 进行讨论。
-->
## 你正在使用哪个版本的 nexttrace
<!-- 比如linux_amd64 macOS_arm64 -->
## 你看到的异常现象是什么?
<!-- 请描述具体现象 -->
## 你期待看到的正常表现是怎样的?
## 请附上你的命令
<!-- 提交 issue 前,请隐去您的隐私信息 -->
## 请附上出错时软件输出的错误信息

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1,17 +1,31 @@
on:
push: # 每次带有 tag 的 push 候触发
tags:
- 'v*'
push:
pull_request:
name: Build Release
name: Test & Build Release
jobs:
release:
Test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master # checkout 代码
- uses: actions/setup-go@v2 # 配置 Go 环境
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
with:
go-version: "1.18" # 改成自己的版本
go-version: "1.18"
- name: Test
run: go test -v -coverprofile='coverage.out' -covermode=count ./...
Build:
needs: test
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
with:
go-version: "1.18"
- run: bash .cross_compile.sh
@@ -22,8 +36,14 @@ jobs:
files: |
dist/nexttrace_darwin_amd64
dist/nexttrace_darwin_arm64
dist/nexttrace_linux_386
dist/nexttrace_linux_amd64
dist/nexttrace_linux_arm64
dist/nexttrace_linux_armv7
dist/nexttrace_linux_mips
dist/nexttrace_openbsd_amd64
dist/nexttrace_openbsd_arm64
dist/nexttrace_freebsd_amd64
dist/nexttrace_freebsd_arm64
env:
GITHUB_TOKEN: ${{ secrets.GT_Token }}

141
README.md
View File

@@ -1,32 +1,39 @@
<div align="center">
<img src="asset/logo.png" height="200px"/>
<img src="asset/logo.png" height="200px" alt="NextTrace Logo"/>
</div>
# NextTrace
一款开源的可视化路由跟踪工具使用Golang开发。
一款开源的可视化路由跟踪工具,使用 Golang 开发。
## How To Use
### Install
### Automated Install
```bash
bash -c "$(curl -Ls https://raw.githubusercontent.com/xgadget-lab/nexttrace/main/nt_install.sh)"
# Linux 一键安装脚本
bash <(curl -Ls https://raw.githubusercontent.com/xgadget-lab/nexttrace/main/nt_install.sh)
# GHPROXY 镜像(国内使用)
bash <(curl -Ls https://ghproxy.com/https://raw.githubusercontent.com/xgadget-lab/nexttrace/main/nt_install.sh)
# macOS brew 安装命令
brew tap xgadget-lab/nexttrace && brew install nexttrace
```
- `Release`里面为很多系统以及不同架构提供了编译好的二进制可执行文件,如果没有可以自行编译。
- 一些本项目的必要依赖在`Windows``Golang`底层实现不完全,所以目前`NextTrace``Windows`平台不可用。
### Get Started
`NextTrace`默认使用`icmp`协议发起`TraceRoute`请求,该协议同时支持`IPv4``IPv6`
`NextTrace`默认使用`ICMP`协议发起`TraceRoute`请求,该协议同时支持`IPv4``IPv6`
```bash
# IPv4 ICMP Trace
nexttrace 1.0.0.1
# 获得 route-path
nexttrace -report 1.0.0.1
# 表格打印一次性输出全部跳数需等待20-40秒
nexttrace -table 1.0.0.1
@@ -35,6 +42,7 @@ nexttrace 2606:4700:4700::1111
```
`NextTrace`也可以使用`TCP``UDP`协议发起`Traceroute`请求,不过目前只支持`IPv4`
```bash
# TCP SYN Trace
nexttrace -T www.bing.com
@@ -48,24 +56,68 @@ nexttrace -U 1.0.0.1
nexttrace -U -p 53 1.0.0.1
```
### IP数据库
`NextTrace`也同样支持一些进阶功能,如 IP 反向解析、并发数控制、模式切换等
目前使用的IP数据库默认为我们自己搭建的API服务如果后期遇到滥用我们可能会选择关闭。
```bash
# 每一跳发送2个探测包
nexttrace -q 2 www.hkix.net
我们也会在后期开放服务端源代码您也可以根据该项目的源码自行搭建属于您的API服务器。
# 无并发,每次只发送一个探测包
nexttrace -r 1 www.hkix.net
NextTrace所有的的IP地理位置`API DEMO`可以参考[这里](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
# 打开IP反向解析功能在IPv6的骨干网定位辅助有较大帮助
nexttrace -rdns www.bbix.net
### 全部用法详见Usage菜单
# 特色功能打印Route-Path图
# Route-Path图示例
# AS6453 塔塔通信「Singapore『Singapore』」
# ╭╯
# ╰AS9299 Philippine Long Distance Telephone Co.「Philippines『Metro Manila』」
# ╭╯
# ╰AS36776 Five9 Inc.「Philippines『Metro Manila』」
# ╭╯
# ╰AS37963 阿里云「ALIDNS.COM『ALIDNS.COM』」
nexttrace -report www.time.com.my
```
`NextTrace`支持用户自主选择 IP 数据库(目前支持:`LeoMoeAPI`, `IP.SB`, `IPInfo`, `IPInsight`, `IPAPI.com`
```bash
# 可以自行指定IP数据库[此处为IP.SB]不指定则默认为LeoMoeAPI
nexttrace -d IP.SB
## 特别的:其中 ipinfo API 需要从ipinfo自行购买服务如有需要可以clone本项目添加其提供的token自行编译
## TOKEN填写路径ipgeo/tokens.go
## 另外由于IP.SB被滥用比较严重会经常出现无法查询的问题请知悉。
## IPAPI.com限制调用较为严格如有查询不到的情况请几分钟后再试。
```
`NextTrace`支持参数混合使用
```bash
Example:
nexttrace -d IPInsight -m 20 -p 443 -q 5 -r 20 -rdns 1.1.1.1
nexttrace -T -q 2 -r 1 -rdns -table -report 2001:4860:4860::8888
```
### IP 数据库
目前使用的 IP 数据库默认为我们自己搭建的 API 服务,如果后期遇到滥用,我们可能会选择关闭。
我们也会在后期开放服务端源代码,您也可以根据该项目的源码自行搭建属于您的 API 服务器。
NextTrace 所有的的 IP 地理位置`API DEMO`可以参考[这里](https://github.com/xgadget-lab/nexttrace/blob/main/ipgeo/)
### 全部用法详见 Usage 菜单
```shell
Usage of nexttrace:
'nexttrace [options] <hostname>' or 'nexttrace <hostname> [option...]'
Options:
-T Use TCP SYN for tracerouting (default port is 80)
-U Use UDP Package for tracerouting (default port is 53 in UDP)
-V Check Version
-d string
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight] (default "LeoMoeAPI")
-displayMode string
Choose The Display Mode [table, classic] (default "table")
Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com] (default "LeoMoeAPI")
-m int
Set the max number of hops (max TTL to be reached). (default 30)
-p int
@@ -76,51 +128,76 @@ Usage of nexttrace:
Set ParallelRequests number. It should be 1 when there is a multi-routing. (default 18)
-rdns
Set whether rDNS will be display
-table
Output trace results as table
-report
Route Path
```
## 项目截图
![](asset/screenshot2.png)
<div align="center">
![](asset/screenshot3.png)
<img src=asset/screenshot.png alt="NextTrace Screenshot" height="688" />
![](asset/screenshot.png)
</div>
## FAQ 常见问题
如果你在安装或者使用的时候遇到了问题,我们建议你不要把新建一个 `issue` 作为首选项
以下是我们推荐的排错流程:
1. 查看是否为常见问题 -> [前往 Github Wiki](https://github.com/xgadget-lab/nexttrace/wiki/FAQ---%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%A7%A3%E7%AD%94)
2. 不会软件的参数使用 -> [前往 Github Discussions](https://github.com/xgadget-lab/nexttrace/discussions)
3. 疑似 BUG、或者功能建议 -> [前往 Github Issues](https://github.com/xgadget-lab/nexttrace/issues)
## Thanks
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
[Sam Sam](https://github.com/samleong123) (samsam123@samsam123.name.my)
[Vincent Young](https://github.com/missuo) (i@yyt.moe)
[tsosunchia](https://github.com/tsosunchia)
[waiting4new](https://github.com/waiting4new)
FFEE_CO
nsnnns
[FFEE_CO](https://github.com/fkx4-p)
## IP Database Copyright
### IPv4 Database
#### China MainLand
#### China
* 项目组自行维护 ~ 御三家骨干网数据 ~ 5%
* 埃文科技 Paid Database ~ 95%
| ISP | 类型 | 数据源 | 占比 |
| :------------: | :----: | :-------: | :--: |
| 电信/联通/移动 | 骨干网 | NextTrace | 10% |
| 电信/联通/移动 | 城域网 | 埃文科技 | 90% |
#### WorldWide
* 埃文科技 Paid Database ~ 15%
| ISP | 类型 | 数据源 | 占比 |
| :-----: | :----: | :-------: | :--: |
| Tier-01 | 骨干网 | IPInfo | 2% |
| Tier-01 | 骨干网 | 埃文科技 | 3% |
| Tier-01 | 骨干网 | IPInSight | 5% |
| Tier-01 | 城域网 | IPInSight | 90% |
* IpInfo Free ~ 15%
* IPInSight Free ~ 70%
| ISP | 类型 | 数据源 | 占比 |
| :----: | :----: | :-------: | :--: |
| Others | 骨干网 | IPInSight | 5% |
| Others | 城域网 | IPInSight | 95% |
### IPv6 Database
| ISP | 类型 | 数据源 | 占比 |
| :-: | :--: | :--------------: | :--: |
| All | 全部 | IP2Location Lite | 100% |
This product includes IP2Location LITE data available from <a href="https://lite.ip2location.com">https://lite.ip2location.com</a>.
### Others
其他第三方API尽管集成在本项目内但是具体的TOS以及AUP请详见第三方API官网。如遇到IP数据错误也请直接联系他们纠错。
其他第三方 API 尽管集成在本项目内,但是具体的 TOS 以及 AUP请详见第三方 API 官网。如遇到 IP 数据错误,也请直接联系他们纠错。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 866 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

BIN
asset/screenshot_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

35
config/config.go Normal file
View File

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

18
config/config_test.go Normal file
View File

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

160
config/generate_config.go Normal file
View File

@@ -0,0 +1,160 @@
package config
import (
"fmt"
"io/ioutil"
"os"
"gopkg.in/yaml.v2"
)
func pathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func writeFile(content []byte) error {
var err error
var path string
path, err = configFromUserHomeDir()
if err != nil {
path, err = configFromRunDir()
if err != nil {
return err
}
}
if exist, _ := pathExists(path); !exist {
err := os.Mkdir(path, os.ModePerm)
if err != nil {
return err
}
}
if err = ioutil.WriteFile(path+"ntraceConfig.yml", []byte(content), 0644); err != nil {
return err
}
return nil
}
func AutoGenerate() (*tracerConfig, error) {
token := Token{
LeoMoeAPI: "NextTraceDemo",
IPInfo: "",
}
preference := Preference{
AlwaysRoutePath: false,
TablePrintDefault: false,
DataOrigin: "LEOMOEAPI",
}
finalConfig := tracerConfig{
Token: token,
Preference: preference,
}
yamlData, err := yaml.Marshal(&finalConfig)
if err != nil {
return nil, err
}
if err = writeFile(yamlData); err != nil {
return nil, err
} else {
return &finalConfig, nil
}
}
func Generate() (*tracerConfig, error) {
var leotoken string
var iPInfoToken string
var tmpInput string
fmt.Println("欢迎使用高阶自定义功能,这是一个配置向导,我们会帮助您生成配置文件。您的配置文件会被放在 ~/.nexttrace/ntraceConfig.yml 中,您也可以通过编辑这个文件来自定义配置。")
fmt.Println("请输入您的LeoMoeAPI Token您可以回车以便继续使用公共Token")
fmt.Scanln(&leotoken)
if leotoken == "" {
fmt.Println("检测到您的输入为空您将使用公共Token。")
leotoken = "NextTraceDemo"
}
fmt.Println("请输入您的IPInfo Token如果您不需要使用IPInfo可以直接回车")
fmt.Scanln(&iPInfoToken)
token := Token{
LeoMoeAPI: leotoken,
IPInfo: iPInfoToken,
}
var preference Preference
var AlwaysRoutePath bool
var tablePrintDefault bool
var dataOrigin string
fmt.Print("我希望默认在路由跟踪完毕后不绘制Route-Path图 (y/n) [y]")
fmt.Scanln(&tmpInput)
if tmpInput == "n" || tmpInput == "N" || tmpInput == "no" || tmpInput == "No" || tmpInput == "NO" {
AlwaysRoutePath = true
} else {
AlwaysRoutePath = false
}
fmt.Print("我希望路由跟踪默认实时显示,而不使用制表模式 (y/n) [y]")
fmt.Scanln(&tmpInput)
if tmpInput == "n" || tmpInput == "N" || tmpInput == "no" || tmpInput == "No" || tmpInput == "NO" {
tablePrintDefault = true
} else {
tablePrintDefault = false
}
fmt.Println("请选择默认的IP地理位置API数据源\n1. LeoMoe\n2. IPInfo\n3. IPInsight\n4. IP.SB\n5. IP-API.COM")
fmt.Print("请输入您的选择:")
fmt.Scanln(&tmpInput)
switch tmpInput {
case "1":
dataOrigin = "LEOMOEAPI"
case "2":
dataOrigin = "IPINFO"
case "3":
dataOrigin = "IPINSIGHT"
case "4":
dataOrigin = "IP.SB"
case "5":
dataOrigin = "IPAPI.COM"
default:
dataOrigin = "LEOMOEAPI"
}
preference = Preference{
AlwaysRoutePath: AlwaysRoutePath,
TablePrintDefault: tablePrintDefault,
DataOrigin: dataOrigin,
}
finalConfig := tracerConfig{
Token: token,
Preference: preference,
}
yamlData, err := yaml.Marshal(&finalConfig)
if err != nil {
return nil, err
}
if err = writeFile(yamlData); err != nil {
return nil, err
} else {
fmt.Println("配置文件已经更新,在下次路由跟踪时,将会使用您的偏好。")
return &finalConfig, nil
}
}

47
config/read_config.go Normal file
View File

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

111
fast_trace/basic.go Normal file
View File

@@ -0,0 +1,111 @@
package fastTrace
type AllLocationCollection struct {
Beijing BackBoneCollection
Shanghai BackBoneCollection
Guangzhou BackBoneCollection
}
type BackBoneCollection struct {
Location string
CT163 ISPCollection
CTCN2 ISPCollection
CU169 ISPCollection
CU9929 ISPCollection
CM ISPCollection
EDU ISPCollection
}
type ISPCollection struct {
ISPName string
IP string
}
const (
CT163 string = "电信 163 AS4134"
CTCN2 string = "电信 CN2 AS4809"
CU169 string = "联通 169 AS4837"
CU9929 string = "联通 A网 AS9929"
CM string = "移动 骨干网 AS9808"
EDU string = "教育网 CERNET AS4538"
)
var TestIPsCollection = AllLocationCollection{
Beijing: Beijing,
Shanghai: Shanghai,
Guangzhou: Guangzhou,
}
var Beijing = BackBoneCollection{
Location: "北京",
CT163: ISPCollection{
ISPName: CT163,
IP: "106.37.67.1",
},
CU169: ISPCollection{
ISPName: CU169,
IP: "123.125.96.156",
},
CM: ISPCollection{
ISPName: CM,
IP: "211.136.25.153",
},
EDU: ISPCollection{
ISPName: EDU,
IP: "101.6.15.130",
},
}
var Shanghai = BackBoneCollection{
Location: "上海",
CT163: ISPCollection{
ISPName: CT163,
IP: "101.226.28.198",
},
CTCN2: ISPCollection{
ISPName: CTCN2,
IP: "58.32.4.1",
},
CU169: ISPCollection{
ISPName: CU169,
IP: "139.226.206.150",
},
CU9929: ISPCollection{
ISPName: CU9929,
IP: "210.13.86.1",
},
CM: ISPCollection{
ISPName: CM,
IP: "120.204.34.85",
},
EDU: ISPCollection{
ISPName: EDU,
IP: "202.120.58.155",
},
}
var Guangzhou = BackBoneCollection{
Location: "广州",
CT163: ISPCollection{
ISPName: CT163,
IP: "106.37.67.1",
},
CU169: ISPCollection{
ISPName: CU169,
IP: "123.125.96.156",
},
CM: ISPCollection{
ISPName: CM,
IP: "120.198.26.254",
},
}

136
fast_trace/fast_trace.go Normal file
View File

@@ -0,0 +1,136 @@
package fastTrace
import (
"fmt"
"log"
"net"
"time"
"github.com/xgadget-lab/nexttrace/config"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/printer"
"github.com/xgadget-lab/nexttrace/reporter"
"github.com/xgadget-lab/nexttrace/trace"
)
type FastTracer struct {
Preference config.Preference
TracerouteMethod trace.Method
}
func (f *FastTracer) tracert(location string, ispCollection ISPCollection) {
fmt.Printf("『%s %s 』\n", location, ispCollection.ISPName)
fmt.Printf("traceroute to %s, 30 hops max, 32 byte packets\n", ispCollection.IP)
ip := net.ParseIP(ispCollection.IP)
var conf = trace.Config{
DestIP: ip,
DestPort: 80,
MaxHops: 30,
NumMeasurements: 3,
ParallelRequests: 18,
RDns: !f.Preference.NoRDNS,
IPGeoSource: ipgeo.GetSource(f.Preference.DataOrigin),
Timeout: 1 * time.Second,
}
if f.TracerouteMethod == trace.ICMPTrace {
conf.RealtimePrinter = printer.RealtimePrinter
}
res, err := trace.Traceroute(f.TracerouteMethod, conf)
if err != nil {
log.Fatal(err)
}
if f.TracerouteMethod == trace.TCPTrace {
printer.TracerouteTablePrinter(res)
}
if f.Preference.AlwaysRoutePath {
r := reporter.New(res, ip.String())
r.Print()
}
}
func initialize() *FastTracer {
configData, err := config.Read()
// Initialize Default Config
if err != nil || configData.DataOrigin == "" {
if configData, err = config.AutoGenerate(); err != nil {
log.Fatal(err)
}
}
// Set Token from Config
ipgeo.SetToken(configData.Token)
return &FastTracer{
Preference: configData.Preference,
}
}
func (f *FastTracer) testAll() {
f.testCT()
f.testCU()
f.testCM()
f.testEDU()
}
func (f *FastTracer) testCT() {
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CT163)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CT163)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CTCN2)
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CT163)
}
func (f *FastTracer) testCU() {
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CU169)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CU169)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CU9929)
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CU169)
}
func (f *FastTracer) testCM() {
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.CM)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.CM)
f.tracert(TestIPsCollection.Guangzhou.Location, TestIPsCollection.Guangzhou.CM)
}
func (f *FastTracer) testEDU() {
f.tracert(TestIPsCollection.Beijing.Location, TestIPsCollection.Beijing.EDU)
f.tracert(TestIPsCollection.Shanghai.Location, TestIPsCollection.Shanghai.EDU)
}
func FastTest(tm bool) {
var c string
fmt.Println("您想测试哪些ISP的路由\n1. 国内四网\n2. 电信\n3. 联通\n4. 移动\n5. 教育网")
fmt.Print("请选择选项:")
fmt.Scanln(&c)
ft := initialize()
if !tm {
ft.TracerouteMethod = trace.ICMPTrace
fmt.Println("您将默认使用ICMP协议进行路由跟踪如果您想使用TCP SYN进行路由跟踪可以加入 -T 参数")
} else {
ft.TracerouteMethod = trace.TCPTrace
}
switch c {
case "1":
ft.testAll()
case "2":
ft.testCT()
case "3":
ft.testCU()
case "4":
ft.testCM()
case "5":
ft.testEDU()
default:
ft.testAll()
}
}

2
go.mod
View File

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

6
go.sum
View File

@@ -1,4 +1,3 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
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=
@@ -13,8 +12,6 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
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/rodaine/table v1.0.1 h1:U/VwCnUxlVYxw8+NJiLIuCxA/xa6jL38MY3FYysVWWQ=
@@ -52,7 +49,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

43
ipgeo/ipapicom.go Normal file
View File

@@ -0,0 +1,43 @@
package ipgeo
import (
"errors"
"io/ioutil"
"log"
"net/http"
"regexp"
"time"
"github.com/tidwall/gjson"
)
func IPApiCom(ip string) (*IPGeoData, error) {
url := "http://ip-api.com/json/" + ip + "?fields=status,message,country,regionName,city,isp,as"
client := &http.Client{
// 2 秒超时
Timeout: 2 * time.Second,
}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0")
content, err := client.Do(req)
if err != nil {
log.Println("ip-api.com 请求超时(2s)请切换其他API使用")
return nil, err
}
body, _ := ioutil.ReadAll(content.Body)
res := gjson.ParseBytes(body)
if res.Get("status").String() != "success" {
return &IPGeoData{}, errors.New("超过API阈值")
}
re := regexp.MustCompile("[0-9]+")
return &IPGeoData{
Asnumber: re.FindString(res.Get("as").String()),
Country: res.Get("country").String(),
City: res.Get("city").String(),
Prov: res.Get("regionName").String(),
Isp: res.Get("isp").String(),
}, nil
}

View File

@@ -1,6 +1,8 @@
package ipgeo
import "strings"
import (
"strings"
)
type IPGeoData struct {
Asnumber string
@@ -22,7 +24,11 @@ func GetSource(s string) Source {
return IPSB
case "IPINSIGHT":
return IPInSight
case "IPAPI.COM":
return IPApiCom
case "IPINFO":
return IPInfo
default:
return nil
return LeoIP
}
}

View File

@@ -15,11 +15,12 @@ func TestLeoIP(t *testing.T) {
}
func TestIPSB(t *testing.T) {
res, err := IPSB("1.1.1.1")
assert.Nil(t, err)
assert.NotNil(t, res)
assert.NotEmpty(t, res.Asnumber)
assert.NotEmpty(t, res.Isp)
// Not available
//res, err := IPSB("1.1.1.1")
//assert.Nil(t, err)
//assert.NotNil(t, res)
//assert.NotEmpty(t, res.Asnumber)
//assert.NotEmpty(t, res.Isp)
}
func TestIPInfo(t *testing.T) {
@@ -40,3 +41,12 @@ func TestIPInSight(t *testing.T) {
// 这个库有时候不提供城市信息,返回值为""
//assert.NotEmpty(t, res.City)
}
func TestIPApiCom(t *testing.T) {
res, err := IPApiCom("1.1.1.1")
assert.Nil(t, err)
assert.NotNil(t, res)
assert.NotEmpty(t, res.Country)
assert.NotEmpty(t, res.City)
assert.NotEmpty(t, res.Prov)
}

View File

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

View File

@@ -2,7 +2,9 @@ package ipgeo
import (
"io/ioutil"
"log"
"net/http"
"os"
"time"
"github.com/tidwall/gjson"
@@ -11,7 +13,7 @@ import (
func IPSB(ip string) (*IPGeoData, error) {
url := "https://api.ip.sb/geoip/" + ip
client := &http.Client{
// 2秒超时
// 2 秒超时
Timeout: 2 * time.Second,
}
req, _ := http.NewRequest("GET", url, nil)
@@ -19,11 +21,17 @@ func IPSB(ip string) (*IPGeoData, error) {
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0")
content, err := client.Do(req)
if err != nil {
log.Println("api.ip.sb 请求超时(2s)请切换其他API使用")
return nil, err
}
body, _ := ioutil.ReadAll(content.Body)
res := gjson.ParseBytes(body)
if res.Get("country").String() == "" {
// 什么都拿不到证明被Cloudflare风控了
os.Exit(1)
}
return &IPGeoData{
Asnumber: res.Get("asn").String(),
Country: res.Get("country").String(),

View File

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

View File

@@ -1,61 +0,0 @@
package listener_channel
import (
"golang.org/x/net/context"
"net"
"time"
)
type ReceivedMessage struct {
N *int
Peer net.Addr
Msg []byte
Err error
}
type ListenerChannel struct {
ctx context.Context
cancel context.CancelFunc
Conn net.PacketConn
Messages chan ReceivedMessage
}
func New(conn net.PacketConn) *ListenerChannel {
ctx, cancel := context.WithCancel(context.Background())
results := make(chan ReceivedMessage, 50)
return &ListenerChannel{Conn: conn, ctx: ctx, cancel: cancel, Messages: results}
}
func (l *ListenerChannel) Start() {
for {
select {
case <-l.ctx.Done():
return
default:
}
reply := make([]byte, 1500)
err := l.Conn.SetReadDeadline(time.Now().Add(2 * time.Second))
if err != nil {
l.Messages <- ReceivedMessage{Err: err}
continue
}
n, peer, err := l.Conn.ReadFrom(reply)
if err != nil {
l.Messages <- ReceivedMessage{Err: err}
continue
}
l.Messages <- ReceivedMessage{
N: &n,
Peer: peer,
Err: nil,
Msg: reply,
}
}
}
func (l *ListenerChannel) Stop() {
l.cancel()
}

133
main.go
View File

@@ -4,9 +4,13 @@ import (
"flag"
"fmt"
"log"
"net"
"os"
"strings"
"time"
"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"
@@ -14,35 +18,103 @@ import (
"github.com/xgadget-lab/nexttrace/util"
)
var tcpSYNFlag = flag.Bool("T", false, "Use TCP SYN for tracerouting (default port is 80)")
var udpPackageFlag = flag.Bool("U", false, "Use UDP Package for tracerouting (default port is 53 in UDP)")
var port = flag.Int("p", 80, "Set SYN Traceroute Port")
var numMeasurements = flag.Int("q", 3, "Set the number of probes per each hop.")
var parallelRequests = flag.Int("r", 18, "Set ParallelRequests number. It should be 1 when there is a multi-routing.")
var maxHops = flag.Int("m", 30, "Set the max number of hops (max TTL to be reached).")
var dataOrigin = flag.String("d", "LeoMoeAPI", "Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight]")
var rdnsenable = flag.Bool("rdns", false, "Set whether rDNS will be display")
var routePath = flag.Bool("report", false, "Route Path")
var realtimePrint = flag.Bool("realtime", false, "Output trace results in runtime")
var tablePrint = flag.Bool("table", false, "Output trace results as table")
var fSet = flag.NewFlagSet("", flag.ExitOnError)
var fastTest = fSet.Bool("f", false, "One-Key Fast Traceroute")
var tcpSYNFlag = fSet.Bool("T", false, "Use TCP SYN for tracerouting (default port is 80)")
var udpPackageFlag = fSet.Bool("U", false, "Use UDP Package for tracerouting (default port is 53 in UDP)")
var port = fSet.Int("p", 80, "Set SYN Traceroute Port")
var manualConfig = fSet.Bool("c", false, "Manual Config [Advanced]")
var numMeasurements = fSet.Int("q", 3, "Set the number of probes per each hop.")
var parallelRequests = fSet.Int("r", 18, "Set ParallelRequests number. It should be 1 when there is a multi-routing.")
var maxHops = fSet.Int("m", 30, "Set the max number of hops (max TTL to be reached).")
var dataOrigin = fSet.String("d", "", "Choose IP Geograph Data Provider [LeoMoeAPI, IP.SB, IPInfo, IPInsight, IPAPI.com]")
var noRdns = fSet.Bool("n", false, "Disable IP Reverse DNS lookup")
var routePath = fSet.Bool("report", false, "Route Path")
var tablePrint = fSet.Bool("table", false, "Output trace results as table")
var ver = fSet.Bool("V", false, "Check Version")
func printArgHelp() {
fmt.Println("\nArgs Error\nUsage : 'nexttrace [option...] HOSTNAME' or 'nexttrace HOSTNAME [option...]'\nOPTIONS: [-VTU] [-d DATAORIGIN.STR ] [ -m TTL ] [ -p PORT ] [ -q PROBES.COUNT ] [ -r PARALLELREQUESTS.COUNT ] [-rdns] [ -table ] -report")
fSet.PrintDefaults()
os.Exit(2)
}
func flagApply() string {
flag.Parse()
ipArg := flag.Args()
if flag.NArg() != 1 {
fmt.Println("Args Error\nUsage : ./nexttrace [-T] [-rdns] [-displayMode <displayMode>] [-d <dataOrigin> ] [ -m <hops> ] [ -p <port> ] [ -q <probes> ] [ -r <parallelrequests> ] <hostname>")
os.Exit(2)
printer.Version()
target := ""
if len(os.Args) < 2 {
printArgHelp()
}
return ipArg[0]
// flag parse
if !strings.HasPrefix(os.Args[1], "-") {
target = os.Args[1]
fSet.Parse(os.Args[2:])
} else {
fSet.Parse(os.Args[1:])
target = fSet.Arg(0)
}
// Print Version
if *ver {
os.Exit(0)
}
// Advanced Config
if *manualConfig {
if _, err := config.Generate(); err != nil {
log.Fatal(err)
}
os.Exit(0)
}
// -f Fast Test
if *fastTest {
fastTrace.FastTest(*tcpSYNFlag)
os.Exit(0)
}
if target == "" {
printArgHelp()
}
return target
}
func main() {
domain := flagApply()
if os.Getuid() != 0 {
log.Fatalln("Traceroute requires root/sudo privileges.")
}
domain := flagApply()
ip := util.DomainLookUp(domain)
configData, err := config.Read()
// Initialize Default Config
if err != nil || configData.DataOrigin == "" {
if configData, err = config.AutoGenerate(); err != nil {
log.Fatal(err)
}
}
// Set Token from Config
ipgeo.SetToken(configData.Token)
// Check Whether User has specified IP Geograph Data Provider
if *dataOrigin == "" {
// Use Default Data Origin with Config
*dataOrigin = configData.DataOrigin
}
var ip net.IP
if *tcpSYNFlag || *udpPackageFlag {
ip = util.DomainLookUp(domain, true)
} else {
ip = util.DomainLookUp(domain, false)
}
printer.PrintTraceRouteNav(ip, domain, *dataOrigin)
var m trace.Method = ""
@@ -66,7 +138,7 @@ func main() {
MaxHops: *maxHops,
NumMeasurements: *numMeasurements,
ParallelRequests: *parallelRequests,
RDns: *rdnsenable,
RDns: !*noRdns,
IPGeoSource: ipgeo.GetSource(*dataOrigin),
Timeout: 2 * time.Second,
}
@@ -81,21 +153,14 @@ func main() {
log.Fatalln(err)
}
if *routePath {
if (*tcpSYNFlag && *udpPackageFlag) || *tablePrint || configData.TablePrintDefault {
printer.TracerouteTablePrinter(res)
} else if *tcpSYNFlag || *udpPackageFlag {
printer.TraceroutePrinter(res)
}
if *routePath || configData.AlwaysRoutePath {
r := reporter.New(res, ip.String())
r.Print()
return
}
if m == trace.ICMPTrace && *tablePrint {
printer.TracerouteTablePrinter(res)
}
if m == trace.TCPTrace || m == trace.UDPTrace {
if *realtimePrint {
printer.TraceroutePrinter(res)
} else {
printer.TracerouteTablePrinter(res)
}
}
}

View File

@@ -1,252 +1,115 @@
#!/bin/bash
usrPath="/usr/local/bin"
Green_font="\033[32m"
Yellow_font="\033[33m"
Red_font="\033[31m"
Font_suffix="\033[0m"
Info="${Green_font}[Info]${Font_suffix}"
Error="${Red_font}[Error]${Font_suffix}"
Tips="${Green_font}[Tips]${Font_suffix}"
Temp_path="/var/tmp/nexttrace"
checkRootPermit() {
[[ $EUID -ne 0 ]] && echo "请使用sudo/root权限运行本脚本" && exit 1
[[ $EUID -ne 0 ]] && echo -e "${Error} 请使用sudo/root权限运行本脚本" && exit 1
}
checkSystemArch() {
arch=$(uname -m)
if [[ $arch == "x86_64" ]]; then
archParam="amd64"
archParam="amd64"
fi
if [[ $arch == "aarch64" ]]; then
archParam="arm64"
fi
if [[ $arch == "arm64" ]]; then
archParam="arm64"
fi
if [[ $archParam == "" ]]; then
echo "未知的系统架构,请联系作者"
exit 1
archParam="arm64"
fi
}
checkSystemDistribution() {
case "$OSTYPE" in
darwin*)
osDistribution="darwin"
downPath="/var/tmp/nexttrace"
;;
linux*)
osDistribution="linux"
downPath="/var/tmp/nexttrace"
;;
linux*)
osDistribution="linux"
downPath="/usr/local/bin/nexttrace"
;;
*)
echo "unknown: $OSTYPE"
exit 1
;;
echo "unknown: $OSTYPE"
exit 1
;;
esac
}
getLocation() {
echo "正在获取地理位置信息..."
countryCode=$(curl -s "http://ip-api.com/line/?fields=countryCode")
}
installWgetPackage() {
# macOS should install wget originally. Nothing to do
echo "wget 正在安装中..."
echo -e "${Info} wget 正在安装中..."
# try apt
apt-get -h &>/dev/null
apt -h &> /dev/null
if [ $? -eq 0 ]; then
# 先更新一下数据源有些机器数据源比较老可能会404
apt-get update -y &>/dev/null
apt-get install wget -y &>/dev/null
# 先更新一下数据源有些机器数据源比较老可能会404
apt update -y &> /dev/null
apt install wget -y &> /dev/null
fi
# try yum
yum -h &>/dev/null
yum -h &> /dev/null
if [ $? -eq 0 ]; then
yum -y update &>/dev/null
yum install wget -y &>/dev/null
yum install wget -y &> /dev/null
fi
# try dnf
dnf -h &>/dev/null
dnf -h &> /dev/null
if [ $? -eq 0 ]; then
dnf check-update &>/dev/null
dnf install wget -y &>/dev/null
dnf install wget -y &> /dev/null
fi
# try pacman
pacman -h &>/dev/null
pacman -h &> /dev/null
if [ $? -eq 0 ]; then
pacman -Sy &>/dev/null
pacman -S wget &>/dev/null
pacman -Sy
pacman -S wget
fi
wget -h &>/dev/null
if [ $? -ne 0 ]; then
echo "wget 安装失败"
exit 1
fi
}
installJqPackage() {
# macOS should install wget originally. Nothing to do
echo "jq 正在安装中..."
# try apt
apt-get -h &>/dev/null
if [ $? -eq 0 ]; then
# 先更新一下数据源有些机器数据源比较老可能会404
apt-get update -y &>/dev/null
apt-get install jq -y &>/dev/null
fi
# try yum
yum -h &>/dev/null
if [ $? -eq 0 ]; then
yum -y update &>/dev/null
yum install jq -y &>/dev/null
fi
# try dnf
dnf -h &>/dev/null
if [ $? -eq 0 ]; then
dnf check-update &>/dev/null
dnf install jq -y &>/dev/null
fi
# try pacman
pacman -h &>/dev/null
if [ $? -eq 0 ]; then
pacman -Sy &>/dev/null
pacman -S jq &>/dev/null
fi
jq -h &>/dev/null
if [ $? -ne 0 ]; then
echo "jq 安装失败"
exit 1
fi
}
checkWgetPackage() {
wget -h &>/dev/null
wget -h &> /dev/null
if [ $? -ne 0 ]; then
read -r -p "您还没有安装wget是否安装? (y/n)" input
case $input in
[yY][eE][sS] | [yY])
installWgetPackage
;;
[nN][oO] | [nN])
echo "您选择了取消安装,脚本即将退出"
exit 1
;;
*)
installWgetPackage
;;
esac
installWgetPackage
fi
}
checkVersion() {
echo "正在检查版本..."
version=$(curl -sL https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | jq -r '.tag_name')
if [[ $version == "" ]]; then
echo "获取版本失败,请检查网络连接"
exit 1
fi
echo 当前最新release版本${version}
read -r -p "是否安装/更新软件? (y/n)" input
case $input in
[yY][eE][sS] | [yY])
break
;;
[nN][oO] | [nN])
echo "您选择了取消安装/更新,脚本即将退出"
exit 1
;;
*)
break
;;
esac
}
checkJqPackage() {
jq -h &>/dev/null
if [ $? -ne 0 ]; then
echo "您还没有安装jq 当您取消安装我们会使用awk获取当前版本号。"
read -r -p "但是如遇Github变更API这可能会存在问题是否安装? (y/n)" input
case $input in
[yY][eE][sS] | [yY])
installJqPackage
;;
[nN][oO] | [nN])
echo "您选择了取消安装"
return 0
;;
*)
installJqPackage
;;
esac
fi
return 1
}
downloadBinrayFile() {
echo "正在获取最新版的 NextTrace 发行版文件信息..."
checkJqPackage
echo -e "${Info} 获取最新版的 NextTrace 发行版文件信息"
# 简单说明一下Github提供了一个API可以获取最新发行版本的二进制文件下载地址对应的是browser_download_url根据刚刚测得的osDistribution、archParam获取对应的下载地址
if [[ $? -eq 1 ]]; then
# 支持 jq 不回退
# echo nexttrace_${osDistribution}_${archParam}
latestURL=$(curl -s https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | jq ".assets[] | select(.name == \"nexttrace_${osDistribution}_${archParam}\") | .browser_download_url")
latestURL=${latestURL:1:-1}
else
# 不支持 jq用户拒绝安装回退 awk
latestURL=$(curl -s https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | grep -i "browser_download_url.*${osDistribution}.*${archParam}" | awk -F '"' '{print $4}')
fi
latestURL=$(curl -s https://api.github.com/repos/xgadget-lab/nexttrace/releases/latest | grep -i "browser_download_url.*${osDistribution}.*${archParam}" | awk -F '"' '{print $4}')
if [ "$countryCode" == "CN" ]; then
read -r -p "检测到国内网络环境,是否使用镜像下载以加速(y/n)" input
case $input in
[yY][eE][sS] | [yY])
latestURL="https://ghproxy.com/"$latestURL
;;
[nN][oO] | [nN])
echo "您选择了不使用镜像,下载可能会变得异常缓慢,或者失败"
;;
*)
latestURL="https://ghproxy.com/"$latestURL
;;
esac
echo -e "${Info} 检测到国内环境,正在使用镜像下载"
latestURL="https://ghproxy.com/"$latestURL
fi
echo "正在下载 NextTrace 二进制文件..."
wget -O ${downPath} ${latestURL} &>/dev/null
if [ $? -eq 0 ]; then
echo "NextTrace 现在已经在您的系统中可用"
changeMode
mv ${downPath} ${usrPath}
if [[ ${osDistribution} == "macOS" ]]; then
xattr -r -d com.apple.quarantine ${usrPath}/nexttrace
fi
echo -e "${Info} 正在下载 NextTrace 二进制文件..."
wget -O ${Temp_path} ${latestURL} &> /dev/null
if [ $? -eq 0 ];
then
changeMode
mv ${Temp_path} ${downPath}
echo -e "${Info} NextTrace 现在已经在您的系统中可用"
else
echo "NextTrace 下载失败,请检查您的网络是否正常"
exit 1
echo -e "${Error} NextTrace 下载失败,请检查您的网络是否正常"
exit 1
fi
}
changeMode() {
chmod +x ${downPath} &>/dev/null
chmod +x ${Temp_path} &> /dev/null
}
runBinrayFileHelp() {
if [ -e ${usrPath} ]; then
${usrPath}/nexttrace -h
if [ -e ${downPath} ]; then
${downPath} -V
echo -e "${Tips} 一切准备就绪!使用命令 nexttrace 1.1.1.1 开始您的第一次路由测试吧~ 更多进阶命令玩法可以用 nexttrace -h 查看哦\n 关于软件卸载因为nexttrace是绿色版单文件卸载只需输入命令 rm /usr/local/bin/nexttrace 即可"
fi
}
@@ -255,8 +118,6 @@ checkRootPermit
checkSystemDistribution
checkSystemArch
checkWgetPackage
# TODO: 检查版本并更新
#checkVersion
# Download Procedure
getLocation

View File

@@ -5,6 +5,15 @@ import (
"net"
)
var version = "v0.0.0.alpha"
var buildDate = ""
var commitID = ""
func Version() {
fmt.Println("NextTrace", version, buildDate, commitID)
fmt.Println("XGadget-lab Leo (leo.moe) & Vincent (vincent.moe) & zhshch (xzhsh.ch)")
}
func PrintTraceRouteNav(ip net.IP, domain string, dataOrigin string) {
fmt.Println("IP Geo Data Provider: " + dataOrigin)

View File

@@ -52,11 +52,11 @@ func formatIpGeoData(ip string, data *ipgeo.IPGeoData) string {
// TODO: 判断阿里云和腾讯云内网,数据不足,有待进一步完善
// TODO: 移动IDC判断到Hop.fetchIPData函数减少API调用
if strings.HasPrefix(ip, "9.") {
res = append(res, "局域网", "腾讯云")
res = append(res, "LAN Address")
} else if strings.HasPrefix(ip, "11.") {
res = append(res, "局域网", "阿里云")
res = append(res, "LAN Address")
} else if data.Country == "" {
res = append(res, "局域网")
res = append(res, "LAN Address")
} else {
// 有些IP的归属信息为空这个时候将ISP的信息填入
if data.Owner == "" {

105
printer/printer_test.go Normal file
View File

@@ -0,0 +1,105 @@
package printer
import (
"errors"
"net"
"testing"
"time"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
"github.com/xgadget-lab/nexttrace/util"
)
func TestPrintTraceRouteNav(t *testing.T) {
PrintTraceRouteNav(util.DomainLookUp("1.1.1.1", false), "1.1.1.1", "dataOrigin")
}
var testGeo = &ipgeo.IPGeoData{
Asnumber: "TestAsnumber",
Country: "TestCountry",
Prov: "TestProv",
City: "TestCity",
District: "TestDistrict",
Owner: "TestOwner",
Isp: "TestIsp",
}
var testResult = &trace.Result{
Hops: [][]trace.Hop{
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: testGeo,
},
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: testGeo,
},
},
{
{
Success: false,
Address: nil,
Hostname: "",
TTL: 0,
RTT: 0,
Error: errors.New("test error"),
Geo: nil,
},
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: nil,
},
},
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "test",
TTL: 0,
RTT: 0,
Error: nil,
Geo: &ipgeo.IPGeoData{},
},
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: testGeo,
},
},
},
}
func TestTraceroutePrinter(t *testing.T) {
TraceroutePrinter(testResult)
}
func TestTracerouteTablePrinter(t *testing.T) {
TracerouteTablePrinter(testResult)
}
func TestRealtimePrinter(t *testing.T) {
RealtimePrinter(testResult, 0)
RealtimePrinter(testResult, 1)
RealtimePrinter(testResult, 2)
}

View File

@@ -7,7 +7,7 @@ import (
)
func RealtimePrinter(res *trace.Result, ttl int) {
fmt.Print(ttl)
fmt.Print(ttl + 1)
for i := range res.Hops[ttl] {
HopPrinter(res.Hops[ttl][i])
}

View File

@@ -4,6 +4,8 @@ import (
"fmt"
"strings"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
"github.com/fatih/color"
@@ -37,7 +39,7 @@ func TracerouteTablePrinter(res *trace.Result) {
if data.City != "" {
tbl.AddRow(data.Hop, data.IP, data.Latency, data.Asnumber, data.Country+", "+data.Prov+", "+data.City, data.Owner)
} else {
tbl.AddRow(data.Hop, data.IP, data.Latency, data.Asnumber, data.Country, data.Owner)
tbl.AddRow(data.Hop, data.IP, data.Latency, data.Asnumber, data.Country + ", " + data.Prov, data.Owner)
}
}
@@ -72,16 +74,18 @@ func tableDataGenerator(h trace.Hop) *rowData {
Hop: fmt.Sprint(h.TTL),
IP: IP,
Latency: lantency,
Country: "局域网",
Owner: "腾讯云",
Country: "LAN Address",
Prov: "LAN Address",
Owner: "",
}
} else if strings.HasPrefix(IP, "11.") {
return &rowData{
Hop: fmt.Sprint(h.TTL),
IP: IP,
Latency: lantency,
Country: "局域网",
Owner: "阿里云",
Country: "LAN Address",
Prov: "LAN Address",
Owner: "",
}
}
@@ -89,6 +93,10 @@ func tableDataGenerator(h trace.Hop) *rowData {
IP = fmt.Sprint(h.Hostname, " (", IP, ") ")
}
if h.Geo == nil {
h.Geo = &ipgeo.IPGeoData{}
}
r := &rowData{
Hop: fmt.Sprint(h.TTL),
IP: IP,

View File

@@ -1,10 +1,10 @@
package reporter
import (
"errors"
"fmt"
"net"
"strings"
"sync"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
@@ -24,9 +24,12 @@ func New(rs *trace.Result, ip string) Reporter {
}
type reporter struct {
targetIP string
routeReport map[uint16][]routeReportNode
routeResult *trace.Result
targetTTL uint16
targetIP string
routeReport map[uint16][]routeReportNode
routeReportLock sync.Mutex
routeResult *trace.Result
wg sync.WaitGroup
}
type routeReportNode struct {
@@ -40,71 +43,115 @@ func experimentTag() {
fmt.Println("Route-Path 功能实验室")
}
func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData) (routeReportNode, error) {
rpn := routeReportNode{}
go func() {
ptr, err := net.LookupAddr(ip)
if err == nil {
if strings.Contains(strings.ToLower(ptr[0]), "ix") {
rpn.ix = true
} else {
rpn.ix = false
}
}
}()
func (r *reporter) generateRouteReportNode(ip string, ipGeoData ipgeo.IPGeoData, ttl uint16) {
var success bool = true
defer r.wg.Done()
rpn := routeReportNode{}
ptr, err := net.LookupAddr(ip)
if err == nil {
if strings.Contains(strings.ToLower(ptr[0]), "ix") {
rpn.ix = true
} else {
rpn.ix = false
}
}
// TODO: 这种写法不好,后面再重构一下
// 判断反向解析的域名中又或者是IP地理位置数据库中是否出现了 IX
if strings.Contains(strings.ToLower(ipGeoData.Isp), "exchange") || strings.Contains(strings.ToLower(ipGeoData.Isp), "ix") || strings.Contains(strings.ToLower(ipGeoData.Owner), "exchange") || strings.Contains(strings.ToLower(ipGeoData.Owner), "ix") {
rpn.ix = true
}
// TODO: 正则判断POP并且提取带宽大小等信息
// CN2 需要特殊处理因为他们很多没有ASN
// 但是目前这种写法是不规范的属于凭空标记4809的IP
// TODO: 用更好的方式显示 CN2 骨干网的路由 Path
if strings.HasPrefix(ip, "59.43") {
rpn.asn = "4809"
} else {
rpn.asn = ipGeoData.Asnumber
}
// 无论最后一跳是否为存在地理位置信息AnyCast都应该给予显示
if ipGeoData.Country == "" || ipGeoData.City == "" || ipGeoData.City == "-" && ip != r.targetIP {
return rpn, errors.New("GeoData Search Failed")
if (ipGeoData.Country == "" || ipGeoData.Country == "LAN Address" || ipGeoData.Country == "-") && ip != r.targetIP {
success = false
} else {
if ipGeoData.City == "" {
rpn.geo = []string{ipGeoData.Country, ipGeoData.Country}
rpn.geo = []string{ipGeoData.Country, ipGeoData.Prov}
} else {
rpn.geo = []string{ipGeoData.Country, ipGeoData.City}
}
}
if ipGeoData.Asnumber == "" {
rpn.asn = "*"
}
if ipGeoData.Isp == "" {
rpn.isp = ipGeoData.Owner
} else {
rpn.isp = ipGeoData.Isp
}
return rpn, nil
// 有效记录
if success {
// 锁住资源防止同时写panic
r.routeReportLock.Lock()
// 添加到MAP中
r.routeReport[ttl] = append(r.routeReport[ttl], rpn)
// 写入完成,解锁释放资源给其他协程
r.routeReportLock.Unlock()
}
}
func (r *reporter) InitialBaseData() Reporter {
var nodeIndex uint16 = 1
reportNodes := map[uint16][]routeReportNode{}
for i := uint16(0); int(i) < len(r.routeResult.Hops); i++ {
r.routeReport = reportNodes
r.targetTTL = uint16(len(r.routeResult.Hops))
for i := uint16(0); i < r.targetTTL; i++ {
traceHop := r.routeResult.Hops[i][0]
if traceHop.Success {
currentIP := traceHop.Address.String()
rpn, err := r.generateRouteReportNode(currentIP, *traceHop.Geo)
if err == nil {
reportNodes[nodeIndex] = append(reportNodes[nodeIndex], rpn)
nodeIndex += 1
}
r.wg.Add(1)
go r.generateRouteReportNode(currentIP, *traceHop.Geo, i)
}
}
r.routeReport = reportNodes
// 等待所有的子协程运行完毕
r.wg.Wait()
return r
}
func (r *reporter) Print() {
var beforeActiveTTL uint16 = 0
r.InitialBaseData()
for i := uint16(1); int(i) < len(r.routeReport)+1; i++ {
// 尝试首个有效 TTL
for i := uint16(0); i < r.targetTTL; i++ {
if len(r.routeReport[i]) != 0 {
beforeActiveTTL = i
// 找到以后便不再循环
break
}
}
for i := beforeActiveTTL; i < r.targetTTL; i++ {
// 计算该TTL内的数据长度如果为0则代表没有有效数据
if len(r.routeReport[i]) == 0 {
// 跳过改跃点的数据整理
continue
}
nodeReport := r.routeReport[i][0]
if i == 1 {
if i == beforeActiveTTL {
fmt.Printf("AS%s %s「%s『%s", nodeReport.asn, nodeReport.isp, nodeReport.geo[0], nodeReport.geo[1])
} else {
nodeReportBefore := r.routeReport[i-1][0]
nodeReportBefore := r.routeReport[beforeActiveTTL][0]
// ASN 相同,同个 ISP 内部的数据传递
if nodeReportBefore.asn == nodeReport.asn {
// Same ASN but Coutry or City Changed
if nodeReportBefore.geo[0] != nodeReport.geo[0] {
@@ -115,8 +162,11 @@ func (r *reporter) Print() {
}
}
} else {
// ASN 不同,跨 ISP 的数据传递,这里可能会出现 POP、IP Transit、Peer、Exchange
fmt.Printf("』」")
if int(i) != len(r.routeReport)+1 {
// 部分 Shell 客户端可能无法很好的展示这个特殊字符
// TODO: 寻找其他替代字符
fmt.Printf("\n ╭╯\n ╰")
}
if nodeReport.ix {
@@ -126,6 +176,8 @@ func (r *reporter) Print() {
}
}
}
// 标记为最新的一个有效跃点
beforeActiveTTL = i
}
fmt.Println("』」")
}

View File

@@ -1,31 +1,115 @@
package reporter
import (
"net"
"testing"
"time"
"github.com/xgadget-lab/nexttrace/ipgeo"
"github.com/xgadget-lab/nexttrace/trace"
"github.com/xgadget-lab/nexttrace/util"
)
var testResult = &trace.Result{
Hops: [][]trace.Hop{
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("192.168.3.1")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: &ipgeo.IPGeoData{
Asnumber: "4808",
Country: "中国",
Prov: "北京市",
City: "北京市",
District: "北京市",
Owner: "",
Isp: "中国联通",
},
},
},
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("114.249.16.1")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: &ipgeo.IPGeoData{
Asnumber: "4808",
Country: "中国",
Prov: "北京市",
City: "北京市",
District: "北京市",
Owner: "",
Isp: "中国联通",
},
},
},
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("219.158.5.150")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: &ipgeo.IPGeoData{
Asnumber: "4837",
Country: "中国",
Prov: "",
City: "",
District: "",
Owner: "",
Isp: "中国联通",
},
},
},
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("62.115.125.160")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: &ipgeo.IPGeoData{
Asnumber: "1299",
Country: "Sweden",
Prov: "Stockholm County",
City: "Stockholm",
District: "",
Owner: "",
Isp: "Telia Company AB",
},
},
},
{
{
Success: true,
Address: &net.IPAddr{IP: net.ParseIP("213.226.68.73")},
Hostname: "test",
TTL: 0,
RTT: 10 * time.Millisecond,
Error: nil,
Geo: &ipgeo.IPGeoData{
Asnumber: "56630",
Country: "Germany",
Prov: "Hesse, Frankfurt",
City: "",
District: "",
Owner: "",
Isp: "Melbikomas UAB",
},
},
},
},
}
func TestPrint(t *testing.T) {
ip := util.DomainLookUp("213.226.68.73")
var m trace.Method = "tcp"
var conf = trace.Config{
DestIP: ip,
DestPort: 80,
MaxHops: 30,
NumMeasurements: 1,
ParallelRequests: 1,
RDns: true,
IPGeoSource: ipgeo.GetSource("LeoMoeAPI"),
Timeout: 2 * time.Second,
//Quic: false,
}
res, _ := trace.Traceroute(m, conf)
r := New(res, ip.String())
r := New(testResult, "213.226.68.73")
r.Print()
}

View File

@@ -1,19 +0,0 @@
package signal
type Signal struct {
sigChan chan struct{}
}
func New() *Signal {
return &Signal{sigChan: make(chan struct{}, 1)}
}
func (s *Signal) Signal() {
if len(s.sigChan) == 0 {
s.sigChan <- struct{}{}
}
}
func (s *Signal) Chan() chan struct{} {
return s.sigChan
}

View File

@@ -1,45 +0,0 @@
package taskgroup
import (
"sync"
)
type TaskGroup struct {
count int
mu sync.Mutex
done []chan struct{}
}
func New() *TaskGroup {
return &TaskGroup{
count: 0,
mu: sync.Mutex{},
done: []chan struct{}{},
}
}
func (t *TaskGroup) Add() {
t.mu.Lock()
defer t.mu.Unlock()
t.count++
}
func (t *TaskGroup) Done() {
t.mu.Lock()
defer t.mu.Unlock()
if t.count-1 == 0 {
for _, doneChannel := range t.done {
doneChannel <- struct{}{}
}
t.done = []chan struct{}{}
}
t.count--
}
func (t *TaskGroup) Wait() {
doneChannel := make(chan struct{})
t.mu.Lock()
t.done = append(t.done, doneChannel)
t.mu.Unlock()
<-doneChannel
}

View File

@@ -1,6 +1,7 @@
package trace
import (
"encoding/binary"
"log"
"net"
"os"
@@ -74,19 +75,32 @@ func (t *ICMPTracer) listenICMP() {
if msg.N == nil {
continue
}
rm, err := icmp.ParseMessage(1, msg.Msg[:*msg.N])
if err != nil {
log.Println(err)
continue
if binary.BigEndian.Uint16(msg.Msg[32:34]) != uint16(os.Getpid()&0xffff) {
// 如果类型为应答消息且应答消息包的进程ID与主进程相同时不跳过
if msg.Msg[0] != 0 || binary.BigEndian.Uint16(msg.Msg[4:6]) != uint16(os.Getpid()&0xffff) {
continue
}
}
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
t.handleICMPMessage(msg, 0, rm.Body.(*icmp.TimeExceeded).Data)
case ipv4.ICMPTypeEchoReply:
t.handleICMPMessage(msg, 1, rm.Body.(*icmp.Echo).Data)
default:
// log.Println("received icmp message of unknown type", rm.Type)
dstip := net.IP(msg.Msg[24:28])
if dstip.Equal(t.DestIP) || dstip.Equal(net.IPv4zero) {
// 匹配再继续解析包,否则直接丢弃
rm, err := icmp.ParseMessage(1, msg.Msg[:*msg.N])
if err != nil {
log.Println(err)
continue
}
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
t.handleICMPMessage(msg, 0, rm.Body.(*icmp.TimeExceeded).Data)
case ipv4.ICMPTypeEchoReply:
t.handleICMPMessage(msg, 1, rm.Body.(*icmp.Echo).Data)
default:
// log.Println("received icmp message of unknown type", rm.Type)
}
}
}
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/xgadget-lab/nexttrace/listener_channel"
"github.com/xgadget-lab/nexttrace/util"
"golang.org/x/net/context"
"golang.org/x/net/icmp"
@@ -89,18 +88,21 @@ func (t *TCPTracer) listenICMP() {
if msg.N == nil {
continue
}
rm, err := icmp.ParseMessage(1, msg.Msg[:*msg.N])
if err != nil {
log.Println(err)
continue
}
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
t.handleICMPMessage(msg, rm.Body.(*icmp.TimeExceeded).Data)
case ipv4.ICMPTypeDestinationUnreachable:
t.handleICMPMessage(msg, rm.Body.(*icmp.DstUnreach).Data)
default:
//log.Println("received icmp message of unknown type", rm.Type)
dstip := net.IP(msg.Msg[24:28])
if dstip.Equal(t.DestIP) {
rm, err := icmp.ParseMessage(1, msg.Msg[:*msg.N])
if err != nil {
log.Println(err)
continue
}
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
t.handleICMPMessage(msg, rm.Body.(*icmp.TimeExceeded).Data)
case ipv4.ICMPTypeDestinationUnreachable:
t.handleICMPMessage(msg, rm.Body.(*icmp.DstUnreach).Data)
default:
//log.Println("received icmp message of unknown type", rm.Type)
}
}
}
}
@@ -110,10 +112,7 @@ func (t *TCPTracer) listenICMP() {
// @title listenTCP
// @description 监听TCP的响应数据包
func (t *TCPTracer) listenTCP() {
lc := listener_channel.New(t.tcp)
defer lc.Stop()
lc := NewPacketListener(t.tcp, t.ctx)
go lc.Start()
for {

View File

@@ -10,7 +10,6 @@ import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/xgadget-lab/nexttrace/listener_channel"
"github.com/xgadget-lab/nexttrace/util"
"golang.org/x/net/context"
"golang.org/x/net/icmp"
@@ -111,10 +110,7 @@ func (t *TCPTracerv6) listenICMP() {
// @title listenTCP
// @description 监听TCP的响应数据包
func (t *TCPTracerv6) listenTCP() {
lc := listener_channel.New(t.tcp)
defer lc.Stop()
lc := NewPacketListener(t.tcp, t.ctx)
go lc.Start()
for {

View File

@@ -39,11 +39,11 @@ func formatIpGeoData(ip string, data *ipgeo.IPGeoData) string {
// TODO: 判断阿里云和腾讯云内网,数据不足,有待进一步完善
// TODO: 移动IDC判断到Hop.fetchIPData函数减少API调用
if strings.HasPrefix(ip, "9.") {
res = append(res, "局域网", "腾讯云")
res = append(res, "LAN Address", "")
} else if strings.HasPrefix(ip, "11.") {
res = append(res, "局域网", "阿里云")
res = append(res, "LAN Address", "")
} else if data.Country == "" {
res = append(res, "局域网")
res = append(res, "LAN Address")
} else {
// 有些IP的归属信息为空这个时候将ISP的信息填入
if data.Owner == "" {

View File

@@ -25,7 +25,7 @@ func LocalIPPort(dstip net.IP) (net.IP, int) {
return nil, -1
}
func DomainLookUp(host string) net.IP {
func DomainLookUp(host string, ipv4Only bool) net.IP {
ips, err := net.LookupIP(host)
if err != nil {
fmt.Println("Domain " + host + " Lookup Fail.")
@@ -36,17 +36,20 @@ func DomainLookUp(host string) net.IP {
var ipv6Flag = false
for _, ip := range ips {
ipSlice = append(ipSlice, ip)
// 仅返回ipv4的ip
// if ip.To4() != nil {
// ipSlice = append(ipSlice, ip)
// } else {
// ipv6Flag = true
// }
if ipv4Only {
// 仅返回ipv4的ip
if ip.To4() != nil {
ipSlice = append(ipSlice, ip)
} else {
ipv6Flag = true
}
} else {
ipSlice = append(ipSlice, ip)
}
}
if ipv6Flag {
fmt.Println("[Info] IPv6 Traceroute is not supported right now.")
fmt.Println("[Info] IPv6 TCP/UDP Traceroute is not supported right now.")
if len(ipSlice) == 0 {
os.Exit(0)
}