Flask+Nginx反向代理ssl報(bào)錯(cuò)The plain HTTP request was sent to HTTPS port解決辦法

2022年6月24日01:15:38 發(fā)表評論 6,292 ℃

最近通過Nginx反向代理一個(gè)網(wǎng)站,環(huán)境為Flask+uwsgi+Nginx反向代理,當(dāng)部署證書并設(shè)置強(qiáng)制跳轉(zhuǎn)https以后,在瀏覽器輸入:blog.amd5.cn訪問出現(xiàn)了“400 Bad Request The plain HTTP request was sent to HTTPS port”錯(cuò)誤,如下圖:

Flask+Nginx反向代理ssl報(bào)錯(cuò)The plain HTTP request was sent to HTTPS port解決辦法

一開始懷疑自己的配置有問題,反復(fù)確認(rèn)和對比以后,排除配置問題。

于是網(wǎng)上搜索了相關(guān)報(bào)錯(cuò),找到了解決方案,出現(xiàn)這種報(bào)錯(cuò)的主要原因是:

因?yàn)镠TTP請求被發(fā)送到HTTPS端口,這種報(bào)錯(cuò)多出現(xiàn)在Nginx既處理HTTP請求又處理HTTPS請求的情況。

正常80端口訪問應(yīng)該是:http://blog.amd5.cn:80/login

正常開啟HTTPS以后443端口訪問應(yīng)該是:https://blog.amd5.cn:443/login

但是此時(shí)卻變成了: http://blog.amd5.cn:443/login,即HTTP請求被發(fā)送到HTTPS端口。

如果我直接在瀏覽器輸入:https://blog.amd5.cn,卻能正常跳轉(zhuǎn)到https://blog.amd5.cn/login

直接輸入http://blog.amd5.cn/login,也能正常跳轉(zhuǎn)到https://blog.amd5.cn/login

為什么會(huì)有這樣的問題呢,經(jīng)過排查原來是多次重定向?qū)е碌?,主要是因?yàn)樵谑褂肍lask-Login驗(yàn)證登錄的時(shí)候,如果未登錄,會(huì)重定向到登錄頁面。

通過瀏覽器開發(fā)者工具,可以看到,當(dāng)我瀏覽器輸入blog.amd5.cn,第一次重定向?yàn)閔ttp->https:

Request URL: https://blog.amd5.cn/
Request Method: GET
Status Code: 302 FOUND
Remote Address: 127.0.0.1:443
Referrer Policy: strict-origin-when-cross-origin

然后第二次重定向?yàn)椋?->/login:

Request URL: http://blog.amd5.cn:443/login
Request Method: GET
Status Code: 400 Bad Request
Remote Address: 127.0.0.1:443
Referrer Policy: strict-origin-when-cross-origin

簡單來說就是:當(dāng)?shù)谝淮握埱笤噲D通過HTTP訪問網(wǎng)站blog.amd5.cn,這個(gè)請求被重定向到HTTPS。于是Nginx預(yù)計(jì)使用SSL(443端口)交互,但原來的請求(通過端口80接收,即檢查到未登錄,需要從/跳轉(zhuǎn)到/login)是普通的HTTP請求,于是會(huì)產(chǎn)生錯(cuò)誤。

解決方法是在原來的配置上面加兩個(gè)參數(shù):

proxy_set_header X-Forwarded-Proto https; # X-Forwarded-Proto(XFP)報(bào)頭是用于識(shí)別協(xié)議HTTP或HTTPS的,即用戶客戶端實(shí)際連接到代理或負(fù)載均衡的標(biāo)準(zhǔn)報(bào)頭。
proxy_redirect http:// https://  # proxy_redirect 該指令用來修改被代理服務(wù)器返回的響應(yīng)頭中的Location頭域和“refresh”頭域,也就是把http協(xié)議改成https協(xié)議。

添加以后完整的配置如下:

server {
listen 443 ssl;
ssl_certificate /conf/ssl/blog.amd5.cn.pem;
ssl_certificate_key /conf/ssl/blog.amd5.cn.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
server_name  blog.amd5.cn;
#代理配置
location /{
proxy_set_header X-Original-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host blog.amd5.cn:$server_port;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://127.0.0.1:5000/;
proxy_redirect http:// https://;
}
}
server{
listen 80 ;
server_name blog.amd5.cn;
#代理配置
location /{
proxy_set_header X-Original-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host blog.amd5.cn:$server_port;
proxy_pass http://127.0.0.1:5000/;
}
add_header X-Cache $upstream_cache_status;
proxy_cache_key $host$uri$is_args$args;
if ($scheme = http) {
    return 301 https://$host$uri?$args;
 }
}

再次測試訪問正常:

Flask+Nginx反向代理ssl報(bào)錯(cuò)The plain HTTP request was sent to HTTPS port解決辦法

兩次請求:

Request URL: https://blog.amd5.cn/
Request Method: GET
Status Code: 302 FOUND
Remote Address: 127.0.0.1:443
Referrer Policy: strict-origin-when-cross-origin

Request URL: https://blog.amd5.cn/login
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:443
Referrer Policy: strict-origin-when-cross-origin
【騰訊云】云服務(wù)器、云數(shù)據(jù)庫、COS、CDN、短信等云產(chǎn)品特惠熱賣中

發(fā)表評論

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: