2020.06更新:经Github f1ynng8提出的issues发现本地nginx跳转443配置文件缺少了一个),现已补上,是我手滑给大家造成不便了,抱歉抱歉~

若不想了解具体原理,可点击下方链接直接查看纯享版代码和操作指导

纯享版新鲜出炉,欢迎大家参考~

最近忙于工程没有关注blog的情况,发现很多朋友在考虑如何不暴露端口,请注意,本文是为了容差性兼容不正确配置的后端http和https才会暴露端口的,如果你对你的后端nginx配正确性很有信心,则不需要劫持502响应码,但这样如果发生后端配置错误,将直接抛出502给用户,降低用户体验。请谨慎考虑!

为了方便大家偷懒,我已经把配置文件上传至Github,大家下载的时候麻烦给颗星星吧~

关于后端混杂htpps和http还不想全部在frps端处理http到https还想隐藏端口的问题

这种奇怪要求当然我有考虑到 解决方案有两种:
1.为个别后端为http的站点建立单独一组配置文件,在frps所在的服务器的nginx上反代http到https
2.自动检测后端是否为只有http,这里可以直接调用frps提供的api,用lua批量处理
我个人目前使用后的是第二种,但无奈写blog的时间太少,相关方案的示例我会在下一次摸鱼时总结放出

前言

不知不觉也已经用frp两年了,但刚才在搜索引擎上仍不能找到完美的Nginx反代frp服务端实现https和泛域名/泛解析的方案,某站上甚至每一百余日出现一次解决了没的提问,大部分的实现都是反代了frp的http,在反代https时大多报了502错误,下面给出正确姿势。
再次注意,502错误是后端https配置不正确造成的,完全可以避免,可以不暴露端口!
如果你不能看懂本文内容,请直接点击懒人配置文档,那里有全面的各个环节的配置文件示例
为什么多想了一步想给用户获得更好的体验的容差兼容整到最后大家以为是需要暴露端口
在开始之前先给出基础知识,觉得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的$host$uri$args$request_uri

$host代表请求的主机 $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的监听端口
#注意:这里的error_page 502是为了容差兼容后端的https配置不正确问题,不至于向用户直接抛出异常
#如果你被默认跳转,则证明你的后端https配置有误,并不是本方案必须暴露端口!!!!!!!!!x10086
#懒人模板中有三个环节全部需要遇到的配置文件,如果遇到默认跳转,可留言或比对文件中的配置信息,看差在哪里
}
        #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; #若去除行首的注释符,则需要修改成你想要存放日志的位置
    }
Last modification:June 3rd, 2020 at 10:02 am