作者博客上的原文链接:原文链接
作者博客上的懒人模板链接:懒人模板
注意:本方案完全可以隐藏端口,劫持502响应码是为了容差兼容后端https配置不正确的情况,不至于向用户抛出502异常。如果你配置过后默认就被跳转,说明你的后端配置有误,请点击作者博客上的懒人模板链接查看包括前后端nginx和frp的完整配置信息及说明。
前言
不知不觉也已经用frp两年了,但刚才在搜索引擎上仍不能找到完美的Nginx反代frp服务端实现https和泛域名/泛解析的方案,某站上甚至每一百余日出现一次解决了没的提问,大部分的实现都是反代了frp的http,在反代https时大多报了502错误,下面给出正确姿势。
在开始之前先给出基础知识,觉得OK的同志可以跳过
基础知识1:nginx的https强制跳转
可在同一个server中同时listen http和ssl http2后通过nginx的if语句进行跳转
代码及解析如下
server
{
listen 80; #监听http端口,端口号80
listen 443 ssl http2; #监听https端口,端口号443
server_name *.domain.com; #填写你需要的泛域名
charset utf-8;
if ($server_port !~ 443){ #若端口号不为443
rewrite ^(/.*)$ https: #$host$1 permanent; #302跳转到https地址
error_page 497 https://$host$request_uri; #497用于http到https的强制跳转
ssl_certificate ./fullchain; #ssl证书的fullchain(含公钥的完整证书链)
ssl_certificate_key ./privkey; #ssl证书的privkey(私钥)
ssl_protocols TLSv1.1 TLSv1.2;
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;
}
基础知识2:nginx的urirequest_uri
request_uri代表请求的uri $uri代表包含args的uri
如:
https://www.baidu.com/s?&wd=ray8.cc&ie=utf-8
$host为www.baidu.com
$request_uri为/s?&wd=ray8.cc&ie=utf-8
$uri为/
$args为s?&wd=ray8.cc&ie=utf-8
基础知识3:nginx的http_realip_module模块
准备专门开一篇文章,待填坑。
反向代理流程图
流程图中Server1部分为正常反向代理的https
Server2部分为后端使用http时的反向代理http到https
配置文件及解析
流程图中server1部分为
server
{
listen 80;
listen 443 ssl http2;
server_name *.domain.com; #填写你需要的泛域名
charset utf-8;
if ($server_port !~ 443){
rewrite ^(/.*)$ https:
error_page 497 https://$host$request_uri;
ssl_certificate ./fullchain; #需要修改成证书公钥对应位置
ssl_certificate_key ./privkey; #需要修改成证书私钥对应位置
ssl_protocols TLSv1.1 TLSv1.2;
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;
}
location / {
resolver 8.8.8.8;
proxy_ssl_server_name on;
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;
proxy_set_header Host $host;
proxy_pass https://$host:5678; #端口号(5678)替换为你frps的https监听端口
error_page 502 http://$host:6666/$request_uri; #端口号(6666)替换为你下一个server的监听端口
}
#access_log /.log; #若去除行首的注释符,则需要修改成你想要存放日志的位置
}
流程图中server2部分为:
server
{
listen 6666;
listen 7777 ssl http2;
server_name *.domain.com; #填写你需要的泛域名
charset utf-8;
if ($server_port !~ 7777){
rewrite ^(/.*)$ https:
error_page 497 https://$host$request_uri;
ssl_certificate ./fullchain; #需要修改成证书公钥对应位置
ssl_certificate_key ./privkey; #需要修改成证书私钥对应位置
ssl_protocols TLSv1.1 TLSv1.2;
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;
}
location / {
resolver 8.8.8.8;
proxy_ssl_server_name on;
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;
proxy_set_header Host $host;
proxy_pass https://$host:1234; #端口号(1234)替换为你frps的http监听端口
}
#access_log /.log; #若去除行首的注释符,则需要修改成你想要存放日志的位置
}