nginxでSSL設定をするときに気を付けたいこと

takahashi 著者:takahashi

nginxでSSL設定をするときに気を付けたいこと

高橋です。

以前家で趣味で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は非常に細かい設定ができるのが人気の理由の一つですが、その分設定の仕方を理解しておかないとハマってしまうことも…

もっと勉強が必要だなぁ、と感じた瞬間でした…

  • この記事いいね! (0)

著者について

takahashi

takahashi administrator

Webエンジニア。 趣味で自宅サーバーを稼働中。 ファンタジーが好き。