完成Bitsflow家人云的迁移工作

This commit is contained in:
zeaslity
2025-12-08 08:56:23 +08:00
parent 9d93a1ee6e
commit dcc8afffba
19 changed files with 1515 additions and 404 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="dataSourceStorageLocal" created-in="IU-252.25557.131">
<component name="dataSourceStorageLocal" created-in="IU-252.28238.7">
<data-source name="腾讯云-成都" uuid="79c9466f-d8a3-418a-b54a-f6e314306a0c">
<database-info product="MySQL" version="8.0.27" jdbc-version="4.2" driver-name="MySQL Connector/J" driver-version="mysql-connector-java-8.0.25 (Revision: 08be9e9b4cba6aa115f9b27b215887af40b159e0)" dbms="MYSQL" exact-version="8.0.27" exact-driver-version="8.0">
<extra-name-characters>#@</extra-name-characters>

View File

@@ -69,7 +69,7 @@ sudo sysctl -p /etc/sysctl.d/proxy-wdd.conf
sysctl net.ipv4.tcp_congestion_control
sudo ethtool -K enp3s0 gro on
sudo ethtool -K enp3s0 gso on
sudo ethtool -K enp3s0 tso on
sudo ethtool -K ens3 gro on
sudo ethtool -K ens3 gso on
sudo ethtool -K ens3 tso on

View File

@@ -50,6 +50,7 @@ dns: # 启用 DNS 服务器
# Fake-IP 例外名单对于这些域名Clash 将返回其真实的 IP 地址
# 这对于一些无法处理 Fake-IP 的内网服务或特定应用至关重要
fake-ip-filter:
- localhost
- '*.lan'
- '*.local'
- '*.arpa'
@@ -69,7 +70,6 @@ dns: # 启用 DNS 服务器
- 119.29.29.29
# [优化] 主 DNS 服务器列表 (国内,加密 DoH)
# 会与 Fallback DNS 并发请求,如果返回的 IP 是国内 IP则立即采用速度快
# 使用加密 DNS 替代传统 UDP DNS增强解析的稳定性和抗干扰性。
nameserver:
- 223.5.5.5 # 阿里云
- 180.76.76.76 # 百度DNS
@@ -85,6 +85,8 @@ dns: # 启用 DNS 服务器
- https://dns.quad9.net/dns-query # IBM quad9
- https://dns.opendns.com/dns-query # CISCO OpenDNS
- https://dns.adguard-dns.com/dns-query # AdGuard DNS
- tls://8.8.8.8:853 # Google DoT (纯IP)
- tls://1.1.1.1:853 # Cloudflare DoT (纯IP)
- tls://8.8.4.4:853 # Google DNS (DoT)
# Fallback DNS 例外名单,匹配此列表的域名将只使用主 DNS 解析
fallback-filter:
@@ -120,12 +122,13 @@ dns: # 启用 DNS 服务器
prefer-h3: false
# DNS也遵循规则进行解析
respect-rules: false
# 代理的DNS解析地址
# [关键] 代理节点域名解析必须用纯IP的国内DNS
proxy-server-nameserver:
- 'https://dns.google/dns-query'
- 'https://1.1.1.1/dns-query'
- 223.5.5.5
- 119.29.29.29
# 直连模式下的DNS服务器
direct-nameserver:
- 192.168.78.39
- 119.29.29.29 # 腾讯 DNSPod
- 114.114.114.114 # 114 DNS
- 223.5.5.5 # 阿里 DNS
@@ -167,274 +170,6 @@ external-controller-cors: { }
proxies:
- type: vless
name: TC-HongKong
server: 43.154.83.213
port: 24443
uuid: f8702759-f402-4e85-92a6-8540d577de22
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: BFC-LosAngles
server: 154.40.34.106
port: 443
uuid: 302fbcb8-e096-46a1-906f-e879ec5ab0c5
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: xx.l4.ca.bg.107421.xyz
tls: true
udp: true
- type: vless
name: CF-HongKong-R-TCHK
server: 43.154.83.213
port: 24453
uuid: 93be1d17-8e02-449d-bb99-683ed46fbe50
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-HongKong
server: 43.154.83.213
port: 24452
uuid: cdf0b19a-9524-48d5-b697-5f10bb567734
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: Care-DEU-Dusseldorf-R-TCHK
server: 43.154.83.213
port: 24451
uuid: 9fa9b4e7-d76d-4890-92cf-ce9251a76f59
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: Care-DEU-Dusseldorf
server: 45.134.50.233
port: 443
uuid: b1417d92-998d-410b-a5f3-cf144b6f043e
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: bingo.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-KOR-Seoul
server: 140.238.14.103
port: 443
uuid: 1089cc14-557e-47ac-ac85-c07957b3cce3
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: xx.s4.cc.hh.107421.xyz
tls: true
udp: true
- type: vless
name: FV-DEU-Frankfurt
server: 43.154.83.213
port: 24444
uuid: 6055eac4-dee7-463b-b575-d30ea94bb768
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-KOR-Seoul
server: 43.154.83.213
port: 24445
uuid: 1cd284b2-d3d8-4165-b773-893f836c2b51
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-JPN-Tokyo
server: 43.154.83.213
port: 24446
uuid: bf0e9c35-84a9-460e-b5bf-2fa9f2fb3bca
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-GBR-London
server: 43.154.83.213
port: 24447
uuid: adc19390-373d-4dfc-b0f6-19fab1b6fbf6
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-SGP
server: 43.154.83.213
port: 24448
uuid: e31bc28e-8ebd-4d72-a98e-9227f26dfac3
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-KOR-Seoul-R-TCHK
server: 43.154.83.213
port: 24449
uuid: 7e27da0c-3013-4ed4-817b-50cc76a0bf81
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-JPN-Tokyo-R-TCHK
server: 43.154.83.213
port: 25000
uuid: c751811a-404f-4a05-bc41-5d572e741398
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-USA-Phoenix-R-TCHK
server: 43.154.83.213
port: 25001
uuid: fce2a9c6-1380-4ffa-ba84-6b9ec9ee2eea
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- type: vless
name: FV-USA-LosAngles
server: 43.154.83.213
port: 24450
uuid: 56fb312c-bdb0-48ca-bf66-4a2dd34040c6
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: book.107421.xyz
tls: true
udp: true
- name: CF_VIDEO_1
type: vless
server: bingo.pp.icederce.ip-ddns.com
port: 8443
uuid: 86c50e3a-5b87-49dd-bd20-03c7f2735e40
udp: false
tls: true
network: ws
servername: pp.icederce.ip-ddns.com
ws-opts:
path: "/?ed=2560"
headers:
Host: pp.icederce.ip-ddns.com
- name: CF_VIDEO_2
type: vless
server: bingo.icederce.ip-ddns.com
port: 8443
uuid: 86c50e3a-5b87-49dd-bd20-03c7f2735e40
udp: false
tls: true
network: ws
servername: pp.icederce.ip-ddns.com
ws-opts:
path: "/?ed=2560"
headers:
Host: pp.icederce.ip-ddns.com
- type: socks5
name: TC-CHN-Shanghai
server: 42.192.52.227
port: 22887
username: zeaslity
password: a1f090ea-e39c-49e7-a3be-9af26b6ce563
udp: true
- type: vless
name: Oracle-JPN-Tokyo-R-OSel
server: 140.238.14.103
port: 20443
uuid: 21dab95b-088e-47bd-8351-609fd23cb33c
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: xx.t2.ll.c0.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-JPN-Osaka-R-OSel
server: 140.238.14.103
port: 21443
uuid: 4c2dd763-56e5-408f-bc8f-dbf4c1fe41f9
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: xx.o1.vl.s4.107421.xyz
tls: true
udp: true
- type: vless
name: Oracle-USA-Phoneix-R-OSel
server: 140.238.14.103
port: 22443
uuid: de576486-e254-4d9d-949a-37088358ec23
skip-cert-verify: false
network: tcp
flow: xtls-rprx-vision
servername: xx.p2.vl.s4.107421.xyz
tls: true
udp: true
- { "type": "socks5","name": "onetools-35-71","server": "192.168.35.71","port": 22888,"username": "zeaslity","password": "password","udp": true }
proxy-groups:
- name: 🚀 节点选择
type: select
@@ -627,14 +362,18 @@ rules: # 1. 广告、追踪器拦截规则 (最高优先级)
# 直接拒绝连接,提升网页加载速度和隐私保护
- RULE-SET,reject,REJECT
# [新增] DNS服务器IP直连防止DNS请求走代理
- IP-CIDR,8.8.8.8/32,DIRECT,no-resolve
- IP-CIDR,8.8.4.4/32,DIRECT,no-resolve
- IP-CIDR,1.1.1.1/32,DIRECT,no-resolve
- IP-CIDR,1.0.0.1/32,DIRECT,no-resolve
- IP-CIDR,223.5.5.5/32,DIRECT,no-resolve
- IP-CIDR,119.29.29.29/32,DIRECT,no-resolve
# [优化] 核心国内流量直连规则 (IP 维度)
# 将中国大陆的 IP 地址段置于高优先级。这是解决国内网站访问缓慢和超时的关键。
# 任何目标地址在此列表内的连接都会被立即直连,无需进行 DNS 查询和 GEOIP 判断。
- RULE-SET,cncidr,DIRECT
- # 5. 基于地理位置的补充规则
- # 所有目标 IP 位于中国大陆的流量都直连
- # 这条规则作为对域名规则的补充,确保国内 IP 流量的直连
- GEOIP,CN,DIRECT
# 工作代理模式
- DOMAIN-SUFFIX,cdcyy.cn,💩 工作直连
@@ -661,6 +400,11 @@ rules: # 1. 广告、追踪器拦截规则 (最高优先级)
- RULE-SET,telegramcidr,📲 电报信息
- RULE-SET,proxy,🌍 国外媒体
- # 5. 基于地理位置的补充规则
- # 所有目标 IP 位于中国大陆的流量都直连
- # 这条规则作为对域名规则的补充,确保国内 IP 流量的直连
- GEOIP,CN,DIREC
# 6. 最终的兜底规则 (最低优先级)
# 所有未匹配到以上任何规则的流量,都走代理
# 这是确保未知的新网站或国外服务能正常访问的关键

View File

@@ -25,7 +25,9 @@
[TCP] dial 🎯 全球直连 (match RuleSet/direct) 127.0.0.1:56064 --> static.zhihu.com:443 error: dns resolve failed: context deadline exceeded
访问网址非常卡顿,请给出解决方案.考虑自建DNS服务器是否能够解决问题
请查阅clash的配置规格修改上述的配置文件要求对配置进行详细的中文注释说明。
请帮我分析上述的配置文件开启TUN模式开启DNS之后
日志出现大量的[UDP] dial 🐟 漏网之鱼 (match Match/) mihomo --> 1.1.1.1:53 error: new vless client error: context canceled错误
请分析出现的原因,给出解决办法

View File

@@ -0,0 +1,31 @@
你是一名精通LINUX服务器内核及网络参数调优的顶级专家熟练掌握XrayV2rayTrojan等各种前沿的代理软件代理协议
我现在中国境内需要避开GFW阻拦访问全球互联网现在有两台主机
1. 主机A位于香港
1. 可能存在审查等
2. 带宽为30Mbps
3. 直接访问其的网络质量良好
2. 主机B位于日本
1. 不存在审查等风险
2. 带宽为50Mbps
3. 直接访问网络限度堪忧,丢包率很严重
4. 从主机A访问主机B的网络质量目测还行
请实现如下的内容
1. 我直接访问主机A采用vless协议请分析vless协议是否实现速度和安全性的平衡。国内-主机A-主机B如何实现安全且高效的链式代理请寻找合适的代理协议
2.请实现脚本判定主机A到主机B之间往返之间的网络质量连接速度丢包率等需要在每天的不同时段执行然后输出一份综合性的报告。使用go或者shell实现自行寻找最合适的语言
3.请给出内核及网络优化参数使得主机A和主机B能够满足极致的转发性能减少代理的性能及时延损耗
你是一名优秀的go编程大师使用go语言实现一个主机A到主机B之间网络质量检测程序
1 真实代理延迟模拟真实TCP请求从主机A到主机B然后数据从主机B返回主机A的真实时延或者丢包情况
2 测试主机A到主机B的延迟测试主机B到主机A的延迟
3 测试主机A到主机B的丢包情况测试主机B到主机A的丢包情况,需要测试TCP及UDP丢包
4 [不强制]-针对上述延迟测试, 实现形式为类似tracerooute样式的路由追踪
5 需要定时执行,测试不同时间周期的网络质量,需要形成一份测试报告

View File

@@ -0,0 +1,42 @@
#!/bin/bash
# UFW 防火墙规则清除脚本
# 适用于 Ubuntu 22.04
# 检查是否以root权限运行
if [ "$EUID" -ne 0 ]; then
echo "请使用 sudo 运行此脚本"
exit 1
fi
echo "========================================="
echo "开始清除 UFW 防火墙规则"
echo "========================================="
# 1. 禁用UFW
echo ">>> 禁用 UFW 防火墙"
ufw disable
echo "执行: ufw disable"
# 2. 重置UFW到出厂默认状态删除所有规则
echo ">>> 重置 UFW 到出厂默认状态"
echo "y" | ufw reset
echo "执行: ufw reset"
# 3. 恢复默认策略
echo ">>> 恢复默认策略"
ufw default deny incoming
echo "执行: ufw default deny incoming"
ufw default allow outgoing
echo "执行: ufw default allow outgoing"
# 4. 显示当前状态
echo "========================================="
echo "UFW 防火墙规则已全部清除"
echo "当前状态:"
echo "========================================="
ufw status verbose
echo ""
echo "清除完成UFW 已禁用,所有自定义规则已删除"
echo "如需重新启用,请运行: sudo ufw enable"

View File

@@ -1,105 +1,90 @@
#!/bin/bash
#
# UFW 防火墙配置脚本
# 适用于 Ubuntu 22.04 LTS
#
# 适用于 Ubuntu 22.04
# --- 脚本开始 ---
# 检查是否以root权限运行
if [ "$EUID" -ne 0 ]; then
echo "请使用 sudo 运行此脚本"
exit 1
fi
echo "========================================="
echo "开始配置 UFW 防火墙规则"
echo "========================================="
# 1. 禁用UFW确保配置过程中不会被锁定
echo ">>> 临时禁用 UFW"
ufw disable
# 2. 重置UFW到默认状态清除所有现有规则
echo ">>> 重置 UFW 到默认状态"
echo "y" | ufw reset
# 3. 设置默认策略:允许所有出站流量,拒绝所有入站流量
echo ">>> 设置默认策略:允许出站,拒绝入站"
ufw default allow outgoing
echo "执行: ufw default allow outgoing"
ufw default deny incoming
echo "执行: ufw default deny incoming"
# 4. 允许白名单IP的所有流量入站方向
echo ">>> 添加白名单 IP 规则(允许所有端口和协议)"
echo "执行: ufw allow from 42.192.52.227/32"
ufw allow from 42.192.52.227/32
echo "执行: ufw allow from 43.154.83.213/32"
ufw allow from 43.154.83.213/32
echo "执行: ufw allow from 144.24.164.121/32"
ufw allow from 144.24.164.121/32
echo "执行: ufw allow from 132.145.87.10/32"
ufw allow from 132.145.87.10/32
echo "执行: ufw allow from 140.238.0.0/16"
ufw allow from 140.238.0.0/16
# 5. 允许公网访问指定端口TCP 和 UDP
echo ">>> 开放公网端口0.0.0.0/0"
echo "执行: ufw allow from 0.0.0.0/0 to any port 443 proto tcp"
ufw allow from 0.0.0.0/0 to any port 443 proto tcp
echo "执行: ufw allow from 0.0.0.0/0 to any port 443 proto udp"
ufw allow from 0.0.0.0/0 to any port 443 proto udp
echo "执行: ufw allow from 0.0.0.0/0 to any port 22333 proto tcp"
ufw allow from 0.0.0.0/0 to any port 22333 proto tcp
echo "执行: ufw allow from 0.0.0.0/0 to any port 22333 proto udp"
ufw allow from 0.0.0.0/0 to any port 22333 proto udp
echo "执行: ufw allow from 0.0.0.0/0 to any port 25000:26000 proto tcp"
ufw allow from 0.0.0.0/0 to any port 25000:26000 proto tcp
echo "执行: ufw allow from 0.0.0.0/0 to any port 25000:26000 proto udp"
ufw allow from 0.0.0.0/0 to any port 25000:26000 proto udp
# 6. 禁止非白名单IP的ICMP请求ping
echo ">>> 配置 ICMP 规则仅允许白名单IP"
echo "注意默认拒绝策略已经阻止非白名单的ICMP白名单IP可以ping"
# 7. 启用UFW
echo ">>> 启用 UFW 防火墙"
echo "y" | ufw enable
# 8. 显示当前规则
echo "========================================="
echo "UFW 防火墙配置完成!当前规则如下:"
echo "========================================="
ufw status verbose
# 输出提示信息,告知用户脚本即将开始
echo "================================================="
echo " UFW 防火墙自动配置脚本即将开始... "
echo "================================================="
echo ""
# --- 1. 重置 UFW ---
# 为了避免与旧规则冲突首先重置UFW到初始状态。
# --force 选项可以在没有交互提示的情况下完成重置。
echo "--- 步骤 1: 重置UFW防火墙清除所有现有规则 ---"
echo "执行命令: sudo ufw --force reset"
sudo ufw --force reset
echo "-------------------------------------------------"
echo ""
# --- 3. 开放特定端口 (对所有IP) ---
# 为公共服务开放指定的端口。
echo "--- 步骤 3: 向所有IP开放指定的TCP/UDP端口 ---"
# 开放 HTTPS (443) 端口
echo "开放端口: 443/tcp 和 443/udp"
echo "执行命令: sudo ufw allow 443"
sudo ufw allow 443
# 开放自定义 (22333) 端口
echo "开放端口: 22333/tcp 和 22333/udp"
echo "执行命令: sudo ufw allow 22333"
sudo ufw allow 22333
# 开放自定义 (25000-26000) 端口范围
echo "开放端口范围: 25000:26000/tcp"
echo "执行命令: sudo ufw allow 25000:26000/tcp"
sudo ufw allow 25000:26000/tcp
echo "开放端口范围: 25000:26000/udp"
echo "执行命令: sudo ufw allow 25000:26000/udp"
sudo ufw allow 25000:26000/udp
echo "-------------------------------------------------"
echo ""
# --- 4. 添加IP白名单 ---
# 为受信任的IP地址开放所有权限方便管理和访问。
echo "--- 步骤 4: 为白名单IP开放所有协议和端口 ---"
WHITELIST_IPS=(
"42.192.52.227/32"
"43.154.83.213/32"
"144.24.164.121/32"
"132.145.87.10/32"
"140.238.0.0/16"
)
# 遍历IP列表并添加规则
for ip in "${WHITELIST_IPS[@]}"; do
echo "添加白名单IP: ${ip}"
echo "执行命令: sudo ufw allow from ${ip} to any"
sudo ufw allow from ${ip} to any
done
echo "-------------------------------------------------"
echo ""
# --- 2. 设置默认策略 ---
# 这是防火墙的基础安全策略。
# deny incoming: 拒绝所有未经明确允许的进入流量。
# allow outgoing: 允许服务器主动发起的任何出站流量。
echo "--- 步骤 2: 设置默认防火墙策略 ---"
echo "设置默认拒绝所有进入流量..."
echo "执行命令: sudo ufw default deny incoming"
sudo ufw default deny incoming
echo "设置默认允许所有出口流量..."
echo "执行命令: sudo ufw default allow outgoing"
sudo ufw default allow outgoing
echo "-------------------------------------------------"
echo ""
# --- 5. ICMP (Ping) 请求处理 ---
# UFW的默认拒绝策略(deny incoming)已经包含了对ICMP的阻止。
# 而上一步的IP白名单规则(ufw allow from <IP>)允许了这些IP的所有协议因此它们可以ping通。
# 这精确地实现了“禁止非白名单IP的ICMP请求”的目标。
echo "--- 步骤 5: ICMP (Ping) 请求说明 ---"
echo "无需额外规则。默认的'deny incoming'策略已阻止非白名单IP的ping请求。"
echo "-------------------------------------------------"
echo ""
# --- 6. 启用 UFW ---
# 应用以上所有规则,正式启动防火墙。
echo "--- 步骤 6: 启用UFW防火墙 ---"
echo "执行命令: sudo ufw enable"
sudo ufw enable
echo "-------------------------------------------------"
echo ""
# --- 7. 显示最终状态 ---
# 显示详细的防火墙状态,以便用户检查配置是否正确。
echo "--- 步骤 7: 显示当前防火墙状态 ---"
echo "执行命令: sudo ufw status verbose"
sudo ufw status verbose
echo "-------------------------------------------------"
echo ""
echo "================================================="
echo " 防火墙配置完成!请检查上面的状态。 "
echo "================================================="
echo "配置总结:"
echo "- 出站流量:全部允许"
echo "- 入站流量:默认拒绝"
echo "- 开放端口443, 22333, 25000-26000 (TCP/UDP)"
echo "- 白名单IP42.192.52.227, 43.154.83.213, 144.24.164.121, 132.145.87.10, 140.238.0.0/16"
echo "- ICMP仅白名单IP可访问"

View File

@@ -2,13 +2,15 @@
你是一个精通ubuntu22.04系统下ufw使用的计算机高手请实现一个shell脚本实现如下的功能
- 所有的命令均有清晰的中文注释
- 所有执行的命令均使用echo进行打印输出
- 开放访问目的地端口为443 22333 25000-26000的tcp udp到0.0.0.0/0
- 对以下IP开放全部协议及端口
- 允许全部的流出方向流量
- 开放来源为0.0.0.0/0 流入本机的端口为443 22333 25000-26000的tcp udp流量
- 对以下IP的流入本机方向流量的全部协议及端口
- 42.192.52.227/32
- 43.154.83.213/32
- 144.24.164.121/32
- 132.145.87.10/32
- 140.238.0.0/16
- 禁止其他端口的访问流量
- 禁止其他端口的流入流量
- 禁止非白名单IP的ICMP请求
- 允许全部的出口流量
请同步写出清除上述所有规则的脚本

View File

@@ -0,0 +1,47 @@
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"protocol": "socks",
"listen": "0.0.0.0",
"port": 1234,
"settings": {
"auth": "noauth",
"udp": true,
"ip": "127.0.0.1",
"userLevel": 0
}
},
{
"listen": "0.0.0.0",
"port": 1235,
"protocol": "http",
"tag": "http-no-auth",
"settings": {
"timeout": 300
}
},
{
"listen": "0.0.0.0",
"port": 1236,
"protocol": "http",
"tag": "http-with-auth",
"settings": {
"accounts": [
{
"user": "zeaslity",
"pass": "loveff.22"
}
],
"timeout": 300
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}

View File

@@ -21,7 +21,7 @@ server {
server {
listen unix:/dev/shm/h1.sock proxy_protocol;
# listen 5001;
server_name bingo.107421.xyz;
server_name xx.l4.ca.bg.107421.xyz;
set_real_ip_from unix:;
real_ip_header proxy_protocol;
@@ -42,7 +42,7 @@ server {
set_real_ip_from unix:;
real_ip_header proxy_protocol;
server_name bingo.107421.xyz;
server_name xx.l4.ca.bg.107421.xyz;
# grpc settings
# grpc_read_timeout 1h;

View File

@@ -50,13 +50,13 @@ dns: # 启用 DNS 服务器
# Fake-IP 例外名单对于这些域名Clash 将返回其真实的 IP 地址
# 这对于一些无法处理 Fake-IP 的内网服务或特定应用至关重要
fake-ip-filter:
- localhost
- '*.lan'
- '*.local'
- '*.arpa'
- time.*.com
- ntp.*.com
- time.*.com
- +.market.xiaomi.com
- localhost.ptlogin2.qq.com
- '*.msftncsi.com'
- www.msftconnecttest.com
@@ -69,7 +69,6 @@ dns: # 启用 DNS 服务器
- 119.29.29.29
# [优化] 主 DNS 服务器列表 (国内,加密 DoH)
# 会与 Fallback DNS 并发请求,如果返回的 IP 是国内 IP则立即采用速度快
# 使用加密 DNS 替代传统 UDP DNS增强解析的稳定性和抗干扰性。
nameserver:
- 223.5.5.5 # 阿里云
- 180.76.76.76 # 百度DNS
@@ -80,11 +79,13 @@ dns: # 启用 DNS 服务器
# 用于解析国外域名。当主 DNS 返回国外 IP 时Clash 会认为可能被污染,
# 并采用 Fallback DNS 的解析结果,以确保准确性
fallback:
- https://dns.google/dns-query # Google DNS (DoH)
- https://dns.cloudflare.com/dns-query # Cloudflare DNS (DoH)
- https://dns.quad9.net/dns-query # IBM quad9
- https://dns.google.com/dns-query # Google DNS (DoH)
- https://dns.opendns.com/dns-query # CISCO OpenDNS
- https://dns.adguard-dns.com/dns-query # AdGuard DNS
- tls://8.8.8.8:853 # Google DoT (纯IP)
- tls://1.1.1.1:853 # Cloudflare DoT (纯IP)
- tls://8.8.4.4:853 # Google DNS (DoT)
# Fallback DNS 例外名单,匹配此列表的域名将只使用主 DNS 解析
fallback-filter:
@@ -120,15 +121,16 @@ dns: # 启用 DNS 服务器
prefer-h3: false
# DNS也遵循规则进行解析
respect-rules: false
# 代理的DNS解析地址
# [关键] 代理节点域名解析必须用纯IP的国内DNS
proxy-server-nameserver:
- 'https://dns.google/dns-query'
- 'https://1.1.1.1/dns-query'
- 223.5.5.5
- 119.29.29.29
# 直连模式下的DNS服务器
direct-nameserver:
- 223.5.5.5 # 阿里 DNS
- 192.168.78.39
- 119.29.29.29 # 腾讯 DNSPod
- 114.114.114.114 # 114 DNS
- 223.5.5.5 # 阿里 DNS
# 禁止远程调试
@@ -181,7 +183,7 @@ proxies:
- type: vless
name: BFC-LosAngles
server: 154.40.34.106
server: 45.143.128.143
port: 443
uuid: 302fbcb8-e096-46a1-906f-e879ec5ab0c5
skip-cert-verify: false
@@ -478,6 +480,10 @@ proxy-groups:
- Oracle-JPN-Tokyo-R-OSel
- Oracle-JPN-Osaka-R-OSel
- Oracle-USA-Phoneix-R-OSel
- name: 🛜 DNS
type: select
proxies:
- TC-HongKong
- name: 🌍 国外媒体
type: select
proxies:
@@ -627,14 +633,18 @@ rules: # 1. 广告、追踪器拦截规则 (最高优先级)
# 直接拒绝连接,提升网页加载速度和隐私保护
- RULE-SET,reject,REJECT
# [新增] DNS服务器IP直连防止DNS请求走代理
- IP-CIDR,8.8.8.8/32,DIRECT,no-resolve
- IP-CIDR,8.8.4.4/32,DIRECT,no-resolve
- IP-CIDR,1.1.1.1/32,DIRECT,no-resolve
- IP-CIDR,1.0.0.1/32,DIRECT,no-resolve
- IP-CIDR,223.5.5.5/32,DIRECT,no-resolve
- IP-CIDR,119.29.29.29/32,DIRECT,no-resolve
# [优化] 核心国内流量直连规则 (IP 维度)
# 将中国大陆的 IP 地址段置于高优先级。这是解决国内网站访问缓慢和超时的关键。
# 任何目标地址在此列表内的连接都会被立即直连,无需进行 DNS 查询和 GEOIP 判断。
- RULE-SET,cncidr,DIRECT
- # 5. 基于地理位置的补充规则
- # 所有目标 IP 位于中国大陆的流量都直连
- # 这条规则作为对域名规则的补充,确保国内 IP 流量的直连
- GEOIP,CN,DIRECT
# 工作代理模式
- DOMAIN-SUFFIX,cdcyy.cn,💩 工作直连
@@ -653,7 +663,6 @@ rules: # 1. 广告、追踪器拦截规则 (最高优先级)
# 优先匹配已知需要直连的域名和服务 (Apple, iCloud 等)
- RULE-SET,icloud,🍎 苹果服务
- RULE-SET,apple,🍎 苹果服务
- RULE-SET,direct,🎯 全球直连
# 4. 明确的代理规则
# 匹配已知需要代理的服务 (Google, Telegram, 以及其他国际服务)
@@ -661,6 +670,13 @@ rules: # 1. 广告、追踪器拦截规则 (最高优先级)
- RULE-SET,telegramcidr,📲 电报信息
- RULE-SET,proxy,🌍 国外媒体
- # 5. 基于地理位置的补充规则
- # 所有目标 IP 位于中国大陆的流量都直连
- # 这条规则作为对域名规则的补充,确保国内 IP 流量的直连
- GEOIP,CN,DIRECT
- RULE-SET,direct,🎯 全球直连
# 6. 最终的兜底规则 (最低优先级)
# 所有未匹配到以上任何规则的流量,都走代理
# 这是确保未知的新网站或国外服务能正常访问的关键

View File

@@ -1,5 +1,5 @@
vless://f8702759-f402-4e85-92a6-8540d577de22@43.154.83.213:24443?type=tcp&encryption=none&security=tls&path=%2f&flow=xtls-rprx-vision&sni=book.107421.xyz#TC-HongKong
vless://302fbcb8-e096-46a1-906f-e879ec5ab0c5@154.40.34.106:443?type=tcp&encryption=none&security=tls&path=%2f&flow=xtls-rprx-vision&sni=xx.l4.ca.bg.107421.xyz#BFC-LosAngles
vless://302fbcb8-e096-46a1-906f-e879ec5ab0c5@45.143.128.143:443?type=tcp&encryption=none&security=tls&path=%2f&flow=xtls-rprx-vision&sni=xx.l4.ca.bg.107421.xyz#BFC-LosAngles
vless://9fa9b4e7-d76d-4890-92cf-ce9251a76f59@43.154.83.213:24451?type=tcp&encryption=none&security=tls&path=%2f&flow=xtls-rprx-vision&sni=book.107421.xyz#Care-DEU-Dusseldorf-R-TCHK
vless://7e27da0c-3013-4ed4-817b-50cc76a0bf81@43.154.83.213:24449?type=tcp&encryption=none&security=tls&path=%2f&flow=xtls-rprx-vision&sni=book.107421.xyz#Oracle-KOR-Seoul-R-TCHK

View File

@@ -0,0 +1,55 @@
# ==========================================================
# 核心拥塞控制与队列管理 (解决丢包与延迟)
# ==========================================================
# 使用 FQ (Fair Queueing) 队列调度算法这是BBR的必要配合
net.core.default_qdisc = fq
# 开启 BBR 拥塞控制算法
net.ipv4.tcp_congestion_control = bbr
# ==========================================================
# TCP 缓冲区调优 (针对 30-50Mbps 带宽优化)
# ==========================================================
# 格式: min default max
# 核心策略:限制 max 值,防止 Bufferbloat。
# 2MB (2097152) 的缓冲区足以应对 50Mbps 下 300ms 的抖动,再大就会导致高延迟。
# 接收缓冲区
net.ipv4.tcp_rmem = 4096 87380 2097152
# 发送缓冲区
net.ipv4.tcp_wmem = 4096 65536 2097152
# 开启窗口缩放,允许窗口超过 64KB
net.ipv4.tcp_window_scaling = 1
# ==========================================================
# 连接追踪与并发优化 (Xray 高并发转发需求)
# ==========================================================
# 增加系统级文件描述符限制
fs.file-max = 1048576
# 增加入站连接队列长度,防止突发流量导致握手失败
net.core.somaxconn = 4096
net.core.netdev_max_backlog = 4096
# TCP Fast Open (TFO):减少握手延迟
# 值 3 表示同时开启客户端和服务端的 TFO 支持
# Xray 需要在配置中显式开启 "tcpFastOpen": true 才能生效
net.ipv4.tcp_fastopen = 3
# ==========================================================
# 抗丢包与快速恢复
# ==========================================================
# 开启 SACK (选择性确认),对丢包环境极其重要
net.ipv4.tcp_sack = 1
net.ipv4.tcp_dsack = 1
net.ipv4.tcp_fack = 1
# 缩短保活探测时间快速剔除死连接GFW常导致连接“假死”
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
# ==========================================================
# 转发功能开启 (主机A必须)
# ==========================================================
net.ipv4.ip_forward = 1

View File

@@ -0,0 +1,730 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"net"
"os"
"strings"
"sync"
"time"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
// ============ 通用数据结构 ============
type TestPacket struct {
SeqNum uint64
Timestamp int64
Type string // "tcp", "udp", "ping"
Data []byte
}
type Stats struct {
PacketsReceived uint64
PacketsLost uint64
LastSeqNum uint64
RTTSamples []time.Duration
}
type Metrics struct {
PacketsSent uint64
PacketsReceived uint64
PacketsLost uint64
RTTSamples []time.Duration
MinRTT time.Duration
MaxRTT time.Duration
AvgRTT time.Duration
Jitter time.Duration
}
type TestReport struct {
Timestamp time.Time
TestDuration time.Duration
TargetHost string
TCPMetrics *Metrics
UDPMetrics *Metrics
TracerouteHops []HopInfo
}
type HopInfo struct {
TTL int
Address string
RTT time.Duration
}
// ============ 服务端实现 ============
type NetworkServer struct {
tcpAddr string
udpAddr string
tcpStats *Stats
udpStats *Stats
statsLock sync.RWMutex
}
func NewNetworkServer(tcpPort, udpPort int) *NetworkServer {
return &NetworkServer{
tcpAddr: fmt.Sprintf(":%d", tcpPort),
udpAddr: fmt.Sprintf(":%d", udpPort),
tcpStats: &Stats{},
udpStats: &Stats{},
}
}
func (ns *NetworkServer) Start() {
log.Printf("========== 网络质量检测服务端 ==========")
log.Printf("TCP监听端口: %s", ns.tcpAddr)
log.Printf("UDP监听端口: %s", ns.udpAddr)
log.Printf("服务器已启动,等待客户端连接...")
log.Printf("========================================\n")
// 启动TCP服务器
go ns.serveTCP()
// 启动UDP服务器
go ns.serveUDP()
select {}
}
func (ns *NetworkServer) serveTCP() {
listener, err := net.Listen("tcp", ns.tcpAddr)
if err != nil {
log.Fatalf("TCP监听失败: %v", err)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("TCP连接接受错误: %v", err)
continue
}
go ns.handleTCPConnection(conn)
}
}
func (ns *NetworkServer) handleTCPConnection(conn net.Conn) {
defer conn.Close()
log.Printf("[TCP] 新连接来自 %s", conn.RemoteAddr())
buf := make([]byte, 8192)
for {
n, err := conn.Read(buf)
if err != nil {
log.Printf("[TCP] 连接 %s 断开", conn.RemoteAddr())
return
}
var packet TestPacket
if err := json.Unmarshal(buf[:n], &packet); err != nil {
continue
}
receiveTime := time.Now().UnixNano()
ns.updateStats(ns.tcpStats, packet.SeqNum)
// 立即回显数据包
response := TestPacket{
SeqNum: packet.SeqNum,
Timestamp: receiveTime,
Type: "tcp_response",
Data: packet.Data,
}
data, _ := json.Marshal(response)
conn.Write(data)
}
}
func (ns *NetworkServer) serveUDP() {
addr, err := net.ResolveUDPAddr("udp", ns.udpAddr)
if err != nil {
log.Fatalf("UDP地址解析失败: %v", err)
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
log.Fatalf("UDP监听失败: %v", err)
}
defer conn.Close()
log.Printf("[UDP] 监听在 %s", ns.udpAddr)
buf := make([]byte, 8192)
for {
n, remoteAddr, err := conn.ReadFromUDP(buf)
if err != nil {
log.Printf("UDP读取错误: %v", err)
continue
}
var packet TestPacket
if err := json.Unmarshal(buf[:n], &packet); err != nil {
continue
}
receiveTime := time.Now().UnixNano()
ns.updateStats(ns.udpStats, packet.SeqNum)
// 回显UDP数据包
response := TestPacket{
SeqNum: packet.SeqNum,
Timestamp: receiveTime,
Type: "udp_response",
Data: packet.Data,
}
data, _ := json.Marshal(response)
conn.WriteToUDP(data, remoteAddr)
}
}
func (ns *NetworkServer) updateStats(stats *Stats, seqNum uint64) {
ns.statsLock.Lock()
defer ns.statsLock.Unlock()
stats.PacketsReceived++
if seqNum > stats.LastSeqNum+1 {
stats.PacketsLost += seqNum - stats.LastSeqNum - 1
}
stats.LastSeqNum = seqNum
}
// ============ 客户端实现 ============
type NetworkClient struct {
targetHost string
tcpPort int
udpPort int
testDuration time.Duration
packetSize int
reportFile string
tcpMetrics *Metrics
udpMetrics *Metrics
mu sync.Mutex
}
func NewNetworkClient(host string, tcpPort, udpPort int, duration time.Duration) *NetworkClient {
return &NetworkClient{
targetHost: host,
tcpPort: tcpPort,
udpPort: udpPort,
testDuration: duration,
packetSize: 1024,
reportFile: "network_quality_report.json",
tcpMetrics: &Metrics{MinRTT: time.Hour},
udpMetrics: &Metrics{MinRTT: time.Hour},
}
}
func (nc *NetworkClient) testTCPLatency() error {
addr := fmt.Sprintf("%s:%d", nc.targetHost, nc.tcpPort)
conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil {
return fmt.Errorf("TCP连接失败: %v", err)
}
defer conn.Close()
log.Printf("[TCP] 开始延迟测试 -> %s", addr)
var seqNum uint64
deadline := time.Now().Add(nc.testDuration)
for time.Now().Before(deadline) {
seqNum++
packet := TestPacket{
SeqNum: seqNum,
Timestamp: time.Now().UnixNano(),
Type: "tcp_probe",
Data: make([]byte, nc.packetSize),
}
sendTime := time.Now()
data, _ := json.Marshal(packet)
if _, err := conn.Write(data); err != nil {
nc.mu.Lock()
nc.tcpMetrics.PacketsLost++
nc.mu.Unlock()
continue
}
nc.mu.Lock()
nc.tcpMetrics.PacketsSent++
nc.mu.Unlock()
buf := make([]byte, 8192)
conn.SetReadDeadline(time.Now().Add(2 * time.Second))
_, err := conn.Read(buf)
if err != nil {
nc.mu.Lock()
nc.tcpMetrics.PacketsLost++
nc.mu.Unlock()
continue
}
rtt := time.Since(sendTime)
nc.updateTCPMetrics(rtt)
time.Sleep(100 * time.Millisecond)
}
log.Printf("[TCP] 测试完成")
return nil
}
func (nc *NetworkClient) testUDPLatency() error {
addr := fmt.Sprintf("%s:%d", nc.targetHost, nc.udpPort)
raddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return fmt.Errorf("UDP地址解析失败: %v", err)
}
conn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
return fmt.Errorf("UDP连接失败: %v", err)
}
defer conn.Close()
log.Printf("[UDP] 开始延迟测试 -> %s", addr)
var seqNum uint64
deadline := time.Now().Add(nc.testDuration)
sentPackets := make(map[uint64]time.Time)
var wg sync.WaitGroup
// 发送协程
wg.Add(1)
go func() {
defer wg.Done()
for time.Now().Before(deadline) {
seqNum++
packet := TestPacket{
SeqNum: seqNum,
Timestamp: time.Now().UnixNano(),
Type: "udp_probe",
Data: make([]byte, nc.packetSize),
}
sendTime := time.Now()
nc.mu.Lock()
sentPackets[seqNum] = sendTime
nc.mu.Unlock()
data, _ := json.Marshal(packet)
conn.Write(data)
nc.mu.Lock()
nc.udpMetrics.PacketsSent++
nc.mu.Unlock()
time.Sleep(100 * time.Millisecond)
}
}()
// 接收协程
buf := make([]byte, 8192)
for time.Now().Before(deadline.Add(3 * time.Second)) {
conn.SetReadDeadline(time.Now().Add(1 * time.Second))
n, err := conn.Read(buf)
if err != nil {
continue
}
var response TestPacket
if err := json.Unmarshal(buf[:n], &response); err != nil {
continue
}
nc.mu.Lock()
if sendTime, ok := sentPackets[response.SeqNum]; ok {
rtt := time.Since(sendTime)
nc.updateUDPMetrics(rtt)
delete(sentPackets, response.SeqNum)
}
nc.mu.Unlock()
}
wg.Wait()
nc.mu.Lock()
nc.udpMetrics.PacketsLost = uint64(len(sentPackets))
nc.mu.Unlock()
log.Printf("[UDP] 测试完成")
return nil
}
func (nc *NetworkClient) performTraceroute() ([]HopInfo, error) {
log.Printf("[Traceroute] 路由追踪到 %s", nc.targetHost)
hops := make([]HopInfo, 0, 30)
maxTTL := 30
timeout := 2 * time.Second
for ttl := 1; ttl <= maxTTL; ttl++ {
hopInfo, reached, err := nc.probeHop(ttl, timeout)
if err != nil {
continue
}
hops = append(hops, hopInfo)
if hopInfo.Address != "*" {
log.Printf(" %2d %-15s %.2fms", ttl, hopInfo.Address,
float64(hopInfo.RTT.Microseconds())/1000.0)
} else {
log.Printf(" %2d *", ttl)
}
if reached {
break
}
}
return hops, nil
}
func (nc *NetworkClient) probeHop(ttl int, timeout time.Duration) (HopInfo, bool, error) {
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
return HopInfo{}, false, err
}
defer conn.Close()
if err := conn.IPv4PacketConn().SetTTL(ttl); err != nil {
return HopInfo{}, false, err
}
msg := icmp.Message{
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff,
Seq: ttl,
Data: []byte("TRACEROUTE"),
},
}
msgBytes, err := msg.Marshal(nil)
if err != nil {
return HopInfo{}, false, err
}
dst, err := net.ResolveIPAddr("ip4", nc.targetHost)
if err != nil {
return HopInfo{}, false, err
}
start := time.Now()
if _, err := conn.WriteTo(msgBytes, dst); err != nil {
return HopInfo{}, false, err
}
reply := make([]byte, 1500)
conn.SetReadDeadline(time.Now().Add(timeout))
_, peer, err := conn.ReadFrom(reply)
rtt := time.Since(start)
if err != nil {
return HopInfo{TTL: ttl, Address: "*", RTT: 0}, false, nil
}
hopAddr := peer.String()
reachedTarget := (hopAddr == dst.String())
return HopInfo{
TTL: ttl,
Address: hopAddr,
RTT: rtt,
}, reachedTarget, nil
}
func (nc *NetworkClient) updateTCPMetrics(rtt time.Duration) {
nc.mu.Lock()
defer nc.mu.Unlock()
nc.tcpMetrics.PacketsReceived++
nc.tcpMetrics.RTTSamples = append(nc.tcpMetrics.RTTSamples, rtt)
if rtt < nc.tcpMetrics.MinRTT {
nc.tcpMetrics.MinRTT = rtt
}
if rtt > nc.tcpMetrics.MaxRTT {
nc.tcpMetrics.MaxRTT = rtt
}
}
func (nc *NetworkClient) updateUDPMetrics(rtt time.Duration) {
nc.udpMetrics.PacketsReceived++
nc.udpMetrics.RTTSamples = append(nc.udpMetrics.RTTSamples, rtt)
if rtt < nc.udpMetrics.MinRTT {
nc.udpMetrics.MinRTT = rtt
}
if rtt > nc.udpMetrics.MaxRTT {
nc.udpMetrics.MaxRTT = rtt
}
}
func (nc *NetworkClient) calculateMetrics() {
// 计算TCP平均RTT和抖动
if len(nc.tcpMetrics.RTTSamples) > 0 {
var sum time.Duration
for _, rtt := range nc.tcpMetrics.RTTSamples {
sum += rtt
}
nc.tcpMetrics.AvgRTT = sum / time.Duration(len(nc.tcpMetrics.RTTSamples))
var jitterSum time.Duration
for i := 1; i < len(nc.tcpMetrics.RTTSamples); i++ {
diff := nc.tcpMetrics.RTTSamples[i] - nc.tcpMetrics.RTTSamples[i-1]
if diff < 0 {
diff = -diff
}
jitterSum += diff
}
if len(nc.tcpMetrics.RTTSamples) > 1 {
nc.tcpMetrics.Jitter = jitterSum / time.Duration(len(nc.tcpMetrics.RTTSamples)-1)
}
}
// 计算UDP平均RTT和抖动
if len(nc.udpMetrics.RTTSamples) > 0 {
var sum time.Duration
for _, rtt := range nc.udpMetrics.RTTSamples {
sum += rtt
}
nc.udpMetrics.AvgRTT = sum / time.Duration(len(nc.udpMetrics.RTTSamples))
var jitterSum time.Duration
for i := 1; i < len(nc.udpMetrics.RTTSamples); i++ {
diff := nc.udpMetrics.RTTSamples[i] - nc.udpMetrics.RTTSamples[i-1]
if diff < 0 {
diff = -diff
}
jitterSum += diff
}
if len(nc.udpMetrics.RTTSamples) > 1 {
nc.udpMetrics.Jitter = jitterSum / time.Duration(len(nc.udpMetrics.RTTSamples)-1)
}
}
}
func (nc *NetworkClient) generateReport(hops []HopInfo) error {
nc.calculateMetrics()
report := TestReport{
Timestamp: time.Now(),
TestDuration: nc.testDuration,
TargetHost: nc.targetHost,
TCPMetrics: nc.tcpMetrics,
UDPMetrics: nc.udpMetrics,
TracerouteHops: hops,
}
// 将报告序列化为JSON单行不格式化
data, err := json.Marshal(report)
if err != nil {
return err
}
// 以追加模式打开文件,如果不存在则创建
file, err := os.OpenFile(nc.reportFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return fmt.Errorf("打开报告文件失败: %v", err)
}
defer file.Close()
// 写入JSON数据并添加换行符JSON Lines格式
if _, err := file.Write(data); err != nil {
return fmt.Errorf("写入报告数据失败: %v", err)
}
if _, err := file.WriteString("\n"); err != nil {
return fmt.Errorf("写入换行符失败: %v", err)
}
log.Printf("测试报告已追加至: %s", nc.reportFile)
nc.printReport(&report)
return nil
}
func (nc *NetworkClient) printReport(report *TestReport) {
fmt.Println("\n" + strings.Repeat("=", 50))
fmt.Println(" 网络质量检测报告")
fmt.Println(strings.Repeat("=", 50))
fmt.Printf("测试时间: %s\n", report.Timestamp.Format("2006-01-02 15:04:05"))
fmt.Printf("目标主机: %s\n", report.TargetHost)
fmt.Printf("测试时长: %v\n", report.TestDuration)
fmt.Println(strings.Repeat("-", 50))
fmt.Println("\n【TCP 测试结果】")
fmt.Printf(" 发送包数: %d\n", report.TCPMetrics.PacketsSent)
fmt.Printf(" 接收包数: %d\n", report.TCPMetrics.PacketsReceived)
if report.TCPMetrics.PacketsSent > 0 {
lossRate := float64(report.TCPMetrics.PacketsLost) / float64(report.TCPMetrics.PacketsSent) * 100
fmt.Printf(" 丢包数量: %d (丢包率: %.2f%%)\n", report.TCPMetrics.PacketsLost, lossRate)
}
if report.TCPMetrics.MinRTT < time.Hour {
fmt.Printf(" 最小RTT: %v\n", report.TCPMetrics.MinRTT)
fmt.Printf(" 平均RTT: %v\n", report.TCPMetrics.AvgRTT)
fmt.Printf(" 最大RTT: %v\n", report.TCPMetrics.MaxRTT)
fmt.Printf(" 抖动: %v\n", report.TCPMetrics.Jitter)
}
fmt.Println("\n【UDP 测试结果】")
fmt.Printf(" 发送包数: %d\n", report.UDPMetrics.PacketsSent)
fmt.Printf(" 接收包数: %d\n", report.UDPMetrics.PacketsReceived)
if report.UDPMetrics.PacketsSent > 0 {
lossRate := float64(report.UDPMetrics.PacketsLost) / float64(report.UDPMetrics.PacketsSent) * 100
fmt.Printf(" 丢包数量: %d (丢包率: %.2f%%)\n", report.UDPMetrics.PacketsLost, lossRate)
}
if report.UDPMetrics.MinRTT < time.Hour {
fmt.Printf(" 最小RTT: %v\n", report.UDPMetrics.MinRTT)
fmt.Printf(" 平均RTT: %v\n", report.UDPMetrics.AvgRTT)
fmt.Printf(" 最大RTT: %v\n", report.UDPMetrics.MaxRTT)
fmt.Printf(" 抖动: %v\n", report.UDPMetrics.Jitter)
}
fmt.Println(strings.Repeat("=", 50))
fmt.Printf("报告已保存至: %s\n\n", nc.reportFile)
}
func (nc *NetworkClient) RunScheduledTests(interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
log.Printf("\n========== 开始定时测试 [%s] ==========",
time.Now().Format("2006-01-02 15:04:05"))
// 执行TCP测试
if err := nc.testTCPLatency(); err != nil {
log.Printf("TCP测试错误: %v", err)
}
// 重置UDP指标
nc.mu.Lock()
nc.udpMetrics = &Metrics{MinRTT: time.Hour}
nc.mu.Unlock()
// 执行UDP测试
if err := nc.testUDPLatency(); err != nil {
log.Printf("UDP测试错误: %v", err)
}
// 执行Traceroute
hops, err := nc.performTraceroute()
if err != nil {
log.Printf("Traceroute错误: %v", err)
}
// 生成报告
if err := nc.generateReport(hops); err != nil {
log.Printf("报告生成错误: %v", err)
}
// 重置TCP指标准备下一轮
nc.mu.Lock()
nc.tcpMetrics = &Metrics{MinRTT: time.Hour}
nc.mu.Unlock()
log.Printf("========== 测试完成,等待下一轮 ==========\n")
<-ticker.C
}
}
// ============ 主程序 ============
func main() {
// 定义命令行参数
var (
mode = flag.String("mode", "", "运行模式: server(服务端) 或 client(客户端)")
tcpPort = flag.Int("tcp", 9001, "TCP测试端口")
udpPort = flag.Int("udp", 9002, "UDP测试端口")
targetHost = flag.String("target", "", "目标主机地址(客户端模式必需)")
testDuration = flag.Int("duration", 60, "单次测试时长(秒)")
interval = flag.Int("interval", 3600, "定时测试间隔(秒), 0表示只执行一次")
)
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "\n网络质量检测工具\n\n")
fmt.Fprintf(os.Stderr, "用法:\n")
fmt.Fprintf(os.Stderr, " 服务端模式: %s -mode server [-tcp 端口] [-udp 端口]\n", os.Args[0])
fmt.Fprintf(os.Stderr, " 客户端模式: %s -mode client -target 目标IP [-tcp 端口] [-udp 端口] [-duration 秒] [-interval 秒]\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, "参数说明:\n")
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\n示例:\n")
fmt.Fprintf(os.Stderr, " # 启动服务端,使用默认端口\n")
fmt.Fprintf(os.Stderr, " %s -mode server\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, " # 启动服务端,自定义端口\n")
fmt.Fprintf(os.Stderr, " %s -mode server -tcp 8001 -udp 8002\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, " # 启动客户端单次测试60秒\n")
fmt.Fprintf(os.Stderr, " %s -mode client -target 192.168.1.100 -duration 60 -interval 0\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, " # 启动客户端,每小时测试一次\n")
fmt.Fprintf(os.Stderr, " %s -mode client -target 192.168.1.100 -interval 3600\n\n", os.Args[0])
}
flag.Parse()
// 验证参数
if *mode == "" {
fmt.Fprintf(os.Stderr, "错误: 必须指定运行模式 -mode server 或 -mode client\n\n")
flag.Usage()
os.Exit(1)
}
switch *mode {
case "server":
// 服务端模式
server := NewNetworkServer(*tcpPort, *udpPort)
server.Start()
case "client":
// 客户端模式
if *targetHost == "" {
fmt.Fprintf(os.Stderr, "错误: 客户端模式必须指定 -target 参数\n\n")
flag.Usage()
os.Exit(1)
}
client := NewNetworkClient(*targetHost, *tcpPort, *udpPort, time.Duration(*testDuration)*time.Second)
if *interval == 0 {
// 单次执行
log.Printf("开始单次网络质量测试...")
if err := client.testTCPLatency(); err != nil {
log.Printf("TCP测试错误: %v", err)
}
if err := client.testUDPLatency(); err != nil {
log.Printf("UDP测试错误: %v", err)
}
hops, err := client.performTraceroute()
if err != nil {
log.Printf("Traceroute错误: %v", err)
}
if err := client.generateReport(hops); err != nil {
log.Printf("报告生成错误: %v", err)
}
} else {
// 定时执行
log.Printf("开始定时网络质量监控,间隔: %d秒", *interval)
client.RunScheduledTests(time.Duration(*interval) * time.Second)
}
default:
fmt.Fprintf(os.Stderr, "错误: 无效的运行模式 '%s',必须是 'server' 或 'client'\n\n", *mode)
flag.Usage()
os.Exit(1)
}
}

View File

@@ -0,0 +1,407 @@
package main
//
//import (
// "encoding/binary"
// "encoding/json"
// "flag"
// "fmt"
// "io"
// "log"
// "net"
// "os"
// "sync"
// "time"
//)
//
//// 配置常量
//const (
// ProtocolTCP = "tcp"
// ProtocolUDP = "udp"
// PacketSize = 64 // 探测包大小
// LossTestCount = 20 // 每次丢包测试发送的数据包数量
// TraceMaxTTL = 30 // 路由追踪最大跳数
// ReportFileName = "network_quality_report.log"
//)
//
//// 命令行参数
//var (
// mode = flag.String("mode", "client", "运行模式: server 或 client")
// targetIP = flag.String("target", "127.0.0.1", "目标IP地址 (客户端模式填写服务端的IP)")
// tcpPort = flag.String("tcp-port", "8080", "TCP监听/连接端口")
// udpPort = flag.String("udp-port", "8081", "UDP监听/连接端口")
// interval = flag.Int("interval", 10, "测试间隔时间(秒)")
// doTrace = flag.Bool("trace", false, "是否执行路由追踪 (可能较慢)")
//)
//
//// TestResult 单次测试结果报告
//type TestResult struct {
// Timestamp string `json:"timestamp"`
// Target string `json:"target"`
// TCPLatencyMs float64 `json:"tcp_latency_ms"` // TCP 往返时延
// TCPJitterMs float64 `json:"tcp_jitter_ms"` // 抖动
// LossRateAtoB float64 `json:"loss_rate_a_to_b"` // A到B丢包率 0.0 - 1.0
// LossRateBtoA float64 `json:"loss_rate_b_to_a"` // B到A丢包率 0.0 - 1.0 (模拟)
// TraceRoute []string `json:"traceroute,omitempty"` // 路由路径
//}
//
//// Global logger
//var logger *log.Logger
//
//// C:\Users\wddsh\go\bin\gox.exe -osarch="linux/amd64" -output "build/agent-wdd_{{.OS}}_{{.Arch}}"
//// rm -rf netmonitor_linux_amd64
//// chmod +x netmonitor_linux_amd64 && ./netmonitor_linux_amd64 version
//
//// arm64
//// C:\Users\wddsh\go\bin\gox.exe -osarch="linux/arm64" -output "build/netmonitor_{{.OS}}_{{.Arch}}"
//func main() {
// flag.Parse()
//
// // 初始化日志
// file, err := os.OpenFile(ReportFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// if err != nil {
// fmt.Printf("无法创建日志文件: %v\n", err)
// return
// }
// defer file.Close()
//
// // 同时输出到控制台和文件
// multiWriter := io.MultiWriter(os.Stdout, file)
// logger = log.New(multiWriter, "", log.LstdFlags)
//
// if *mode == "server" {
// runServer()
// } else {
// runClient()
// }
//}
//
//// ======================= 服务端逻辑 (Host B) =======================
//
//func runServer() {
// logger.Println("=== 启动主机 B (Server Mode) ===")
// var wg sync.WaitGroup
// wg.Add(2)
//
// // 1. 启动 TCP Echo Server (用于延迟测试和信令)
// go func() {
// defer wg.Done()
// addr := fmt.Sprintf("0.0.0.0:%s", *tcpPort)
// listener, err := net.Listen(ProtocolTCP, addr)
// if err != nil {
// logger.Fatalf("TCP 监听失败: %v", err)
// }
// logger.Printf("TCP 服务监听中: %s", addr)
//
// for {
// conn, err := listener.Accept()
// if err != nil {
// continue
// }
// go handleTCPConnection(conn)
// }
// }()
//
// // 2. 启动 UDP Server (用于丢包测试)
// go func() {
// defer wg.Done()
// addr := fmt.Sprintf("0.0.0.0:%s", *udpPort)
// udpAddr, err := net.ResolveUDPAddr(ProtocolUDP, addr)
// if err != nil {
// logger.Fatalf("UDP 地址解析失败: %v", err)
// }
// conn, err := net.ListenUDP(ProtocolUDP, udpAddr)
// if err != nil {
// logger.Fatalf("UDP 监听失败: %v", err)
// }
// logger.Printf("UDP 服务监听中: %s", addr)
// handleUDPConnection(conn)
// }()
//
// wg.Wait()
//}
//
//func handleTCPConnection(conn net.Conn) {
// defer conn.Close()
// // 简单的 Echo 服务:收到什么发回什么
// // 这样客户端可以通过计算发送时间和接收时间的差值来算出 RTT
// buf := make([]byte, 1024)
// for {
// conn.SetReadDeadline(time.Now().Add(5 * time.Second))
// n, err := conn.Read(buf)
// if err != nil {
// return
// }
// // 原样写回
// conn.Write(buf[:n])
// }
//}
//
//func handleUDPConnection(conn *net.UDPConn) {
// // UDP 处理逻辑:
// // 1. 接收客户端发来的包(统计 A->B 丢包)
// // 2. 收到特定的 "PONG_REQUEST" 指令后,向客户端反向发送一组包(用于 B->A 测试)
//
// buf := make([]byte, 1024)
// for {
// n, remoteAddr, err := conn.ReadFromUDP(buf)
// if err != nil {
// continue
// }
//
// data := string(buf[:n])
//
// // 如果收到的是反向测试请求
// if data == "TEST_B_TO_A" {
// go sendUDPBurst(conn, remoteAddr)
// }
// // 否则只是接收用于客户端计算发送成功率或者服务端不做处理完全由客户端通过TCP信令协调
// // 在本简化模型中我们采用Echo模式来计算UDP RTT丢包或者单向接收
// // 为了实现"B到A丢包",我们使用上面的 TEST_B_TO_A 触发器
// }
//}
//
//func sendUDPBurst(conn *net.UDPConn, addr *net.UDPAddr) {
// // 向客户端反向发送数据包
// for i := 0; i < LossTestCount; i++ {
// msg := []byte(fmt.Sprintf("SEQ:%d", i))
// conn.WriteToUDP(msg, addr)
// time.Sleep(10 * time.Millisecond) // 发送间隔,防止本地拥塞
// }
//}
//
//// ======================= 客户端逻辑 (Host A) =======================
//
//func runClient() {
// logger.Println("=== 启动主机 A (Client Mode) ===")
// logger.Printf("目标主机: %s, 周期: %d秒", *targetIP, *interval)
//
// ticker := time.NewTicker(time.Duration(*interval) * time.Second)
// defer ticker.Stop()
//
// // 立即执行一次
// performTest()
//
// for range ticker.C {
// performTest()
// }
//}
//
//func performTest() {
// result := TestResult{
// Timestamp: time.Now().Format("2006-01-02 15:04:05"),
// Target: *targetIP,
// }
//
// logger.Println("------------------------------------------------")
// logger.Printf("[%s] 开始新一轮测试...", result.Timestamp)
//
// // 1. 测试 TCP 延迟 (RTT)
// latency, jitter, err := testTCPLatency(*targetIP + ":" + *tcpPort)
// if err != nil {
// logger.Printf("TCP 连接失败: %v", err)
// } else {
// result.TCPLatencyMs = latency
// result.TCPJitterMs = jitter
// logger.Printf("TCP 延迟: %.2f ms, 抖动: %.2f ms", latency, jitter)
// }
//
// // 2. 测试 丢包率 (双向)
// // 注意:为了精确测试 B->A我们需要 B 配合发送
// lossA2B, lossB2A, err := testPacketLoss(*targetIP + ":" + *udpPort)
// if err != nil {
// logger.Printf("UDP 测试失败: %v", err)
// } else {
// result.LossRateAtoB = lossA2B
// result.LossRateBtoA = lossB2A
// logger.Printf("丢包率 A->B: %.1f%%, B->A: %.1f%%", lossA2B*100, lossB2A*100)
// }
//
// // 3. (可选) 路由追踪
// if *doTrace {
// route := performTraceRoute(*targetIP, *tcpPort)
// result.TraceRoute = route
// logger.Println("路由追踪完成")
// }
//
// // 4. 保存报告
// saveReport(result)
//}
//
//// testTCPLatency 发送多次 TCP 请求计算平均 RTT 和抖动
//func testTCPLatency(address string) (float64, float64, error) {
// conn, err := net.DialTimeout(ProtocolTCP, address, 3*time.Second)
// if err != nil {
// return 0, 0, err
// }
// defer conn.Close()
//
// var rtts []float64
// count := 5 // 测试5次取平均
//
// payload := []byte("PING_PAYLOAD_DATA_CHECK_LATENCY")
// buf := make([]byte, 1024)
//
// for i := 0; i < count; i++ {
// start := time.Now()
//
// _, err := conn.Write(payload)
// if err != nil {
// return 0, 0, err
// }
//
// conn.SetReadDeadline(time.Now().Add(2 * time.Second))
// _, err = conn.Read(buf)
// if err != nil {
// return 0, 0, err
// }
//
// rtt := float64(time.Since(start).Microseconds()) / 1000.0 // ms
// rtts = append(rtts, rtt)
// time.Sleep(100 * time.Millisecond)
// }
//
// // 计算平均值
// var sum float64
// for _, v := range rtts {
// sum += v
// }
// avg := sum / float64(len(rtts))
//
// // 计算抖动 (标准差 或 平均偏差)
// var varianceSum float64
// for _, v := range rtts {
// diff := v - avg
// varianceSum += diff * diff
// }
// jitter := varianceSum / float64(len(rtts)) // 简单方差作为抖动参考
//
// return avg, jitter, nil
//}
//
//// testPacketLoss 测试 UDP 丢包
//func testPacketLoss(address string) (float64, float64, error) {
// udpAddr, err := net.ResolveUDPAddr(ProtocolUDP, address)
// if err != nil {
// return 0, 0, err
// }
// conn, err := net.DialUDP(ProtocolUDP, nil, udpAddr)
// if err != nil {
// return 0, 0, err
// }
// defer conn.Close()
//
// // --- A -> B 测试 ---
// // 客户端发送 N 个包,我们假设如果服务端不报错且网络通畅,这里主要测试发送端的出口和路径
// // 严格的 A->B 需要服务端计数并通过 TCP 返回结果。
// // 这里简化逻辑:我们使用 "Echo" 模式来近似 A->B->A 的丢包,或者依赖应用层超时。
// // 但为了满足"双向"需求,我们采用以下策略:
//
// // 1. 发送触发指令,让 B 发数据给 A (测试 B->A)
// // 先开启监听准备接收
// localListener, err := net.ListenUDP(ProtocolUDP, nil) // 随机端口
// if err != nil {
// return 0, 0, fmt.Errorf("无法开启本地 UDP 监听: %v", err)
// }
// defer localListener.Close()
//
// // 告诉服务器:请发包给我 (TEST_B_TO_A)
// // 注意:由于 NAT 存在,服务器直接回发可能需要打洞。
// // 这里假设 A 和 B 之间是连通的(如专线或公网 IP直接发给原来的连接通常可行
// _, err = conn.Write([]byte("TEST_B_TO_A"))
// if err != nil {
// return 0, 0, err
// }
//
// // 接收 B 发来的包
// //receivedCountBtoA := 0
// localListener.SetReadDeadline(time.Now().Add(2 * time.Second))
// readBuf := make([]byte, 1024)
//
// // 快速循环读取
// startTime := time.Now()
// for time.Since(startTime) < 2*time.Second {
// // 这里有个技巧:真正的 P2P UDP 穿透较复杂。
// // 在此我们假设复用 conn 对象读取(如果这是 Connected UDP
// // 或者 B 发回给 conn 的源端口。
// // 简单起见,我们复用 conn 来读取 echo (如果 B 是 echo server) 或者 trigger result.
// // **修正策略**:为了保证代码极简且能跑,我们将 B 设计为:收到什么回什么 (Echo)。
// // 丢包率 = (发送总数 - 接收回显总数) / 发送总数
// // 这计算的是 A->B->A 的总丢包。
// // 如果必须拆分 A->B 和 B->A需要复杂的序列号协议。
//
// // 让我们回退到最稳健的 Echo 模式测试总丢包率,并在报告中标记为 "RTT Packet Loss"
// // 这通常足够反映链路质量。
// break
// }
//
// // --- 重新实现的稳健丢包测试 (基于 Echo) ---
// // 发送 Count 个包,看收回多少个
// successCount := 0
// for i := 0; i < LossTestCount; i++ {
// seqMsg := []byte(fmt.Sprintf("SEQ:%d", i))
// _, err := conn.Write(seqMsg)
// if err == nil {
// conn.SetReadDeadline(time.Now().Add(200 * time.Millisecond))
// n, _, err := conn.ReadFromUDP(readBuf)
// // 如果 B 实现了 TEST_B_TO_A 的特殊逻辑,这里可能会冲突。
// // 所以我们在 B 端代码里,对于非指令包,应该不回或者回显。
// // 修改 B 端:如果不是 "TEST_B_TO_A",则不做操作(单向) 或者 回显(RTT)。
// // 为了代码简单有效:我们假定 B->A 丢包率 ≈ A->B 丢包率 ≈ (1 - RTT回包率)/2
// if err == nil && n > 0 {
// successCount++
// }
// }
// time.Sleep(10 * time.Millisecond)
// }
//
// lossRate := 1.0 - (float64(successCount) / float64(LossTestCount))
//
// // 在简单 UDP 模型下A->B 和 B->A 往往是对称的,或者难以区分。
// // 这里我们将结果同时赋值给两者,代表链路质量
// return lossRate, lossRate, nil
//}
//
//// performTraceRoute 应用层简易路由追踪
//func performTraceRoute(target string, port string) []string {
// var hops []string
//
// // 真正的 traceroute 需要构造 IP 包并修改 TTL (需要 root 权限)。
// // 此处实现一个 "伪" traceroute 占位符,
// // 或者如果环境允许,可以调用系统命令。
// // 为了保持 Go 程序独立性,这里只做简单的连通性检查并记录。
// // 注意:非 Root 无法设置 socket IP_TTL 选项在某些系统上。
//
// hops = append(hops, "Traceroute 需要 Raw Socket 权限,在此模式下仅显示端到端跳跃")
// hops = append(hops, fmt.Sprintf("1. Local -> %s:%s (Direct/NAT)", target, port))
//
// return hops
//}
//
//func saveReport(result TestResult) {
// data, err := json.Marshal(result)
// if err != nil {
// logger.Printf("JSON 序列化失败: %v", err)
// return
// }
// // 写入文件JSON Lines 格式
// logger.Println("保存报告到文件...")
// // logger 已经配置了 MultiWriter所以上面的输出已经写入文件了
// // 这里我们只把纯 JSON 再次追加进去以便机器读取?
// // 为了避免日志混乱,建议只保留日志形式的报告。
// // 或者我们可以专门写一个 data 文件。
//
// f, err := os.OpenFile("net_report_data.jsonl", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// if err == nil {
// defer f.Close()
// f.Write(data)
// f.WriteString("\n")
// }
//}
//
//// 辅助工具Int 转 Bytes
//func itob(v int) []byte {
// b := make([]byte, 8)
// binary.BigEndian.PutUint64(b, uint64(v))
// return b
//}

View File

@@ -0,0 +1,50 @@
go build -o netmonitor net_quality_monitor.go
#### 2. 部署与运行
**第一步:在主机 B 上启动服务端**
服务端将监听 TCP 28080 和 UDP 28081 端口,等待 A 的连接。
```bash
# Linux/Mac
./netmonitor -mode server -tcp 28080 -udp 28081
**第二步:在主机 A 上启动客户端**
客户端将每隔 5 秒测试一次到 140.238.52.228 的网络质量。
```bash
# 开启测试
./netmonitor -mode client -target 140.238.52.228 -tcp 28080 -udp 28081 -duration 10 -interval 60
# 德国
./netmonitor -mode client -target 43.154.83.213 -tcp 28080 -udp 28081 -duration 15 -interval 600
### 功能特点详解
1. **真实 TCP 交互**
* 代码中的 `testTCPLatency` 函数不使用 ICMP Ping而是通过 `net.DialTimeout` 建立完整的三次握手,并发送 Payload 数据。服务端接收并回写Echo
* 计算的时间包含了:`TCP握手时间` + `数据传输时间` + `ACK时间`。这比普通的 Ping 更能反映应用程序(如 HTTP/RPC的真实感受。
2. **UDP 丢包监测**
* `testPacketLoss` 采用 UDP 协议。UDP 是无连接的,不保证到达。
* 客户端连续快速发送 `LossTestCount` (默认20个) 包。如果接收端Echo模式下没有及时返回则判定为丢包。
* 这种方法能有效检测线路拥塞或防火墙限流情况。
3. **定时与报告**
* 程序使用 `time.Ticker` 保证精准的执行周期。
* 结果会同时输出到 **控制台** 和 **net_quality_report.log**。
* 另外生成 **net_report_data.jsonl**,每行一个 JSON 对象,方便后续通过脚本(如 Python/ELK进行图表分析。
4. **关于 Traceroute 的说明**
* 我在代码中预留了 `TraceRoute` 接口。
* *注意*:在 Go 语言中实现真正的 Traceroute修改 TTL需要引入 `golang.org/x/net/ipv4` 包并使用 Raw Socket这要求程序必须以 **root/管理员** 权限运行。为了保持代码作为一个简洁的“单文件”工具,且能保证在普通用户权限下运行,我没有包含 Raw Socket 代码。目前的实现是应用层层面的连通性检查。
### 报告样本
日志文件 (`net_report_data.jsonl`) 内容示例:
```json
{"timestamp":"2023-10-27 10:00:00","target":"192.168.1.200","tcp_latency_ms":12.5,"tcp_jitter_ms":1.2,"loss_rate_a_to_b":0.0,"loss_rate_b_to_a":0.0}
{"timestamp":"2023-10-27 10:00:10","target":"192.168.1.200","tcp_latency_ms":12.8,"tcp_jitter_ms":0.9,"loss_rate_a_to_b":0.05,"loss_rate_b_to_a":0.05}
你可以直接用 Excel 或 Python 读取这个文件来生成网络质量波动图。

View File

@@ -46,7 +46,7 @@ ff02::2 ip6-allrouters
42.192.52.227 tc-sh
43.128.39.232 tc-hk
43.154.83.213 tc-hk
114.117.165.222 tc-cd