利用内网穿透和域名安全访问内部服务
我的unraid上运行了不少服务,其中一些服务我想在外网也能访问,同时需要兼顾安全性和便利性。

vps
个人选用的是阿里云的香港轻量级云服务器,2C/2G/40G的配置一个月34RMB,比内地其他地区的要划算很多。在vps上运行nginx和frps服务即可。
域名和域名解析服务
需要一个域名和支持泛解析的域名解析商,阿里云、腾讯云、cloudflare都支持域名泛解析,将 *.your_domain解析到你的vps IP上。
公网nginx配置
在vps的nginx添加一个代理配置如下:
server {
server_name *.your_domain;
include /etc/nginx/ssl.conf;
location / {
proxy_pass https://localhost:8443;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 4G;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 将所有http请求重定向到https
server {
listen 80;
server_name *.your_domain;
return 301 https://$host$request_uri;
}
ssl.conf文件内容:
listen 443 ssl http2;
ssl_certificate path_to_cert.crt;
ssl_certificate_key path_to_key.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
其中localhost:8443对应的服务就是你的内网nginx服务通过frp暴露出来的服务
frp客户端配置
[nginx]
type = tcp
local_ip = 192.168.50.120
local_port = 443
remote_port = 8443
内部nginx配置
server {
server_name a.your_domain;
include /etc/nginx/ssl.conf;
location / {
proxy_pass http://192.168.50.3;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 4G;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
server_name b.your_domain;
include /etc/nginx/ssl.conf;
location / {
proxy_pass http://192.168.50.4;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 4G;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
...
这样配置好之后,需要增加或者减少服务时,只需要修改内网nginx的配置即可,非常简单方便。
现在有一个问题,我在家使用内网通过域名访问也需要经过vps,这个问题可以通过修改本地DNS服务解决,只需要在本地DNS服务里面将*.your_domain解析到内网nginx服务所在的IP上即可。我的路由器固件自带dnsmasq服务,所以可以很方便实现这一需求
内网dnsmasq配置
- 通过ssh连接路由器
- 在 /jffs/scripts 目录下新建一个文件 dns.conf 内容如下
address = /your_domain/192.168.50.120
address =/a.your_domain/192.168.50.140
server=/b.your_domain/114.114.114.114
上面的配置意思是将 your_domain 的子域名都解析到 192.168.50.120 ,将a.your_domain这个子域名解析到192.168.50.140,将 b.your_domain这个子域名交给114.114.114.114 这个dns服务来解析。
- 在 /jffs/scripts 目录下新建 init-start 脚本文件,内容如下:
#!/bin/sh
echo 'set user dns record'
dnsConf=/jffs/configs/dnsmasq.d/dns.conf
if [ ! -f $dnsConf ]; then
ln -s /jffs/scripts/dns.conf $dnsConf
fi
service restart_dnsmasq
给 init-start 加上可执行权限然后执行即可让dns解析生效,路由器重启时该脚本也会自动执行。不直接将dns.conf文件放到/jffs/configs/dnsmasq.d/目录下是因为/jffs/configs/dnsmasq.d/目录下的文件重启后就没了,所以需要在脚本里使用软链接
这样你在内网环境下使用域名访问服务时直接走的就是内部网络了,不会再经过VPS了
https证书自动部署
使用自签名证书时浏览器上的不安全提醒太难看了,而且我自己部署了一个keycloak认证服务,没有安全证书时需要在客户端侧将keycloak服务的证书设置为可信( 详见 ),但这样做显然比较麻烦,特别是客户端多的时候,所以我需要使用安全证书。
个人能获取到的安全证书比较常见的就是Let’s Encrypt的证书了,但Let’s Encrypt的证书有效期只有3个月,所以需要写程序自动申请和续期。
个人用 go 写了一个简单的web程序,可以对 nginx 进行配置管理和自动证书申请,详情可查看 项目github