闲置安卓手机当旁路网关实现全家科学上网
Category(分类): Backend Status: 已读
原文:闲置安卓手机当旁路网关,无需购买软路由即可让家里所有设备实现科学上网(不良林的博客,2022-12)。 本文为整理版本:合并了原文的文字教程与视频文稿两部分内容。
原理:什么是旁路网关
你可能听过透明网关、透明代理、旁路网关、旁路由、网关模式、网关代理等名词——从原理上讲它们说的是同一种东西,只是通过不同终端设备实现,才造出这么多术语。
- 网关:家里电脑访问任何公网 IP 都需要先交给网关,相当于家庭网络的出口,可以简单理解为路由器;
- 旁路网关:在主路由"旁边"再加一台设备当网关。局域网其他设备访问公网的流量都交给这台旁路由,由它(通过 VPN/代理)转发出去。
对局域网其他设备而言,它并不知道网关已经帮它实现了科学上网,整个过程完全透明,所以也叫透明代理/透明网关。
为什么手机可行:内网设备之间的数据传输不需要经过手机,只有上网的数据才发给手机路由转发——这种模式大幅降低了手机负担,让路由转发性能不强的安卓手机也能胜任。作者实测跑满 100M 带宽没有问题(设备:坚果 Pro 2S,Android 9 + 魔趣系统,估计能扛 500M)。
相比其他方案的优势:
- 省去购买软路由的钱,也省去学习 OpenWrt 的成本(手机人人会用);
- VPN 客户端极其丰富:可以 clash、v2rayNG,也可以用自带节点的第三方 VPN/加速器;
- 可突破 VPN 客户端的设备数限制(某客户端只允许绑定两台设备,旁路网关化后局域网所有设备无视限制直接用);
- 相比 wifi 共享 VPN、http 代理共享等临时手段,这是真正可以 7×24 小时长期稳定使用的方式。
第一步:准备手机
- Root——这是最难的一步,只要 root 了后面都简单。root 之后最好刷一个比较原生的安卓系统;
- 手机 IP 强烈建议改成静态 IP(手机 wifi 设置里把 DHCP 改成静态,或在主路由上做 MAC-IP 绑定);
- 在手机上启动任意 VPN/代理客户端(以 clash 为例),确保手机自身能正常科学上网。
各手机厂商定制程度不同,在一台手机上成功不代表适合所有设备。
第二步:进入手机的 shell
方式一:电脑 adb(platform-tools 下载)
需开启「设置 - 开发者选项 - Android 调试」(找不到开发者选项时,在「关于手机」连续点击「版本号」7 次)。无线连接还需开启「网络 ADB 调试」。
adb devices # 查看设备
adb connect 192.168.0.111 # 无线连接
adb shell # 进入 shell
adb push 电脑路径 手机路径 # 上传文件
adb pull 手机路径 电脑路径 # 下载文件
adb install APK路径 # 安装 APK
方式二:手机 Termux(下载地址)
打开后是 $ 普通用户,输入 su 回车切换为 root(# 号提示符)。
第三步:一键脚本
原文提供的旁路网关脚本(原理:开启 IP 转发 + NAT + 策略路由,把来自物理网口的流量导进 VPN 的 tun 虚拟网卡,并循环检测网络变化自动恢复路由策略):
#!/system/bin/sh
tun='tun0' # 虚拟接口名称
dev='wlan0' # 物理接口名称,eth0、wlan0
interval=3 # 检测网络状态间隔(秒)
pref=18000 # 路由策略优先级
# 开启IP转发功能
sysctl -w net.ipv4.ip_forward=1
# 清除filter表转发链规则
iptables -F FORWARD
# 添加NAT转换,部分第三方VPN需要此设置否则无法上网,若要关闭请注释掉
iptables -t nat -A POSTROUTING -o $tun -j MASQUERADE
# 添加路由策略
ip rule add from all table main pref $pref
ip rule add from all iif $dev table $tun pref $(expr $pref - 1)
contain="from all iif $dev lookup $tun"
while true ;do
if [[ $(ip rule) != *$contain* ]]; then
if [[ $(ip ad|grep 'state UP') != *$dev* ]]; then
echo -e "[$(date "+%H:%M:%S")]dev has been lost."
else
ip rule add from all iif $dev table $tun pref $(expr $pref - 1)
echo -e "[$(date "+%H:%M:%S")]network changed, reset the routing policy."
fi
fi
sleep $interval
done
保存为 proxy.sh,然后:
chmod +x proxy.sh # 赋予可执行权限
nohup ./proxy.sh & # 后台运行
此时这台手机就成为了一台旁路网关。
第四步:让其他设备走这个网关
两种方式:
- 全局设备:修改主路由的 DHCP 设置,把下发的网关改成手机 IP——局域网所有设备直接科学上网;
- 单一设备:手动修改某台设备的网关为手机 IP——只有它走代理(电脑上手动配 IP,关键是默认网关填手机 IP;DNS 污染问题可临时改 1.1.1.1 缓解,但会引入"国内网站解析到国外"等新问题)。
改完后电脑不运行任何代理工具即可直接访问外网,clash 切节点时所有设备跟着切换。
进阶:网线接入
wifi 连接受质量和干扰影响大(作者上古 wifi 环境只跑 20M),追求稳定快速可以:
- 购买 type-c 转网卡转换器(建议选带 PD 充电口的,保证 7×24 供电);
- 关闭 wifi、网线接入主路由,此时物理接口是
eth0(ip a可查看各接口:wlan0是 wifi、tun0是 VPN 虚拟网卡、eth0是网线); - 修改脚本中的
dev='wlan0'为dev='eth0',重新后台运行; - 网线接口在手机上配静态 IP 不方便,建议在主路由上做 MAC-IP 绑定;
- 充电口被占用后 adb 无法走 USB,用
adb connect <手机IP>网络连接。
作者网线接入后测速直接跑满 100M 带宽。
排错与注意事项
安卓系统每次切换网络都会重置部分设置,一些"永久生效"的配置在手机重启后也会被重置(手机每次重启后需要重新运行脚本)。排错命令:
cat /proc/sys/net/ipv4/ip_forward # 检查 IP 转发是否启用
iptables -nvL -t filter # 检查 iptables(filter|nat|mangle)
ip rule # 检查路由策略
ip a # 检查网卡接口
其他要点:
- 切换不同 VPN 客户端前先断开原 VPN:某些客户端(如 clash)启动时直接把 VPN 服务"挤掉"而不是先关闭,会导致 tun 虚拟网卡接口名变化,脚本里写死的
tun0失效、路由规则加不上;断开重连即可恢复接口名。直接在 clash 里切节点没有这个问题; - 熄屏省电会降性能,要当 7×24 网关用必须关闭一切省电选项、性能调最优、关掉不必要的后台;
- 出现莫名其妙的问题直接重启手机,网络设置恢复默认,重来即可;
- 本方式(安卓 VPN 服务)的好处是可以直接在手机上切节点、支持任意第三方 VPN 客户端,缺点是只能在手机上切节点。另一种方式是绕过安卓 VPN 服务、直接跑 clash/v2ray 内核 + WebUI,可在局域网任何设备上切节点,但就没法用第三方 VPN 客户端了。
整理者注
核心思路只有三件事:ip_forward=1 + iptables NAT + 策略路由(ip rule)把物理网口流量导入 tun 口。这与本站《Linux(CentOS7) 使用 Clash 代理教程》是互补关系:服务器端跑 Clash 内核(allow-lan: true)或手机端跑 VPN 客户端,再配合本文的旁路网关策略路由,即可实现全设备零配置上网。