惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
小众软件
小众软件
MongoDB | Blog
MongoDB | Blog
Hugging Face - Blog
Hugging Face - Blog
Jina AI
Jina AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
量子位
A
About on SuperTechFans
G
Google Developers Blog
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research

SQYBI.com Blog

已经崩溃的舆论战场不值得被总结 关于 Quote/0 的那些你在购买前还不知道的特性 从工位牛马到海中人鱼:马尔代夫的大续命术 国航第二架 C919 乘坐体验 独特性和一周年的自我 让 Docusaurus 变得更好:SQYBI.com 上线评论系统 Docusaurus 的近期更新 成为优秀的程序员(02):管理的目的 适配 macOS 系统的机械键盘 小米 14 Ultra 摄影相关的高强度使用体验总结 索尼相机的终极伴侣:Monitor+ 成为优秀的程序员(01):理解“不理解” 从拍照到摄影(02):相机的其它基础参数和进阶影响 从拍照到摄影(01):相机的基础参数 2024 新年快乐! 沉浸式翻译:优秀的浏览器翻译插件 为什么 Linksys VELOP 路由器不适合旁路网关 带着路书去旅行 摄影故事:母亲、孩子、尾迹
解决 Openwrt 上 HomeProxy 插件不支持 Hysteria2 Port Hoppi...
sqybi · 2024-03-06 · via SQYBI.com Blog

随手记录一些比较短的问题解决方案:

Openwrt 上 HomeProxy 的 sing-box 不支持 Hysteria2 port hopping?不如自己来 hop 吧!

背景

Hysteria2 是一种基于 UDP 的代理方案。

因为国内运营商大多对 UDP 的流量进行了管控(UDP QoS),所以如果长期连接某个特定的端口发送大量 UDP 包,很容易导致后续到这个端口的 UDP 包都会被运营商直接丢弃。

Hysteria 的客户端自带了 port hopping 功能,即可以输入一个或多个端口段,由客户端自行在一定时间之后重新连接一个新的端口。

但我在使用的 OpenWrt (ImmortalWrt) 中 HomeProxy 插件是基于 sing-box 的,可惜的是 sing-box 并没有支持 Hysteria2 协议的 port hopping 特性,且根据 issues 中的讨论,今后也没有支持的打算。

我们只好自己动手丰衣足食,写一段自动更换端口的脚本。

服务端配置

根据 Hysteria2 官方文档 中的说明,即使是官方服务端也是不支持配置多端口监听的。这是因为 iptables / nftables 可以简单地通过配置 DNAT 完成同样的功能。

其中iptables 配置如下,如果你的服务端系统已经升级到了 nftables 也可以自行查阅上述文档中的配置方法:

iptables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:29999 -j DNAT --to-destination :443
ip6tables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:29999 -j DNAT --to-destination :443

这里的 20000 - 29999 是 port hopping 功能监听的端口段,后续客户端配置需要对应这一段端口号;443 是 Hysteria2 自身监听的端口。

同时,需要注意 iptables 的配置会在重启后失效,可以使用 netfilter-persistent 来持久化配置。

首先安装 netfilter-persistent

apt install iptables-persistent

理论上如果在安装之前你已经完成了 iptables 配置,那么对应的配置文件就已经被持久化且保存在 /etc/iptables/rules.v4/etc/iptables/rules.v6 中了。

如果没有也没关系,可以执行 iptables-save > /etc/iptables/rules.v4iptables-save > /etc/iptables/rules.v6 手动保存。每次重启的时候,systemctl 的服务 netfilter-persistent.service 都会自动加载这些配置。

客户端配置

客户端则要麻烦一些,推荐使用下列脚本自动执行端口更换操作,模仿 port hopping 的效果。

脚本的开始首先配置了对应服务器配置的端口信息,其中 PORT_STARTING 为起始端口,PORT_RANGE 为端口段的长度。

接下来会尝试最多五次通过 curl google.com 检查网络可达性,注意 HomeProxy 是没有代理 ICMP 协议的,所以这里不要使用 ping,否则可能会失败。

如果五次中有任何一次成功,则意味着端口依然可用,直接退出脚本;如果五次全部失败,则认为端口已经不可用,需要更换端口。

更换端口的方式则是通过 uci 直接修改 OpenWrt 前端 Luci 的配置,同时在修改后适时地重启 homeproxy 服务。

更新提醒:2024-03-13

因为之前的脚本在 OpenWrt 的 sh 中执行,会导致部分语法不支持,所以我更新了脚本内容。

新的脚本通过测试已经确认可以成功执行。

#!/usr/bin/env sh

PORT_STARTING=20000
PORT_RANGE=10000
MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING=5
CURL_TIMEOUT_IN_SECONDS=3
NETWORK_TEST_URL=http://www.google.com/generate_204
LOG_FILE=/var/log/hopping.log
NODE_NAME=my_hysteria_node

failure_count=0

for i in $(seq 1 ${MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING}); do
curl -m ${CURL_TIMEOUT_IN_SECONDS} ${NETWORK_TEST_URL} &> /dev/null

if [ $? -eq 0 ]; then
echo "Network check successful."
break
else
let failure_count=${failure_count}+1
echo "Network check failed. Total failures: ${failure_count}"
fi

sleep 1
done

if [ "${failure_count}" -ge ${MAX_FAILURE_ATTEMPTS_BEFORE_HOPPING} ]; then
new_port=$((RANDOM % ${PORT_RANGE} + ${PORT_STARTING}))
echo `date "+%Y-%m-%d %H:%M:%S"` >>${LOG_FILE}
echo "${failure_count} consecutive ping failures. Try hopping to port ${new_port}." >>${LOG_FILE}

uci set homeproxy.config.main_node=nil
uci commit homeproxy
/etc/init.d/homeproxy restart
sleep 1
uci set homeproxy.${NODE_NAME}.port=${new_port}
uci set homeproxy.config.main_node=${NODE_NAME}
uci commit homeproxy
/etc/init.d/homeproxy restart

echo "Switched to port ${new_port}" >>${LOG_FILE}
echo "" >>${LOG_FILE}
else
echo "Network is OK. Total failures: ${failure_count}"
fi

这里之所以要先检查网络可用性,是因为这个更换端口服务等于重新启动 HomeProxy 和 sing-box,这意味着它不像 Hysteria 官方客户端实现的 port hopping 一样可以保持连接不断开,而是要断开所有网络连接并重连。如果过于频繁地执行这个操作,反而可能导致网络特别是长连接的不稳定。

这里的网络检查是为了能够只在网络已经断开的情况下通过换端口的方式恢复,当然你也可以修改这部分脚本来执行你自己的检查策略。

最后,将上面的脚本存入文件,例如 /root/port_hopping.sh,并添加可执行权限:

chmod +x /root/port_hopping.sh

然后通过 crontab 定期执行:

* * * * * /root/port_hopping.sh

大功告成!