目 录CONTENT

文章目录

nginx反向代理frp实现https访问家里nextcloud服务

醉酒的行者
2025-04-13 / 0 评论 / 0 点赞 / 23 阅读 / 0 字

1 环境

在家里电脑部署了一个nextcloud服务,想实现在公网访问,可以利用frp实现内网穿透,用IP端口来访问。但是暴露一个端口不是很优雅,网上林林总总的有一些教程是通过二级域名+端口或三级域名的方式实现的,实践起来存在诸多问题。本文介绍一种较为全面教程,使用Nginx加frp的方式,实现三级域名访问到nextcloud的服务。

一台公网云服务器A, 举例,ip地址:101.12.12.12

家里的内网机器B,部署nextcloud服务,ip地址:192.168.14.64, 部署的端口443

一个顶级域名abc.com,域名做A记录,nextcloud.abc.com 指向公网云服务机器ip 101.12.12.12

软件frp,Frp 是一款开源的反向代理工具,能够帮助我们反向代理出在内网的服务,下载地址,frp下载地址

目标:实现通过https://nextcloud.abc.com访问部署在家里的nextcloud服务。

2 frp部署

frp分为服务端和客户端两部分,公网云服务器上安装服务端,家里内网服务器上安装客户端。

参照frp的官网文安装。

2.1 frp服务端

首先在云服务器A上部署frps服务端,这里的版本是frp_0.38.0_linux_amd64.tar.gz

切换到/root

cd /root

frp_0.38.0_linux_amd64.tar.gz放于/root下,解压

tar -zxf frp_0.38.0_linux_amd64.tar.gz

建立软连接

ln -s /root/frp_0.38.0_linux_amd64 /root/frp

编辑配置frps.ini,修改如下

[common]
bind_addr = 0.0.0.0
#默认为7000端口,需要在公网云服务器的安全组中打开。
bind_port = 7000
#内网穿透http协议的统一访问端口,http配置vhost_http_port,https配置vhost_https_port,
#所有的frp客户端http都是由vhost_http_port代理,所有的https都是由vhost_https_port代理。
vhost_http_port = 28800
vhost_https_port = 28443
#frpc客户端连接Frps服务端时的token[可选,为了增强安全,建议设置]
privilege_token = xxxxxxx
#web端管理控制面板相关配置[可选],37500也是需要在公网云服务器的安全组打开,如果不用再次进行关闭
dashboard_port = 37500
dashboard_user = admin
dashboard_pwd = xxxxxxx

如果需要启动,直接使用/root/frp/frps -c /root/frp/frps.ini 命令启动即可。

可选使用systemd控制frps服务端的启动,停止,后台运行和开机自启动。

创建/root/frps.service文件,添加如下配置

[Unit]
# 服务名称,可自定义
Description=Frp Server Service
After=network.target

[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart=/root/frp/frps -c /root/frp/frps.ini
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

将该文件移动到/etc/systemd/system,

mv /root/frps.service /etc/systemd/system

使用systemd管理frps服务

#启动frps服务
systemctl start frps
#关闭frps服务
systemctl stop frps
#重启frps服务
systemctl restart frps
#查看frps状态
systemctl status frps
#开启自启动frps
systemctl enable frps

2.2 frp客户端

登录到家里的部署nextcloud内网服务器上,将frp_0.38.0_linux_amd64.tar.gz上传到/root下

切换到/root

cd /root

frp_0.38.0_linux_amd64.tar.gz放于/root下,解压

tar -zxf frp_0.38.0_linux_amd64.tar.gz

建立软连接

ln -s /root/frp_0.38.0_linux_amd64 /root/frp

编辑frpc.ini文件,修改如下:

[common]
#公网云服务器的ip地址
server_addr = 101.12.12.12
#在frps.ini中配置的端口
server_port = 7000
#在frps.ini中配置的token
privilege_token = xxxxx
# 启用admin端口,提供API服务,用于客户端配置文件热加载[可选]
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_pwd = xxxxx

#nextcloud的web配置方式
[nextcloud]
#这里采用https方式
type = https
#本机的内网ip地址
local_ip = 192.168.14.64
#nextcloud的服务端口
local_port = 443
#配置在frps.ini中配置的vhost_https_port
remote_port = 28443
#这里是解析到公网101.12.12.12的域名
custom_domains = nextcloud.abc.com
#启用加密[可选]
use_encryption = true
#启用压缩[可选]
use_compression = true

如果需要启动,直接使用/root/frp/frpc -c /root/frp/frpc.ini 命令启动即可。

可选使用systemd控制frps服务端的启动,停止,后台运行和开机自启动。

创建/root/frpc.service文件,添加如下配置

[Unit]
# 服务名称,可自定义
Description=Frp client Service
After=network.target

[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=5s
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart=/root/frp/frpc -c /root/frp/frpc.ini
# reload配置文件
ExecReload=/root/frp/frpc reload -c /root/frp/frpc.ini
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

将该文件移动到/etc/systemd/system,

mv /root/frpc.service /etc/systemd/system

使用systemd管理frpc服务

#启动frpc服务
systemctl start frpc
#关闭frpc服务
systemctl stop frpc
#重启frpc服务
systemctl restart frpc
#查看frpc状态
systemctl status frpc
#开启自启动frpc
systemctl enable frpc

3 宝塔添加nginx代理

在公网云服务器上,使用宝塔安装nginx,版本是nginx 1.22.1,添加反向代理。如下图所示:

ssl域名申请完毕后,使用https://nextcloud.abc.com访问报502网关异常。这是由于使用nginx反代https的引发的。接下来详细阐述该问题的解决思路。

3.1 nginx反代https 502异常

查询了相关资料发现很少。如果没有必须使用 Nginx 的需求,可以直接使用 frp 绑定80和443端口即可。 如果必须使用 Nginx 作为前端(比如反向代理服务器上还有其他网站),这时你会发现常规 https 访问就会直接返回502了。

如下nginx的一份样例配置:

server {
    listen 80;
    
    listen 443 ssl http2 ;
    listen [::]:80;
    
    listen [::]:443 ssl http2 ;
    
    server_name nextcloud.abc.com;
    ssl_certificate    /www/server/panel/vhost/cert/nextcloud.abc.com/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/nextcloud.abc.com/privkey.pem;
  
    location ^~ / {  
      proxy_pass https://127.0.0.1:28443;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Real-Port $remote_port;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Port $server_port;
      proxy_set_header REMOTE-HOST $remote_addr;
      proxy_ssl_server_name on;
      proxy_connect_timeout 60s;
      proxy_send_timeout 600s;
      proxy_read_timeout 600s; 
    }
}

看上去还是很合理的,但是访问就会出现502,在客户端和nginx日志中也没找到有用的信息。

frp 671 issue找到了解决思路。

个人推测:frp在反向代理https的时候,因为Nginx已经处理过了https的握手信息。所以, Frp无法获取到SNI信息,导致发送请求的时候就是不完整的https请求。如果改成http或者tcp反向代理都能成功,个人认为是Frp的问题,访问的域名变成127.0.0.1,没有SNI信息。因此,在上面那份配置的情况下,可以通过域名+端口号成功访问。

解决方案:

在反向代理前使用动态域名解析。具体如下:

由于在公网云服务器使用的ubuntu系统,ubuntu默认使用了systemd-resolved的DNS服务,因此在公网云服务器的/etc/hosts中加入127.0.0.1 nextcloud.abc.com映射,systemd-resolved默认会读取/etc/hosts文件,完成域名的解析服务。

使用resolvectl query命令检测解析是否生效

resolvectl query nextcloud.abc.com

若显示 nextcloud.abc.com: 127.0.0.1表示配置成功。

如果没有成功,可以强制刷新生效,需要重启systemd-resolved服务。

systemctl restart systemd-resolved
改造后的nginx配置文件如下:

server {
    listen 80;
    
    listen 443 ssl http2 ;
    listen [::]:80;
    
    listen [::]:443 ssl http2 ;
    
    server_name nextcloud.abc.com;
    ssl_certificate    /www/server/panel/vhost/cert/nextcloud.abc.com/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/nextcloud.abc.com/privkey.pem;
  
    location ^~ / {  
      resolver         127.0.0.53;#使用systemd-resolved动态域名解析
      proxy_pass https://$host:28443; #改造为https://$host:28443
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Real-Port $remote_port;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Port $server_port;
      proxy_set_header REMOTE-HOST $remote_addr;
      proxy_ssl_server_name on;
      proxy_connect_timeout 60s;
      proxy_send_timeout 600s;
      proxy_read_timeout 600s; 
    }
}

在宝塔中具体修改如下:


记得重新加载nginx配置。

再次访问https://nextcloud.abc.com, 就正常了。

4 总结

虽然整体上配置和实践的过程踩了很多坑,但是,通过不断查阅资料,完善资料,提升了自身的能力。上述过程可以扩展很多的网站。同时,也为了想把web服务部署在家里的小伙伴们提供了一种思路和方案,控制了成本。希望可以帮助到各位,如果疑问,欢迎来信。

0

评论区