理科系の勉強日記

Linux/Ubuntu/Mac/Emacs/Computer vision/Robotics

自己証明書とNGINXでhttps通信

nginxでリバースプロキシができたので、次はフロントのサーバまでの通信をHTTPSにしてみたいと思います。簡単のため証明書はオレオレ証明書(自己証明書)を使いたいですが、そのままだとブラウザに危険サイトだと怒られるので、まずそれの設定をします。なおOSXでの設定です。

前準備

わかりやすくするために、/private/etc/hostsを編集してIPアドレスに名前をつけます。

127.0.0.1  localhost
255.255.255.255 broadcasthost
::1             localhost
192.168.3.3 airbell.com # 追記

自己証明書の発行

証明書の中に接続先の方法を埋め込みます。そのためのファイルname.txtを作成し、server.crtを作るときにそれを読み込みます。

$ echo subjectAltName = DNS:airbell.com, IP:192.168.3.3 > name.txt
$ openssl genrsa 2048 > server.key
$ openssl req -new -key server.key -subj "/C=JP/ST=Some-State/O=Some-Org/CN=airbell.com" > server.csr
$ openssl x509 -days 3650 -req -extfile name.txt -signkey server.key < server.csr > server.crt

自己証明書の登録

server.crtをクリックしてKey chainがSystemになっていることを確認してAdd。Keychain Accessの設定画面でつくった自己証明書をダブルクリック、TrustをAlways trustに変更すればOKです。

f:id:kenbell1988:20200412141254p:plain
自己証明書の登録

NGINXの設定

リバースプロキシ用に設定したnginx.confをSSLが使えるように以下のように修正しました。設定変更後、sudo nginxで再起動をします。

http {
        # 省略

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        server {

             listen 8111 ssl;
             server_name 192.168.3.3;
             ssl_certificate /path/to/server.crt; # サーバー証明書のパス
             ssl_certificate_key /path/to/server.key; # 秘密鍵のパス

            # 省略
       }
}

確認

ブラウザでアクセスできました。 f:id:kenbell1988:20200412142615p:plain

続いて、リバースプロキシのバックエンドのFlaskにもアクセスしてみましょう。HTTPではエラーですが、HTTPSだと結果が帰ってきました。 Flask側には何もSSLの設定はいれていませんが、フロントのサーバが壁となってくれることが期待できます。

$ curl http://airbell.com:8111/API_1 -X GET                                                                                                            
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.17.9</center>
</body>
</html>

$ curl https://airbell.com:8111/API_1 -X GET                                                                                                             
{
  "message": "Response from flask server[API_1]"
}