内网穿透NAS最佳实践:兼顾安全与灵活性
背景
为了能在外部访问家里的NAS,需要将NAS内网穿透到公网。在大陆做NAS的内网穿透主要存在几个挑战:
- 无法控制光猫
运营商仅提供光猫的普通帐号,而只有管理员帐号才能改桥接、禁防火墙、开端口映射…… - 没有公网IP
光猫获取的IP是运营商的大内网IP(一般为10.X.X.X
),无法跨网访问 - 公网IP周期性动态变化
光猫获取的公网IP每周都会随机更改几次,无法直接通过记录IP访问 - 公网IP的主流端口被封
运营商通常直接封禁80
,443
等主流的端口,通过公网IP根本访问不到或容易被封[1] - 禁止私设网站
大陆禁止未备案的网站提供服务
实践上,如果网站没备案:
大陆IP的云服务器只能通过IP提供服务,不能通过域名访问;
大陆家宽不能将HTTP/HTTPS直接暴露在公网,即使不绑域名也不行,会被断网[2] - 暴露在公网上的网站易被攻击
NAS使用规模大,直接把NAS的服务暴露在公网,未及时更新容易被攻击,或直接被弱密码攻击[3] - 使用VPN保护网站后不方便访问
使用Tailscale、OpenVPN等VPN作为内网穿透方案,在外部访问时不够方便,需要切换到专用的VPN客户端,无法同时魔法分流访问外网
本文重点解决问题3,4,5,6,7。不解决1,2。
方案对比
todo
准备
- 一个Cloudflare免费帐号
- 一个域名,已经托管到了Cloudflare(可参考[4])
最好注册一个收费域名
免费域名不稳定,一旦域名失效更换新域名过于折腾
Namecheap 注册6位数字.xyz
域名或aabbbbb.xyz
类数字域名,仅需$0.85/年 - 光猫已设置内网穿透
光猫不会主动把局域网内的设备映射到公网
需要超级密码以:- 修改光猫为桥接模式,让下级路由器拨号拿到公网IP
- 或设置DMZ主机,把下级路由器整个映射到公网(本文的选择)
- 一个支持端口映射的路由器(近年的路由器绝大多数都支持)
- 一台NAS,本文以群晖为例
参数项 | 预设值 |
---|---|
光猫内网IP | 192.168.1.1 |
路由器内网IP | 192.168.1.100 (光猫分配)192.168.49.1 (路由器分配) |
NAS IP | 192.168.49.100 |
SS Server端口 | 2333 |
VMess Server端口 | 2334 |
L2TP/IPSec端口 | 500 1701 4500 |
OpenVPN端口 | 12345 |
路由器以小米路由器为例。更改默认网段
192.168.31.1
为192.168.49.1
是为了避免网段冲突:
如果不更改默认网段,外网环境也使用了小米路由器,其网段为默认192.168.31.1
时,Clash无法正确将流量基于IP分流,大部分回源功能失效。
实战方案
方案简介
配置域名DNS解析
登录Cloudflare Dashboard,找到domain.xyz
的DNS管理页面:
Main
→ Websites
→ domain.xyz
→ DNS
→ Records
按照下图配置DNS:
注意:图中内容需要替换为你的真实域名、IP
DNS Record | 用途 |
---|---|
domain.xyz | NAS的内网IP,后续通过Clash, VPN均可基于内网域名访问到NAS |
* | *.domain.xyz 的通配解析配合群晖反向代理服务器解析 emby.domain.xyz 等域名 |
frp | FRP Server的公有云服务器IP |
v4 , v6 , v | 家庭网络的公网IP,无需手动配置,后续由ddns-go自动维护更新;v.domain.xyz 是双线域名,根据接入网络自动选择IPv4/IPv6 |
配置完DNS后,需要等待旧的的DNS配置过期,新的DNS配置生效,一般不超过3~5分钟。
配置反向代理
从Synology DSM → 控制面板
→ 登录门户
→ 高级
→ 反向代理服务器
→ 新增
添加新的反向代理配置,如图所示:
以Emby为例,这里来源选HTTP
协议和80
端口,后续配置SSL证书后,这里可以配置为HTTPS
协议和443
端口。
目的地主机名一般填localhost
,端口注意是通过NAS主机访问的端口,如果服务是Docker容器启动,需要填映射到宿主机的端口,而非容器内端口。
现在,可以用http://emby.domain.xyz
在内网访问到Emby。
(可选)配置SSL通配符证书
HTTPS协议的推广对明文HTTP网站越来越不友好,经常看到浏览器对明文HTTP网站的不安全警告。尽管本方案实际上由SS
, VPN
等协议的加密来实现信息安全性,但为每个网站加一层HTTPS访问也是不错的。
下面介绍一种自动更新SSL证书的方法,且是通配符证书,即可以为所有*.domain.xyz
均配备SSL证书,无需在新增子域名时额外申请证书。
配置DDNS
DDNS用于解决公网IP周期性动态变化的问题,实时检测家庭网络的公网IP并更新DNS记录,可以通过DNS解析获取家庭的公网IP。
如图所示,从Synology DSM → 套件中心
→ 设置
→ 套件来源
新增矿神源(对应DSM 7.x
版本)
https://spk7.imnks.com/
安装并打开DDNS-GO套件。
如图所示,添加Cloudflare的DDNS配置:
这里的Cloudflare Token需要从Cloudflare Dashborad中添加
需要为domain.xyz
授予DNS编辑权限:
配置完成后保存,可以在Cloudflare Dashborad的DNS管理页面看到由DDNS-GO自动添加的DNS记录:
Cloudflare Dashboard → Main
→ Websites
→ domain.xyz
→ DNS
→ Records
配置完成后,打开电脑的CMD,ping v4.domain.xyz
应该能解析到公网IP并正确ping通。
如果未正确解析,可以稍等5分钟;
如果不能ping通,需要检查DDNS-GO提交是否为公网IP、光猫防火墙/路由器防火墙是否关闭。
最好在外网测试是否能ping通,建议用手机流量测试。Android使用终端模拟器
,iOS使用网络调试助手
。
配置SS Server
如图所示,SS是集成到Clash实现分流、回源的关键。所有回源流量经由Clash转发到SS server,再解析到家庭内网资源。
大陆内部传输的非HTTP流量没有任何阻断措施,直接使用最基本的SS配置即可。
下面使用Docker部署SS Server:
1 | docker pull gists/shadowsocks-libev:latest |
配置端口映射
本节假设光猫已经改桥接/设置路由器为DMZ主机,可以通过公网访问。
测试链路连通性:
登录群晖SSH,用Python3在2334
端口启用一个简单的http服务器,并保持在后台运行:
1 | python3 -m http.server 2334 |
之后登录路由器后台 → 高级设置
→ 端口映射
,添加 2334
→ 192.168.49.100:2334
的TCP端口映射。
某些小米路由器型号,更改完端口映射后,需要在页面底部应用更改,否则不会生效。
之后用手机访问http://v4.domain.xyz:2334/
,能显示网页说明链路联通。
将端口映射改为2333
即可将SS Server的端口暴露到公网。
(可选)frp内网穿透
长期在外地,一旦遇到光猫配置下发、失去公网IP/端口映射失效,会立刻失去回家途径,无法远程修复网络。
FRP是家宽无公网IP的回家方案,还可以作为公网无法直连时的临时备用解决方案。
(可选)Cloudflare Tunnel
Cloudflare Tunnel是另一种家宽无公网IP的(临时)回家方案,也可以作为公网无法直连时的临时备用解决方案。相比于FRP方案,这种方式不需要我们自备FRP公网服务器,但延迟(≥1s)和带宽(~1MB/s)较差,仅适用于无法直连回家时,避免NAS彻底与外部失联的备选方案。
Clash分流规则
如图所示,基于Clash方案的核心优势就是可以自动分流各类流量,在回家的同时不影响正常在外部网络中的其他流量,及其他特殊流量需求。
下面是一个简单的Clash分流回源规则片段,将所有 *.domain.xyz
和192.168.49.0/24
的流量路由回家(仅节选proxies
, proxy-groups
, rules
字段):
1 | # ... |
- 在家:
回家
代理组切换到DIRECT
,直连高速访问内网资源 - 在外:
回家
代理组切换到回家节点
,通过外网IP直连访问资源 - 在外+公网IP不通:
回家
代理组切换到代理回家节点
,通过公网的FRP Server代理访问资源,适用于DDNS故障、光猫桥接失效等多种故障临时修复场景
或切换到代理->CF回家
,先通过出国节点
出国,然后通过Cloudflare Tunnel代理的VMess节点回家注意这里VMess Server本没有启用TLS(即
HTTP
协议),但经过Cloudflare Tunnel代理后提供HTTPS
协议,因此需要使用tls: true
参数。
(可选)配置VPN
VPN不能分流,但仍有使用价值:
- 针对无法代理的流量,VPN可以强制全局回源
- VPN会维持TCP连接,可规避某些网络对后续建立的TCP连接的限速,最开始建立的TCP连接不限速
- L2TP/IPSec等VPN协议由Win, Android, iOS系统内置支持,无需下载客户端。
客户端推荐
- Windows: Clash for Windows
虽然已经删库跑路,也不支持Hysteria2等新协议,但符合使用习惯,异常重启电脑后打开网页不会出现“无法连接到代理”的问题 - iOS: Stash
对Relay代理链支持较好;配置文件基本与CFW相同,可以共用一份配置文件;价格友好 - MacOS: Stash
对于Arm Mac,直接运行iOS购买的Stash就行 - Android: Clash for Android
跨平台选择 - NAS:
后端服务 - clash-premium[8]
Web面板 - YACD[9]
对于有NAS上部分需要代理的服务,可以用clash-premium做后端,YACD做前端,配置文件可以复用,proxy-providers
,rule-providers
也可以自动更新
特殊APP需求
- Emby的Windows客户端不支持Clash系统代理,需要开启TUN模式(仅播放时需要,查看刮削信息可以被代理)
- 音流暂不支持Clash系统代理,需要开启TUN模式
其他注意事项
- 暂未研究IPV6,除L2TP/IPSec外其他部分理应均可支持IPV6
- todo
- 1.家用宽带不能使用 443/80 端口,大家是怎样实现不加端口号,仅域名访问服务的? - V2EX ↩
- 2.有关近期热议的“私设 web 被查”的解决方案 - V2EX ↩
- 3.记一次群辉中勒索病毒后的应急响应-腾讯云开发者社区-腾讯云 ↩
- 4.如何将NameSilo域名解析到Cloudflare - Beecommercer ↩
- 5.群晖 Let's Encrypt 泛域名证书自动更新 ↩
- 6.Arbitrary TCP | Cloudflare Zero Trust doc ↩
- 7.Synology 证书更新 - kiraKo学习笔记 ↩
- 8.dreamacro/clash-premium - Docker Image | Docker Hub ↩
- 9.haishanh/yacd - Docker Image | Docker Hub ↩