概要
- Nginxでリバースプロキシなサーバを作った
- 「https://〜」(443ポート)へのアクセスは正常に処理される
- 80番ポートがなぜかhttpsなポートとして処理されてしまう
- 結果的に「400 The plain HTTP request was sent to HTTPS port」が出て困る
前提
- ${内容}は変数的なものです
- サーバOS: Ubuntu 18.04.02 LTS
- Nginx: 1.14.0
したいこと
ドメイン名のみのリンクをクリックされた場合に、ブラウザに関係なくHTTPSなサイトに誘導する
症状
ドメイン名のみのリンクの場合、
- Chrome (72.0.3626.119(64-bit)) はうまく解釈してくれました
- Firefox (65.0.1 (64-bit)) はhttpとして解釈され以下の症状が出ました
リクエスト内容 | curlレスポンス(*1) | requestsレスポンス(*2) |
---|---|---|
http://${ドメイン名}:80 | 301 | 400(*3) |
http://${ドメイン名}:443 | 301 | 400(*3) |
https://${ドメイン名}:80 | x | 200 |
https://${ドメイン名}:443 | 200 | 200 |
*1)
curl ${リクエスト内容} -k # kオプションで証明書エラーを無視
*2)
import requests
requests.packages.urllib3.disable_warnings() # 証明書warningを無視
a = requests.get(${リクエスト内容}, verify=False) # verfy=False: 証明書errorを無視
対処
とりあえず設定箇所を全文
server {
listen 80;
listen 443 ssl;
server_name ${domain};
ssl_certificate ${キーファイルのパス}/2019.crt.pem;
ssl_certificate_key ${キーファイルのパス}/2019.key.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
location / {
proxy_pass http://127.0.0.1:8000; # localhostにすると色々ハマる
}
error_page 497 /497.html;
location = /497.html {
root /var/www/html;
internal;
}
}
(※)エラー内容は400で、レスポンスも400だが、実際には497エラーを400にリダイレクト(?)している模様(´・ω・`)
参考: nginx でエラーページ出すなや〜 "400 The plain HTTP request was sent to HTTPS port"
(※)ポート番号はバックで動いてるアプリのポート番号で。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="ja">
<head><meta charset="utf-8"></head>
<body>
HTTPアクセスはできません。トップページにリダイレクトします。
<script type="text/javascript">
setTimeout(function(){ window.location.href = 'https://${ドメイン名}'; }, 100);
</script>
</body>
</html>
(※)/var/www/html
の所有者・グループがwww-data
にする(sudo chown -R www-data:www-data /var/www/html
)のを忘れないように
その他
割と場当たり的な対処になってしまいました。
調べていると「ssl onをコメントアウトする」対処が多かったですが今回はうまく動作しませんでした。
挙動から察するに
NginxはマウントしたポートをデフォルトでHTTPSなポートとして解釈してしまってるような気がします。
大元の設定ファイルである/etc/nginx/nginx.conf
も確認しましたが、それらしい記述はなさそう。
もう一つ謎なのは、SSLが完全に無い状態で80番ポートのみをマウントすると、ローカルからのリクエストは受け付けるのに、リモートからのリクエストは弾かれました。iptablesの設定は確認したのでAppArmorな気もしますが、ちょっとよく分かりません。。
分かるひと教えて下さい(´・ω・`)