最近没钱续宽带,用了用房东的宽带,谁曾想房东宽带的速度稳定性还很给力,就是没了公网,NAS用户体验直接夭折,官方的中转服务越用越气,应应急还行,所以研究了一下,利用 NewFuture/DDNS 开源软件配合 fatedier/FRP 实现了多地转发、异地容灾的折中方案,出奇稳定,还使用了 Cloudflare Tunnel 实现保底连接,从此 NAS 永不失联。
💡
文章内容尽量讲透整体的实现思路及原理,后期有空再提供完整服务器端及客户端的 docker compose 模板降低学习成本
实现的本质是利用中间服务器进行中转,但我们可以利用 Cloudflare Tunnel 实现转发,起码比 NAS 官方中转好使。
1、中转服务器一个或多个(可选);
2、家里或朋友有公网的宽带能给你用(可选);
3、域名一枚并由Cloudflare管理;
4、NAS安装配置 Cloudflare Tunnel;
5、因人而异。
用python编写程序使用tcping间歇测试中转服务器与NAS的通讯情况,选择最优的服务器解析到”nas.xxx.com”域名,若配置的服务器均无法访问,解析至 Cloudflare Tunnel 确保基本的连接保障,只要NAS有网既可以访问,NAS 到内部的应用使用了 nginx 进行反代理,为了配置证书及统一接口。
graph LR
A[User] -- 访问 --> B{nas.xxx.com};
B --> C(DDNS);
C -- tcping-port --> D[Service1<br>Service2<br>more];
D -- 择优 --> E((解析));
E -- Service* IP Address --> B;
B -- FRP --> F[Service*] -- FRP NAT --> G[NAS] -- Nginx Proxy --> H[APP];
B -- Cloudflare Tunnel --> F2[Cloudflare Service] -- Tunnel --> G2[NAS] -- Nginx Proxy --> H2[APP];
登录 Cloudflare 的 Zero Trust 控制面板,在左侧导航栏的 access 选择 tunnels,创建一个隧道名称随意,创建后会提供官方安装方案,将隧道程序安装到NAS主机。
配置好后端地址,此时 Cloudflare 会创建一条解析记录,cname 到 Connector ID。
安装完成后保留好 Connector ID 以备后用
在中转服务器安装 FRP 服务端,安装方法参考官方文档。
frp/README_zh.md at dev · fatedier/frp
https://github.com/fatedier/frp/blob/dev/README_zh.md
配置文件参考:
#Frp作为中间件使用
[common]
bind_addr = 0.0.0.0
bind_port = 7000
kcp_bind_port = 7000
token = xxxxxxxxxxxxxxxxxxx
#接受未启用TLS的客户端连接
tls_only = false
# console or real logFile path like ./frpc.log
#log_file = /dev/null
# trace, debug, info, warn, error
log_level = error
log_max_days = 3
💡
高级玩法:实际使用中发现,如果是安装在家宽并单独使用 FRP 进行 NAT 一段时间后运营商会有一定几率封端口,建议使用伪装工具对 FRP 流量进行隐藏保安全。
在 NAS 上使用 Nginx 对内部服务进行反代理,这样的目的是为了统一接口和配置域名证书,具体配置方案网上找找吧,这个都是因人而异,网上也很多关于nginx反代理的教程,这里提供我其中反代 NAS 页面的参考。
Tips:Nginx 可不止能反代理 WEB 哦。
需要注意:FRP 客户端若开启了 Proxy Protocol ,nginx 也要开启 Proxy Protocol 协议。
server
{
listen nginx:2096 ssl proxy_protocol;
server_name nas.xxx.com;
index index.html;
root /etc/nginx/web/default/;
access_log /LogFile/log/proxy_myqnap_access.log;
error_log /LogFile/log/proxy_myqnap_error.log error;
#SSL-START SSL相关配置
ssl_certificate /acme.sh/*.xxx.com//fullchain.cer;
ssl_certificate_key /acme.sh/*.xxx.com/*.xxx.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
error_page 497 https://$host$request_uri;
#SSL-END
#ERROR-PAGE-START 错误页配置
#error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#禁止访问的文件或目录
location ^~ /\.env { return 403; break; }
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.conf|\.yml|\.pem|\.key|\.bak|\.types|\.project|LICENSE|README.md) { return 403; break; }
#QnapWEB
location / {
proxy_pass https://qnap:2021;
#持久化连接
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
#WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
#proxy protocol
include proxy_header_proxy_protocol.conf;
}
# 禁止爬虫访问
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") { return 403; }
location =/robots.txt {
default_type text/html;
return 200 "User-Agent: *\nDisallow: /";
log_not_found off;access_log off;
access_log /dev/null;error_log /dev/null;
}
#favicon不生成日志
location =/favicon.ico {
log_not_found off;access_log off;
access_log /dev/null;error_log /dev/null;
}
}
NAS 上需要安装 FRP 客户端,配置了多少个服务器就需要安装多少个客户端(推荐使用Docker)。
配置文件参考:
[common]
server_addr = 1.1.1.1(服务器地址)
server_port = 7000
token = xxxxxxxxxxxxxxxxxxx
# KCP
protocol = tcp
# if tls_enable is true, frpc will connect frps by tls
# 启用此功能后除 xtcp 外,可以不用再设置 use_encryption 重复加密
tls_enable = true
# console or real logFile path like ./frpc.log
#log_file = /etc/frp/log/frpc-rt-home.log
# trace, debug, info, warn, error
log_level = error
log_max_days = 3
#NAS网页管理反代理隧道(Docker)
[TCP_NASWEB_HTTPS]
type = tcp
local_ip = nginx #nginx的NAS内部地址
local_port = 2096 #nginx端口
remote_port = 2096 #服务器端口
use_encryption = false
use_compression = false
#Proxy Protocol 协议
proxy_protocol_version = v2
程序由 NewFuture/DDNS 的源码二次开发,主要实现的作用是测试中转服务器的可用性,选择延迟最低的更新解析到指定域名,从域名解析层实现故障切换,如果配置的中转服务器均无法使用解析到 Cloudflare Tunnel ,由于 Cloudflare 有端口限制除了固定的端口外,其他端口是无法访问的。这就是为什么要用 Nginx 进行反代理统一接口的原因之一。
配置说明:
{
"dns": "cloudflare",
"id": "",
"index4": "default",
"index6": "default",
"ipv4": "nas.xxx.com", #域名
"ipv6": "nas.xxx.com", #域名
"proxy": null,
"token": "cloudflare API", #Cloudflare API
"ttl": 60,
"port": 2096,
"pings": 3,
"tunnelscname": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.cfargotunnel.com", #Connector ID
"backser": "FRP服务器地址或域名", #备用服务器
"addresslis4": [
{
"name": "FRP服务器地址或域名1" #常用服务器1
},
{
"name": "FRP服务器地址或域名2" #常用服务器2
}
],
"addresslis6": [
{
"name": "FRP服务器地址或域名1"
},
{
"name": "FRP服务器地址或域名2"
}
]
}
具体安装及使用方法可参考官方教程:https://github.com/NewFuture/DDNS/blob/master/README.md
二次开发(本文使用)
https://github.com/Hscpro/DDNS
源GIT仓库
https://github.com/NewFuture/DDNS
DDNS 服务解析更新地址的记录
实际维护了两条中转隧道,家用公网做主用、服务器备用,CloudFlared 保底备用。
提供 Docker 配置模板
兼容本地公网
Docker 按需启动
💡
未尽事宜欢迎留言沟通
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=5xncd90e99vl