公网访问方案介绍及各类代理服务器的搭建
tags: NAS公网访问方案介绍及各类代理服务器的搭建
NAS 如果不能公网访问,玩法直接少一半,但公网访问又挺复杂的,有很多方案可以选择,常见的有三种:
- DDNS + 反向代理
基本原理是把一个网络入口开放到公网,仅开放一个反向代理服务器的端口,通过不同的域名访问不同的服务。缺点是现在几乎没有公网 IPv4 地址,仅能通过 IPv6 访问。
- 内网穿透 + 反向代理
与 1 类似,但开放到公网的方式是内网穿透,而不是直接 IP 地址访问。这种方案的流量带宽取决于 frps 服务器的带宽,免费方案几乎跑不满家宽上行。
- 虚拟局域网
最安全的方式,缺点是每个客户端都需要安装一个虚拟局域网软件。
这些方案并不互斥,你完全可以将它们结合成更加灵活的方案。下面介绍一下我使用的结合了 1 和 2 的反向代理+DDNS+ 内网穿透实现双栈访问的方案。
路由器基本配置
- NAT 类型更改
NAT 默认为 NAT4,如果能改的话,最好改为 NAT1
- 防火墙
配置规则,禁用所有 IPv6 入站,然后放通 IPv6 反向代理端口,这里假设为 54321
然后放通所有的 IPv6 ping,如果有别的服务需求,按需放行即可
如果你没有公网 IPv4,那么设不设 IPv4 防火墙都无所谓了
内网穿透占坑
每个人选择部署反向代理的位置不同,有的人部署在 PVE 上,有的在 NAS 系统上,有的在路由器上,有的在单独的 LXC 容器里,所以后面我把部署的位置统称为“系统”(我部署在 NAS 上的)。
内网穿透(frps)服务器的端口往往由服务商那边指定,一般都是高位端口,为了结合方案 1、2,我们需要保证 fprs 端口与反向代理服务器的端口一致,大概如下
<frps>:54321 -> <NAS>:54321
所以你要先拿到服务商那边的端口号,再决定自己这边反向代理的端口号。

假设获取到了 54321 端口号
根据服务商的文档在系统上配置穿透即可。由于不同的服务商配置方法不同,这里就不赘述了。
配置 ddns-go
在系统上安装 ddns-go 服务:
sudo mkdir /opt/ddns-go/
sudo mv ./ddns-go /opt/ddns-go/
sudo /opt/ddns-go/ddns-go -s install
然后配置

- IPv4 由内网穿透服务商固定,因此使用命令把 IP 打进去即可
- IPv6 通过网卡检测的方式实现
- IPv4 和 IPv6 的 Domains 一般应当一致,如非你有的服务希望仅 v4 或仅 v6 访问
Nginx 反向代理
模板:
server {
listen 54321 ssl;
listen [::]:54321 ssl;
http2 on;
# 服务域名
server_name example.com;
# 证书地址
ssl_certificate /etc/nginx/conf.d/certs/_.example.com.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/_.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
# 后端服务地址
proxy_pass http://192.168.31.211:7556;
proxy_set_header Host $host;
# 代理 WebSocket,一般都需要
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
不同系统的 nginx 配置文件写法类似,但配置文件路径和重载方法不一样:
debian
配置文件放在 /etc/nginx/site-available,然后软链接到 /etc/nginx/site-enabled
例如:
sudo ln -s /etc/nginx/sites-available/mywebsite /etc/nginx/sites-enabled/
然后验证配置并重载:
sudo nginx -t
sudo systemctl reload/restart nginx
alpine
配置文件放在:/etc/nginx/http.d/
验证配置并重载:
sudo nginx -t
sudo rc-service nginx restart/reload
openwrt
配置文件放在:/etc/nginx/conf.d/
要麻烦一些,有些内容需要 uci 来配置(也可以改配置让 nginx 脱离 uci 的管理),例如:
# 去掉 _lan 区块中对 restrict_locally 的引用
uci del_list nginx._lan.include='restrict_locally'
# 设置一下证书路径:
uci set nginx._redirect2ssl.ssl_certificate='/etc/nginx/conf.d/_.Example.com.crt'
uci set nginx._redirect2ssl.ssl_certificate_key='/etc/nginx/conf.d/_.Example.com.key'
验证配置并重载
nginx -t # 这个命令好像不行,有点忘了,要加个什么
service nginx restart/reload
caddy 反向代理
配置比 nginx 简单很多,但性能要差一点,推荐用这个
这里以 fedora、debian 为例
sudo dnf install caddy
sudo apt install caddy
配置文件在 /etc/caddy/Caddyfile
模板:
# ========== 通用片段 ==========
(common) {
header {
# 隐藏 Caddy 版本号
-Server
# 强制浏览器以后只走 HTTPS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# 禁止浏览器猜测响应内容类型
X-Content-Type-Options "nosniff"
# 防止你的页面被别人的站点用 <iframe> 嵌进去,启用会导致 PVE 无法看到终端
# X-Frame-Options "DENY"
}
# 启用压缩传输
encode gzip
}
# ========== 证书片段 ==========
(nas-cert) {
tls /etc/caddy/certs/_.example.com.crt /etc/caddy/certs/_.example.com.key
}
# ========== NAS 站点 ==========
nas.550293.xyz:54321 {
import common
import nas-cert
reverse_proxy 127.0.0.1:9090 {
transport http {
tls_insecure_skip_verify
}
}
}
music.550293.xyz:56789 {
import common
import nas-cert
reverse_proxy 127.0.0.1:4533
}
# ========== 其他内网服务(IP 不变) ==========
pve.550293.xyz:54321 {
import common
import nas-cert
reverse_proxy 10.0.0.140:8006 {
transport http {
tls_insecure_skip_verify
}
}
}
注意代理 https 和 http 写法略有不同,代理 https 需要加
{
transport http {
tls_insecure_skip_verify
}
}
跳过 SSL 验证,因为内网的 https 服务一般都是自签名。
双栈方案原理
双栈访问方案的核心在于利用 IPv4 和 IPv6 的 DNS 解析特性,实现智能路由选择。其工作原理如下:
IPv4 访问路径
- 反向代理服务端口(如 54321)通过内网穿透服务映射到公网 IPv4 地址(如
11.22.33.44) - 在 ddns-go 中,所有域名都同时解析到公网 IPv4 地址
11.22.33.44和系统的 IPv6 地址 - IPv4 用户访问域名时,DNS 解析到
11.22.33.44,通过内网穿透服务访问到反向代理服务器
IPv6 访问路径
- IPv6 用户访问相同域名时,由于双栈优先使用 IPv6 的特性,DNS 直接解析到系统的 IPv6 地址
- IPv6 流量直接访问系统本地的反向代理端口,无需经过内网穿透服务
这种就是前面要求内网穿透的端口与反向代理端口保持一致的原因:确保无论通过哪种路径访问,都能到达同一个服务端口,从而实现无缝的双栈访问体验。