高橋です。
以前家で趣味でnginxを使ってサーバーを建てたときの話。
Nginxを後ろに控えているWebサーバー(Apache)のリバースプロキシとして構築していました。
構成としてはサブドメインを割り当てたバーチャルホストが複数稼働している環境だったため、nginx側もバーチャルホストに対応すべく下のような設定にしていました。
#省略... server { server_name .example.com; listen 80; listen 443 ssl; ssl on; ssl_certificate /ssl/to/path/example.com/fullchain.pem; ssl_certificate_key /ssl/to/path/example.com/privkey.pem; client_max_body_size 1g; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # クライアントの IP アドレス proxy_set_header X-Forwarded-Host $host; # オリジナルのホスト名。クライアントが Host リクエストヘッダで渡す。 proxy_set_header X-Forwarded-Server $host; # プロキシサーバのホスト名 proxy_set_header X-Real-IP $remote_addr; location / { proxy_pass https://xxx.xxx.xxx.xxx; } } server { server_name .a.example.com; listen 80; listen 443 ssl; ssl on; ssl_certificate /ssl/to/path/a.example.com/fullchain.pem; ssl_certificate_key /ssl/to/path/a.example.com/privkey.pem; client_max_body_size 1g; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # クライアントの IP アドレス proxy_set_header X-Forwarded-Host $host; # オリジナルのホスト名。クライアントが Host リクエストヘッダで渡す。 proxy_set_header X-Forwarded-Server $host; # プロキシサーバのホスト名 proxy_set_header X-Real-IP $remote_addr; location / { proxy_pass https://xxx.xxx.xxx.xxx; } } #省略...<span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
すると..
Bad Requestのエラーが発生。
いろいろ試してもエラーが解消されず頭を抱えていたのですが、調べていたら以下のサイトを発見。
nginx連載6回目: nginxの設定、その4 – TLS/SSLの設定 – インフラエンジニア way
https://heartbeats.jp/hbblog/2012/06/nginx06.html
>sslディレクティブをonに設定すると、SSLが有効になります。ただし、listenディレクティブでsslパラメータを指定したときには不要です。
>ssl on;
>listenディレクティブにsslパラメータを付けると、そのポートでSSLを有効にして待ち受けるようになります。そのポートに関して後述するsslディレクティブをonにしたのと同じ動作になるため、sslディレクティブの記述は不要になります。
>listen 443 ssl;
なるほど、
ssl on;
の記述をしてしまうと
server{}
内で定義されている全ポートにsslが有効になるので、80番ポートでアクセスしてもssl通信と解釈されてしまい、エラーが出ていたようです。
443ポートだけsslにしたい場合は
listen 443 ssl;
とだけ指定しておけば443ポートだけsslを有効にできるようです。
てっきり
“ssl on;”
を入れないとsslが有効にならないものと勘違いしていました(汗
さっきの設定を修正すると以下のようになりました。
#省略... server { server_name .example.com; listen 80; listen 443 ssl; #これは残しておく #ssl on; コメントアウト ssl_certificate /ssl/to/path/example.com/fullchain.pem; ssl_certificate_key /ssl/to/path/example.com/privkey.pem; client_max_body_size 1g; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # クライアントの IP アドレス proxy_set_header X-Forwarded-Host $host; # オリジナルのホスト名。クライアントが Host リクエストヘッダで渡す。 proxy_set_header X-Forwarded-Server $host; # プロキシサーバのホスト名 proxy_set_header X-Real-IP $remote_addr; location / { proxy_pass https://xxx.xxx.xxx.xxx; } } server { server_name .a.example.com; listen 80; listen 443 ssl; #これは残しておく #ssl on; #コメントアウト ssl_certificate /ssl/to/path/a.example.com/fullchain.pem; ssl_certificate_key /ssl/to/path/a.example.com/privkey.pem; client_max_body_size 1g; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # クライアントの IP アドレス proxy_set_header X-Forwarded-Host $host; # オリジナルのホスト名。クライアントが Host リクエストヘッダで渡す。 proxy_set_header X-Forwarded-Server $host; # プロキシサーバのホスト名 proxy_set_header X-Real-IP $remote_addr; location / { proxy_pass https://xxx.xxx.xxx.xxx; } } #省略...
これでnginxを再起動したところ、無事80番ポートの平文通信と443ポートのSSL通信両方ともできるようになりました。
Nginxは非常に細かい設定ができるのが人気の理由の一つですが、その分設定の仕方を理解しておかないとハマってしまうことも…
もっと勉強が必要だなぁ、と感じた瞬間でした…