0. 前言
对于没有公网IP的家庭网络中,要访问局域网中的服务,一般需要通过内网穿透+一台有公网IP的服务器实现,将局域网的服务通过IP+端口的形式对外暴露,这种方式需要公网服务器开放相应端口,不安全也不美观。本文介绍通过二级域名的形式实现对局域网服务的访问。
1.前提条件
(1)公网IP的服务器
可以使用阿里云或腾讯云的ECS或轻量级应用服务器等。假设IP地址为1.1.1.1;假设http访问端口为12345、https端口为67890,需要在防火墙中开放这几个端口。
(2)顶级域名
假设abc.com,假设二级域名为frp.abc.com,需要添加如下A记录将解析指向公网服务器的IP地址:1.1.1.1:
*.frp
*
frp
(3)SSL证书
免费的SSL证书一般时效为90天,可以通过自动化部署证书的工具实现定期生成证书。例如
https://github.com/certd/certd
(4)实现目标
通过a.frp.abc.com、b.frp.abc.com等访问局域网的服务,其中a.frp.abc.com中的a是随便起的web服务的名字。
2.在公网服务器上安装nginx
对不同操作系统安装步骤不同,比较简单不再赘述。
3.安装 FRP
一键部署frp:
https://github.com/mvscode/frps-onekey
4.nginx配置
(1)在/etc/nginx/sites-available/中新建一个frps.conf的配置文件,内容如下:
server {
# 监听http端口
listen 12345;
# 域名配置 记得一定要加上*.frp.abc.com + frp.abc.com这个,只加frp.abc.com是不行的,无法支持泛域名做sub模式
server_name *.frp.abc.com frp.abc.com;
location / {
proxy_pass http://127.0.0.1:12123; #frps配置中的vhostHTTPPort
# 这个Host的header一定要加,不然转发后frp拿不到通过哪个域名访问的,导致转发失败
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
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 $scheme;
}
}
server {
# 监听https端口
listen 67890 ssl fastopen=3 reuseport;
# 域名配置 记得一定要加上*.frp.abc.com + frp.abc.com这个,只加frp.abc.com是不行的,无法支持泛域名做sub模式
server_name *.frp.abc.com frp.abc.com;
# 处理 HTTP 请求,将其重定向到 HTTPS
if ($scheme = http) {
return 301 https://$host$request_uri;
}
ssl_certificate /data/certd/cert.crt; # SSL 证书路径
ssl_certificate_key /data/certd/cert.key; # SSL 密钥路径
# 引入ssl配置文件
include snippets/ssl-params.conf;
location / {
resolver 223.5.5.5; # 阿里公共DNS
proxy_pass https://127.0.0.1:45456; #frps配置中的vhostHTTPSPort
# 对反代连接启用 SNI 支持
proxy_ssl_server_name on;
# 设置 SNI 名称为客户端请求的主机名
proxy_ssl_name $host;
# 这个Host的header一定要加,不然转发后frp拿不到通过哪个域名访问的,导致转发失败
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
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 $scheme;
}
}
(2)/etc/nginx/snippets目录中新建ssl-params.conf文件,内容如下:
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 60m;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 223.5.5.5 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers “EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4”;
# 以下配置来自 [提高安全性的最佳 Nginx 配置](https://godruoyi.com/posts/best-nginx-configuration-for-improved-security),建 议参考。
server_tokens off;
add_header Strict-Transport-Security “max-age=31536000;includeSubDomains;preload”;
add_header X-Frame-Options deny;
add_header X-Content-Type-Options nosniff;
add_header x-xss-protection “1; mode=block”;
add_header Content-Security-Policy “default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’ blob: https:; connect-src ‘self’ https:; img-src ‘self’ data: https: blob:; style-src ‘unsafe-inline’ https:; font-src https:”;
5.frps配置
通过frps-onekey一键部署的frps路径在/usr/local/frps,配置文件为frps.toml,基本配置参考如下,其余配置根据需要参考官方配置说明进行配置:
bindAddr = “0.0.0.0”
bindPort = 12121
kcpBindPort = 12121
quicBindPort = 45457
vhostHTTPPort = 12123 #http端口
vhostHTTPSPort = 45456 #https端口
log.to = “frps.log”
log.level = “info”
log.maxDays = 3
auth.method = “token”
auth.token = “111111111” #自行生成
subDomainHost = “frp.abc.com”
6.frpc配置
(1)OpenWrt
(2)手动安装frpc
[common]
server_addr = 1.1.1.1 # 公网服务器的IP地址
server_port = 12121 # frps.ini文件中填写的端口
token = 111111111 # 填写与frps.ini文件中一样的token
admin_addr = 127.0.0.1 # 启用 admin 端口,用于提供 API 服务,可以用于客户端配置文件热加载
admin_port = 7400 # adnin 具体端口
以下为 web 服务的配置方式
[web]
use_encryption = false
use_compression = false
local_ip = 192.168.1.1
local_port = 80
type = http
subdomain = a #可以通过http://a.frp.abc.com:12123访问
[web2]
use_encryption = false
use_compression = false
local_ip = 192.168.1.2
subdomain = b #可以通过https://a.frp.abc.com:45456访问
type = https
local_port = 55555 #局域网https服务对应的端口
7.启动nginx
(1)验证配置是否正确
nginx -t
如有问题,请检查配置文件是否正确
(2)启动nginx
systemctl restart nginx
8.启动frps
frps restart
观察/usr/local/frps/frps.log日志是否有问题
9.启动frpc
如果是基于OpenWrt界面配置的,直接保存并应用。
如果是手动安装的如下方式启动:
frpc -c frpc.toml
10.域名验证
(1)http://a.frp.abc.com:12123访问
(2)https://a.frp.abc.com:45456访问
可以通过tail -f /var/log/nginx/access.log或tail -f /var/log/nginx/error.log查看日志。