~/app/articles/NORMAL

cat article/2.md

我的NAS寻龙诀:一场由流量焦虑引发的“破案”之旅

学习笔记
NAS
Nginx
Cloudflare CDN
VPS
Frp

"这篇文章讲述了作者如何通过Nginx、Cloudflare CDN、VPS和Frp内网穿透等技术,构建一个智能NAS访问系统,实现内外网自动切换以优化流量使用。在解决这个看似简单的问题过程中,作者深入探索了技术细节,经历了一次"寻龙诀"般的技术之旅。"

date: 2025-11-08T00:26:00 author: 黄应辉

我的NAS寻龙诀:一场由流量焦虑引发的“破案”之旅

每个数字生活的向往者,心中都有一个关于“无缝访问”的梦想:拥有一台NAS,无论身在何处,只需轻轻输入同一个域名,就能立刻接入自己的数字世界,并且获得最本源、最迅捷的内网访问体验。这个梦想,对我来说又多了一层现实的驱动——在校园网里,访问公网会消耗我充值买来的宝贵流量,而访问局域网则完全免费。我的NAS经常要传送动辄几十GB的大文件,如果全走外部公网,那我的钱包可受不了;可如果只走内网,当我换成手机热点时,又得手动切换IP地址,实在太繁琐。

于是,一个极致的优化设想在我脑中诞生:我能不能只访问域名,让Nginx(一个高性能的Web服务器,就像一个智能的交通枢纽)自动判断我的位置,实现内外网智能切换?为了这个目标,我构建了这样一条看似完美的数字通道:我的个人域名,指向Cloudflare的CDN网络(它像一个全球的快递中转站),通过互联网抵达我的一台VPS(虚拟专用服务器),VPS上的Nginx作为智慧的交通枢纽,再经由Frp内网穿透(一条打通外网和内网的秘密隧道)最终稳稳地降落在我的NAS上。

然而,这场为了实现内外网自适应的微小优化,却意外地引领我走下了一层又一层的技术兔子洞。

故事的开端,是一次看似合乎逻辑的失败。我的第一反应是,抓取访问请求里的IP地址进行判断。按照教程,我在Nginx配置里写下:

set $backend "http://nas.handywote.top"; # 默认走反向代理
if ($remote_addr ~* ^172\.29\.) { # 如果来访IP以172.29开头
	set $backend "http://172.29.147.194"; # 就切换到内网地址
}

我本以为$remote_addr(一个Nginx内置变量,记录直接和它握手的客户端IP)会是我的电脑IP。但curl(一个强大的命令行工具,可以用来测试网络请求)的检测结果却给我泼了一盆冷水:

C:\Users\HandyWote>curl -vL https://nas.handywote.top
* Connected to nas.handywote.top (104.21.96.154) port 443 # <--看这里!
...

我的请求竟然先连接了104.21.96.154——这是Cloudflare的服务器IP!这下全明白了,我的所有请求都先被Cloudflare这个“快递中转站”接手了,它会重新帮我访问我的NAS,再把结果返回给我。所以,Nginx看到的$remote_addr永远是Cloudflare的地址,自然不可能匹配我的内网IP,重定向逻辑形同虚设。

幸运的是,Cloudflare非常“贴心”,它把自己看到的访客真实IP,悄悄放在了请求头的一个叫$http_cf_connecting_ip的参数里。这就像快递员发现包裹上写着“派送至甲公司”,但他还是会附上一张小纸条,写着“此包裹来自乙先生的府上”。

我立刻修改了策略,换用这个更可靠的“信物”。为了让配置更优雅,我使用了Nginx的map指令(像一个定义好的“开关盒子”),来专门处理这个判断:

# 在 http 块中添加
map $http_cf_connecting_ip $real_ip_is_internal {
    default 0; # 默认“开关”是0(关),代表外网用户
    ~^172\.29\. 1; # 如果IP匹配 172.29.开头,“开关”就是1(开),代表内网用户
}

然后修改原来的重定向逻辑:

if ($real_ip_is_internal = 1) {
    # 如果“开关”是 1,说明是内网用户,301重定向到内网IP
    return 301 http://172.29.147.194:5666$request_uri;
}
# === 如果“开关”是 0,说明是外网用户,继续走反向代理 ===
proxy_pass http://127.0.0.1:5666; # 走Frp隧道到我的NAS

我信心满满地重启了服务,然而,回应我的却并非期待中的重定向。Nginx的调试日志告诉我,来访者的IP,是一个我从未见过的IPv6地址:2a12:f8c1:50:4::d73。

“这是谁?”我的第一反应是,“这显然不来自我的电脑。”:

C:\Users\HandyWote>ipconfig
Windows IP 配置
未知适配器 singbox_tun:
   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::61be:f6e8:c844:30a8%14
   IPv4 地址 . . . . . . . . . . . . : 172.18.0.1
   子网掩码  . . . . . . . . . . . . : 255.255.255.252
   默认网关. . . . . . . . . . . . . : 172.18.0.2
以太网适配器 有线连接:
   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::3d6a:60d9:c9da:4880%8
   IPv4 地址 . . . . . . . . . . . . : 186.1.1.1
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . :
无线局域网适配器 WLAN:
   连接特定的 DNS 后缀 . . . . . . . : stu.edu.cn
   IPv6 地址 . . . . . . . . . . . . : 2001:250:3003:aa29:40b2:519e:201:8af1
   临时 IPv6 地址. . . . . . . . . . : 2001:250:3003:aa29:60bc:3b51:c16d:2d40
   本地链接 IPv6 地址. . . . . . . . : fe80::1626:aba5:f683:9bc3%7
   IPv4 地址 . . . . . . . . . . . . : 172.29.75.148
   子网掩码  . . . . . . . . . . . . : 255.255.0.0
   默认网关. . . . . . . . . . . . . : fe80::c6e2:87ff:fe5f:7206%7
                                       172.29.255.254

我的怀疑对象,迅速锁定在了那个名为singbox_tun的“未知适配器”上。作为一名经常与网络工具打交道的用户,我立刻意识到这大概率是一个代理软件创建的虚拟网卡。哦,原来是我一直开着V2Ray(一种代理工具)。我用一个比喻说清楚这个问题:我的电脑在上网时,并没有直接从家门口走出去,而是先钻进了一条通往远方的“私人地铁”。这个IPv6地址,正是我乘坐地铁后,在那个遥远城市出口站的地址。当我的请求抵达我的Nginx时,它看到的自然是我的“出口站”,而不是我的“家”。

这个解释合情合理,但我关闭了所有代理软件,问题依旧。还是没有实现重定向,经过我的命令行检查,发现我现在发送请求的依旧不是我想要的172.29开头的内网IP地址,而是一个公网IPv4地址218.16.203.17。我忽然想通了那个最核心、也最基础的原理:内网地址根本就不会跟着请求包“出差”到公网上去! 就像你公司的分机号“8014”无法用于拨打电话一样,分机号只能在公司内部使用。当数据包从你家发出时,路由器(网络世界的“总机/前台”)会执行一种叫做NAT(网络地址转换)的操作,把你的分机号替换成公司的总机号,也就是那个公网IP。

我醍醐灌顶,立刻把Nginx“花名册”里的地址换成了这个公网IP218.16.203.17。重启Nginx,果然实现了跳转!成功了!但为了万无一失,我让手机也连接同样的Wi-Fi进行测试,结果手机却无法重定向。通过查询,我查到手机的公网IP是218.16.203.50。

我终于彻底想通了。一个大学这样的巨型网络,根本不是一个只有一个出口的家庭路由器。它更像一个庞大的园区,拥有通往不同运营商(电信、联通、移动)的多个“大门”,也划分了图书馆、宿舍、教学楼等不同功能的“区域”。每个大门、每个区域,都可能拥有自己独立的公网IP地址池。我身处教学楼,流量走了A门,被分配了17号;而我的手机可能因为负载均衡,被导航到了B门,获得了50号。它们都来自“学校”这个大园区,却是完全不同的出入口。

至此,所有线索终于汇成了一条清晰的逻辑链。真正的解决方案,在此刻变得无比简单。我需要把整个园区的“居民”都请进我的白名单。我观察到两个IP都属于218.16.203.x这个范围,于是我用CIDR(一种更简洁地表示IP地址段的方法)标记法,在Nginx的配置中写下了218.16.203.0/24。

/24是什么意思?它代表这是一个从218.16.203.0到218.16.203.255的地址块,总共256个IP。这一行配置,就相当于对Nginx说:“只要是218.16.203这个大门进来的人,都是自己人!”

保存,重启,再次访问——域名瞬间重定向,熟悉的NAS界面弹了出来,无论是我和我的手机,都成功了!

回望整个过程,从一个看似简单的配置问题开始,我一路追查,相继理解了公网IP与私有IP的本质区别,洞察了NAT的工作原理,体验了代理隧道的奇妙,最后还搞懂了大型机构的网络IP规划。这次探索,解决的技术难题或许微小,但它带给我的,却是一次对网络世界运行法则的系统性重塑。我不仅实现了NAS访问的“内外网一体化”,更在这场寻觅圣杯的旅途中,收获了那张描绘出整个网络世界的、无比珍贵的藏宝图。

$ comments --list (0)

// not signed in


// no comments yet