作者博客上的原文鏈接:原文鏈接
作者博客上的懶人模板鏈接:懶人模板
注意:本方案完全可以隱藏端口,劫持502響應(yīng)碼是為了容差兼容后端https配置不正確的情況,不至于向用戶拋出502異常。如果你配置過后默認(rèn)就被跳轉(zhuǎn),說明你的后端配置有誤,請點擊作者博客上的懶人模板鏈接查看包括前后端nginx和frp的完整配置信息及說明。
前言
不知不覺也已經(jīng)用frp兩年了,但剛才在搜索引擎上仍不能找到完美的Nginx反代frp服務(wù)端實現(xiàn)https和泛域名/泛解析的方案,某站上甚至每一百余日出現(xiàn)一次解決了沒的提問,大部分的實現(xiàn)都是反代了frp的http,在反代https時大多報了502錯誤,下面給出正確姿勢。
在開始之前先給出基礎(chǔ)知識,覺得OK的同志可以跳過
基礎(chǔ)知識1:nginx的https強制跳轉(zhuǎn)
可在同一個server中同時listen http和ssl http2后通過nginx的if語句進行跳轉(zhuǎn)
代碼及解析如下
server
{
listen 80; #監(jiān)聽http端口,端口號80
listen 443 ssl http2; #監(jiān)聽https端口,端口號443
server_name *.domain.com; #填寫你需要的泛域名
charset utf-8;
if ($server_port !~ 443){ #若端口號不為443
rewrite ^(/.*)$ https: #$host$1 permanent; #302跳轉(zhuǎn)到https地址
error_page 497 https://$host$request_uri; #497用于http到https的強制跳轉(zhuǎn)
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;
}
基礎(chǔ)知識2:nginx的
uri
request_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
基礎(chǔ)知識3:nginx的http_realip_module模塊
準(zhǔn)備專門開一篇文章,待填坑。
反向代理流程圖

image
流程圖中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; #需要修改成證書公鑰對應(yīng)位置
ssl_certificate_key ./privkey; #需要修改成證書私鑰對應(yīng)位置
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監(jiān)聽端口
error_page 502 http://$host:6666/$request_uri; #端口號(6666)替換為你下一個server的監(jiān)聽端口
}
#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; #需要修改成證書公鑰對應(yīng)位置
ssl_certificate_key ./privkey; #需要修改成證書私鑰對應(yīng)位置
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監(jiān)聽端口
}
#access_log /.log; #若去除行首的注釋符,則需要修改成你想要存放日志的位置
}