























随着家里电子设备越来越多,客户端维度的科学上网配置已经逐渐支持不了日常需求了:
于是趁着工作之闲,研究了一下软路由,一站式解决了家庭上网问题。
市场上的可自由刷机的路由器还是很多的,不过对于入门级屌丝租客党来说,明白自己到底需要什么是很重要的:
基于上述原则,类似小米AX6000之类的 WIFI 路由器基本不会考虑了;类似J4125之类的性能较强、耗电较高的基于 X86 的路由器基本也不会考虑了;类似 R2s ,N1盒子之类的老东西也不考虑了。
搜寻了一番,发现电犀牛(FastRhino)的 R66s 刚好符合我的基本要求。

相比一些从电视盒子改来的玩意、或者羞羞答答才放开刷机功能的WIFI路由器、或者是仗着原装OpenWrt割韭菜的路由器来说,这个产品还是比较大胆和良心的。
OpenWrt官方固件自然也是可以的,不过考虑到国人的常用需求,一般都是用国内维护的固件。常见的固件有:
个人感觉这些固件其实都大同小异,主要区别还是上游的 OpenWrt 版本不同、Linux 内核版本不同、默认自带的软件包不同(尤其是 iStoreOS 自带了很多私货应用)。其实 R66s 出厂自带的镜像也是够用的(其实就是 Lean 的固件),只是出于政策原因,没有自带科学上网工具。这些东西动动小手自己装下也行,不过为了方便大家开箱即用,直接写到固件里用起来更方便而已。
如果需要自己刷机,其实也不复杂。用读卡器插入PC,用 rufus 工具直接写入指定镜像即可。

这里还遇到了有一个有意思的点,原装的 32G SD 卡插进来之后,Windows系统的文件管理器只识别出了 64MB。原本以为是遇到了奸商,但是用磁盘管理工具一看的确是 32G 的盘。后来研究后才发现是因为这个是系统引导盘,因此有时只会识别系统主分区的大小,有时甚至不会被识别为外部存储,不影响使用。
正常刷完后,SD 卡分区大致如下。只使用了主分区,还有大量未分配的区域,如有需要等启动后再新增分区即可。

相关背景知识可以先看一下油管 jack stone的家庭网络设计,讲的挺好,颇有老司机风范。
考虑到我这里光猫自带的WIFI也够用,但是光猫后台没有admin权限,很多东西不好改。并且出于社恐也不想打电话找宽带师傅把光猫的路由模式改桥接模式。因此我还是采用了 光猫做主路由+R66s做旁路由 的方案:
对于新手小白来说,这一步最容易踩坑。尤其是当接线和配置不对时,连后台都打不开,这是最让人沮丧的。我个人也是尝试了很多姿势才了解其中的弯弯绕。
唉?前面不是说软路由和光猫就是要LAN口相连么?没错,但那是指的配置完成后的连接方式。
在设备出厂、或者刷了新固件后,说明书或文档上都会写清楚当前固件默认配置的IP。例如 R66s 刷的 Lean 固件默认 IP 就是 192.168.100.1。这个配置的意思是,当前设备的 LAN 口配置的是 192.168.100.1 的静态 IP。
而我这边光猫的网段是 192.168.1.0/24 ,软路由的静态 IP 不在这个网段内。这就导致连接光猫的PC设备和软路由是无法连接的,自然也就访问不到后台了。
既然软路由配置静态IP不行,那是不是直接用 WAN 口和光猫的 LAN 口相连就行了?毕竟 WAN 口的默认配置是 DHCP 协议,肯定可以直接加到光猫的网段中。
理论上说当然可以,但是实际上还是要看固件的配置。因为出于安全考虑,很多固件的默认防火墙配置是只允许从 LAN 口访问后台,不允许从 WAN 口访问。

如果我记得不错的话,iStore OS 默认是允许从 WAN 口访问的,而 Lean 固件默认是不允许从 WAN 口访问的。
为了避免上面的各种问题,最稳妥的方法还是电脑端直接和光猫LAN口相连(或者通过交换机相连),这样就避免了各种上面的幺蛾子。如果一不小心光猫的静态IP还和光猫的IP冲突了,直接断开光猫即可。
首次连接到软路由后台后,按照旁路由的配置思路,需要在 网络-> 接口 -> LAN 中进行如下配置:

配置完成后,当前页面应当就加载不出来了,这时候将软路由和光猫 LAN-LAN 相连,然后通过这里配置的静态IP就又可访问了。
OpenWrt 基于 Linux,但是一些重要的配置和Linux 还是有些区别的。重点要关注下面路径下的文件:
/etc/config 这里记录了各个应用的通用配置。操作这里的文件和在 luci 页面中操作是等价的。/etc/init.d 这里记录了各个应用的启动命令,类似 service 或是 systemctl 的功能。/usr/lib/lua/luci/ 这里记录了 luci 的页面信息,用于操作 /etc/config 的配置。Lean 国际版固件自带,或者直接在软件包下搜索安装下面两个包,配置上自己准备好的机场,就能开心使用了。
luci-app-ssr-plus
luci-i18n-ssr-plus-zh-cn由于 SSR 会深入影响 DNS 解析,路由转发等基础功能。因此一般来说,SSR可以算是家庭网络的最大不稳定因素。所以这里有必要简单了解下 SSR-PLUS 的工作原理,方便定位网络问题。
单纯的 SSR 其实就是一个基于 libshadowsocks 的加密 socks 代理。不过仅此而已肯定不够,毕竟更重要的问题是“选择哪些流量走代理,哪些流量不走代理“。因此我理解 SSR-PLUS 就是 OpenWrt 下 SSR 结合了 iptables + ipset + dnsmasq 的组合工具。
SSR-PLUS 在启动时会加载两个外部订阅的数据。这些配置可以在 /etc/ssrplus 下看到:
国内IP列表比较简单,就是在 ipset 里添加一个 china 的路由规则集,方便后续进行 iptables 设置。而GFW 列表除了设置 ipset 之外,还要进行 DNS 选路。
众所周知,DNS 是明文报文,无良运营商可以很方便的进行 DNS 污染,导致直接解析到错误 IP,更别提后续的连接了。
一种简单的解决方案是将所有 DNS 请求都走 SSR 的 socks 代理,但这样毕竟效率较低。因此实践中常用的办法就是:
/tmp/dnsmasq.d/dnsmasq-ssrplus.d 。这样就能做到安全的 DNS 了。
实际用起来发现dns总是容易挂。。。这里需要加一个定时监测脚本拉一下:
ps -ef|grep /usr/sbin/dnsmasq |grep -qv grep
dns_alive=$?
if [ $dns_alive -ne 0 ]
then
echo 'dnsmasq down !!!'
/etc/init.d/dnsmasq restart
echo 'dnsmasq restarting !!!'
fi我们知道 GFW 列表只记录域名,而在用 iptables 对流量路由转发时只能拿到 IP。因此 dnsmasq 在解析 GFW 后,还会将解析出来的 IP 加入到一个名为 gfwlist 的 ipset 规则。
root@OpenWrt:~# ipset list gfwlist
Name: gfwlist
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 56232
References: 2
Number of entries: 1686
Members:
20.198.162.78
65.21.236.8
142.250.186.54
203.77.190.0
54.148.90.231
....这样一来,再配合 iptables 的 NAT 的 PREROUTING 设置,就能做到针对 GFW 内的域名进行代理转发:
root@OpenWrt:~# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
SS_SPEC_WAN_AC tcp -- anywhere anywhere /* _SS_SPEC_RULE_ */
...
Chain SS_SPEC_WAN_AC (2 references)
SS_SPEC_WAN_FW all -- anywhere anywhere match-set gfwlist dst
...
Chain SS_SPEC_WAN_FW (4 references)
target prot opt source destination
RETURN all -- anywhere 0.0.0.0/8
RETURN all -- anywhere 10.0.0.0/8
RETURN all -- anywhere 127.0.0.0/8
RETURN all -- anywhere 169.254.0.0/16
RETURN all -- anywhere 172.16.0.0/12
RETURN all -- anywhere 192.168.0.0/16
RETURN all -- anywhere 0.0.0.224.in-addr.arpa/4
RETURN all -- anywhere 240.0.0.0/4
REDIRECT tcp -- anywhere anywhere redir ports 1234
有了上面的基础,我们就明白了其实这两种模式的区别也很简单。看下两种模式下的 iptables 表就清楚了。
GFW模式:
Chain SS_SPEC_WAN_AC (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere match-set whitelist dst
SS_SPEC_WAN_FW all -- anywhere anywhere match-set blacklist dst
RETURN all -- anywhere anywhere match-set bplan src
SS_SPEC_WAN_FW all -- anywhere anywhere match-set fplan src
RETURN tcp -- anywhere 36.156.102.177 tcp dpt:!domain
RETURN all -- anywhere anywhere match-set china dst
SS_SPEC_WAN_FW all -- anywhere anywhere match-set gfwlist dst
简要的工作流程是:
绕过中国大陆IP模式:
Chain SS_SPEC_WAN_AC (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere match-set whitelist dst
SS_SPEC_WAN_FW all -- anywhere anywhere match-set blacklist dst
RETURN all -- anywhere anywhere match-set bplan src
SS_SPEC_WAN_FW all -- anywhere anywhere match-set fplan src
RETURN tcp -- anywhere 36.156.102.177 tcp dpt:!domain
RETURN all -- anywhere anywhere match-set ss_spec_wan_ac dst
RETURN all -- anywhere anywhere match-set china dst
SS_SPEC_WAN_FW all -- anywhere anywhere 简要的工作流程是:
大白话总结就是:
那么具体家里选哪个更合适呢?我个人建议选 GFW 列表模式。虽然绕过大陆IP模式看起来方便,但是:
不知道为啥 OpenWrt 自带的端口转发功能总是不能正常 work,尤其是转发到内网的其他 IP 时。这时候就需要 socat 来进行额外的端口转发功能。
安装下面的包即可:
luci-i18n-socat-zh-cn
luci-app-socat然后就可以在 网络 -> Socat 里愉快的进行端口转发了。
使用 v3 版的 n2n 需要先更新下 opkg 的源,否则拉不到适配 v3 版本的 luci-app 。虽然可以直接改 /etc/config/n2n 配置文件,不过毕竟不太优雅。
不知道为啥固件自带的源长这样,luci 的版本都跟其他的不一样。。。
src/gz openwrt_base https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/base
src/gz openwrt_luci src/gz openwrt_luci https://downloads.immortalwrt.org/releases/packages-18.06-k5.4/aarch64_generic/luci
src/gz openwrt_packages https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/packages
src/gz openwrt_routing https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/routing
src/gz openwrt_telephony https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/telephony改成一样即可:
src/gz openwrt_base https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/base
src/gz openwrt_luci https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/luci
src/gz openwrt_packages https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/packages
src/gz openwrt_routing https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/routing
src/gz openwrt_telephony https://downloads.immortalwrt.org/releases/21.02.1/packages/aarch64_generic/telephony配置好 n2n 客户端后,再在服务端配置好 nginx,挂上 ssl 域名 ,就能从远端访问家里的 OpenWrt 配置后台了。
当然,由于有些 luci 组件是需要额外暴露端口的,因此直挂 80 端口的 nginx 的话,实时监控、tty终端之类的功能还是没法用的。
运行一段时间后发现 n2n 的客户端 edge 经常时不时的挂掉,logread 看了下日志:
# logread |grep n2n
Thu Mar 30 19:24:48 2023 daemon.info n2n-edge[21183]: 30/Mar/2023 11:24:48 [n2n.c:38] ERROR: Unable to create socket [No file descriptors available][-1]
Thu Mar 30 19:24:48 2023 daemon.info n2n-edge[21183]: 30/Mar/2023 11:24:48 [edge_utils.c:273] ERROR: failed to bind main UDP port 0
...看起来似乎是进程打开的最大句柄数超过了上限,确认了一下发现 ulimit -a 里看到的限制是 1024 ,实际 ls -lA /proc/{pid}/fd|wc -l 看到的正好也是 1024 (ls 的 -lA 参数忽略了 . 目录和 .. 目录,如果直接 ls -la 则是 1026)。。。
解决方式是改 ulimit 增大全局配置,或者直接修改 /etc/init.d/n2n 配置文件,增加进程的配额。而我选择后者(参考 openwrt 配置):
procd_set_param limits core="unlimited"
procd_set_param limits nofile="10240"
procd_set_param limits nproc="10240"(更新)发现上面的配置没用, cat /proc/{pid}/limits 发现 nofile 的配置并没有生效。于是自己写了一个脚本,当 fd 超过限制就自动重启下 n2n,放在 cron 里定期执行:
n2n_pid=`ps -ef|grep /usr/bin/n2n-edge |grep -v grep |awk '{print $1}'`
if [ ! $n2n_pid ]
then
echo 'n2n not started'
exit 1
fi
fd_cnt=`ls /proc/${n2n_pid}/fd |wc -l`
if [ ${fd_cnt} -ge 1024 ]
then
/etc/init.d/n2n restart
fi
Dropbear 可以理解是 OpenWrt 下的 sshd 。为了安全起见,dropbear 默认只对 lan 口过来的请求开放 ssh 连接。因此在配置好 n2n 之后,也是无法直接访问这个服务的。这里需要先关闭下 dropbear 对 lan 口的绑定:
root@OpenWrt:/etc/config# cat /etc/config/dropbear
config dropbear
option PasswordAuth 'on'
option RootPasswordAuth 'on'
option Port '22'
# option Interface 'lan'
# option BannerFile '/etc/banner配置好后 restart 即可生效。
root@OpenWrt:/etc/config# /etc/init.d/dropbear restart软路由配置好了后先不要急着连接设备。建议先重启几次路由器,确保配置正常生效,且重启不丢失。确认完成后,各个需要连接的客户端再手动配置下:
正常情况下,配置好后即可感受科学的魅力,不过偶尔也可能出现一些奇怪的坑。此时可以先尝试:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。