SSLに対応したNGINXリバースプロキシを構築する手順

## まずはじめに
`LGTM` 乞食なのでよろしくお願いします¥

## この記事の目的

Nginxを使ったリバースプロキシをLet's Encryptの無料証明書付きで構築していきます。
独自ドメインの /(root) ディレクトリにアクセスしたとき、Qiitaのトップページにアクセスする設定をしていきます。

## Overview
1. NGINXとLet's Encryptの紹介
2. インフラの準備（AlibabaCloud）
3. NGINXリポジトリの追加〜NGINXのインストール
4. NGINXの設定（リバースプロキシ）
5. SSL証明書（Let's Encrypt）の準備
6. SSL証明書の設定
7. 最後に

## NGINXとLet's Encryptの紹介
### NGINX
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/3f56c2a0-7782-7a33-ea53-553a5ae82703.png)


#### Wikipediaより

> **nginx**（「エンジンエックス」のように発音[[3\]](https://ja.wikipedia.org/wiki/Nginx#cite_note-3)）は、[フリーかつオープンソース](https://ja.wikipedia.org/wiki/FLOSS)な[Webサーバ](https://ja.wikipedia.org/wiki/Webサーバ)である。処理性能・高い並行性・メモリ使用量の小ささに焦点を当てて開発されており、[HTTP](https://ja.wikipedia.org/wiki/HTTP), [HTTPS](https://ja.wikipedia.org/wiki/HTTPS), [SMTP](https://ja.wikipedia.org/wiki/SMTP), [POP3](https://ja.wikipedia.org/wiki/POP3), [IMAP](https://ja.wikipedia.org/wiki/IMAP)の[リバースプロキシ](https://ja.wikipedia.org/wiki/リバースプロキシ)の機能や、[ロードバランサ](https://ja.wikipedia.org/wiki/ロードバランサ)、HTTPキャッシュなどの機能も持つ。
>
> nginxは、[BSDライクライセンス](https://ja.wikipedia.org/wiki/BSDライセンス)でリリースされており、[Linux](https://ja.wikipedia.org/wiki/Linux)、[BSD系](https://ja.wikipedia.org/wiki/BSDの子孫)OS、[macOS](https://ja.wikipedia.org/wiki/MacOS)、[Solaris](https://ja.wikipedia.org/wiki/Solaris)、[AIX](https://ja.wikipedia.org/wiki/AIX)、[HP-UX](https://ja.wikipedia.org/wiki/HP-UX)、[Microsoft Windows](https://ja.wikipedia.org/wiki/Microsoft_Windows)で動作する。2004年に[Igor Sysoev](https://ja.wikipedia.org/wiki/イーゴリ・シソエフ)によって公開された。現在はNGINX Plusとしてnginxのエンタープライズ版の販売やサポートを行っているNginx, Inc.が管理している。



> nginxは静的コンテンツ（つまりサーバ上のファイル）を高速に配信するように設計されている。また、[リバースプロキシ](https://ja.wikipedia.org/wiki/リバースプロキシ)の機能を持つため、背後にWebアプリケーションサーバを配置して動的なコンテンツを配信したり、ソフトウェア[ロードバランサ](https://ja.wikipedia.org/wiki/サーバロードバランス)[[4\]](https://ja.wikipedia.org/wiki/Nginx#cite_note-4)やHTTPキャッシュとしても使うこともできる。各種の[ウェブアプリケーション](https://ja.wikipedia.org/wiki/ウェブアプリケーション)用インターフェース（[FastCGI](https://ja.wikipedia.org/wiki/FastCGI), [uWSGI](https://ja.wikipedia.org/w/index.php?title=UWSGI&action=edit&redlink=1)（[英語版](https://en.wikipedia.org/wiki/uWSGI)）, [Phusion Passenger](https://ja.wikipedia.org/wiki/Phusion_Passenger)など）も標準でサポートしている。
>
> [Apache HTTP Server](https://ja.wikipedia.org/wiki/Apache_HTTP_Server)がリクエストの処理にデフォルトで[スレッド](https://ja.wikipedia.org/wiki/スレッド_(コンピュータ))や[プロセス](https://ja.wikipedia.org/wiki/プロセス)指向のアプローチを用いている一方で、nginxは[非同期](https://ja.wikipedia.org/w/index.php?title=非同期システム&action=edit&redlink=1)（[英語版](https://en.wikipedia.org/wiki/Asynchronous_system)）の[イベント駆動](https://ja.wikipedia.org/wiki/イベント駆動)アプローチを用いている。イベント駆動によるアプローチは、高負荷下において、より予測可能なパフォーマンスを提供すると考えられている[[5\]](https://ja.wikipedia.org/wiki/Nginx#cite_note-5)。



### Let's Encrypt
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/225b9223-1926-2eb5-dee5-09acaa8fa6c3.png)

#### Wikipediaより

> **Let's Encrypt**（レッツ・エンクリプト）は、[2016年](https://ja.wikipedia.org/wiki/2016年)4月に正式に開始された[認証局](https://ja.wikipedia.org/wiki/認証局)である[[1\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-softpedia-launch-1)。自動化された発行プロセスにより、[TLS](https://ja.wikipedia.org/wiki/Transport_Layer_Security)の[X.509](https://ja.wikipedia.org/wiki/X.509)[証明書](https://ja.wikipedia.org/wiki/公開鍵証明書)の発行を無料で行っている[[2\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-Lets-Encrypt-Aims-to-Improve-Security-2)[[3\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-Launching-2015-CA-to-Encrypt-Entire-Web-3)。



> Let's Encryptは、すべての[Webサーバ](https://ja.wikipedia.org/wiki/Webサーバ)への接続を暗号化することを目指したプロジェクトである[[4\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-4)。支払い、サーバ設定、メールによる確認、証明書の更新といった作業を省略することで、TLS暗号化における設定や保守の複雑さを大幅に削減することを意図している[[5\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-ZDNet20141109-5)。[Linux](https://ja.wikipedia.org/wiki/Linux)のWebサーバーでは、[HTTPS](https://ja.wikipedia.org/wiki/HTTPS)の暗号化の設定および証明書の入手・更新がわずか2つのコマンドによって可能である[[6\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-heise20141119-6)[[7\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-SDTimes-7)。
>
> このため、Let's Encryptのソフトウェアパッケージは[Debian](https://ja.wikipedia.org/wiki/Debian)や[Ubuntu](https://ja.wikipedia.org/wiki/Ubuntu)の公式リポジトリに含まれている[[8\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-debian_package1-8)[[9\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-debian_package2-9)。[Mozilla](https://ja.wikipedia.org/wiki/Mozilla)や[Google](https://ja.wikipedia.org/wiki/Google)などの主要なブラウザベンダーが現在主導している[HTTPS](https://ja.wikipedia.org/wiki/HTTPS)重視の方針は、Let's Encryptの利用可能性を見込んだものである[[10\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-deprecating_HTTP_Mozilla-10)[[11\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-deprecating_HTTP_Chromium-11)。このプロジェクトは、ウェブ全体の暗号化接続を達成する可能性のあるものであると認められている[[12\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-Moody-12)。
>
> 完全自動化のため、ドメイン認証 (Domain Validation: DV) 型証明書のみ発行しており、企業認証 (Organization Validation: OV) 型やEV (Extended Validation) 型は提供していない[[13\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-ZDNet20150409-13)。日本語ドメインなどの[国際化ドメイン名](https://ja.wikipedia.org/wiki/国際化ドメイン名)には対応する[[14\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-14)。
>
> Let's Encryptは、できる限り透明化することで信頼性を維持し、攻撃から保護するねらいがある。このため定期的に報告書を発行し[[15\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-transparency_report-15)、全ての[ACME](https://ja.wikipedia.org/wiki/Automated_Certificate_Management_Environment)トランザクションを公開し（たとえば Certificate Transparency などにより）、できる限りオープン標準とフリーソフトウェアを使用している[[6\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-heise20141119-6)。
>
> ACME v2と[ワイルドカード証明書](https://ja.wikipedia.org/w/index.php?title=ワイルドカード証明書&action=edit&redlink=1)（[英語版](https://en.wikipedia.org/wiki/Wildcard_certificate)）のサポートが2018年3月から開始された[[16\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-16)。



> Let's Encryptの中間証明書は[IdenTrust](https://ja.wikipedia.org/w/index.php?title=IdenTrust&action=edit&redlink=1)（[英語版](https://en.wikipedia.org/wiki/IdenTrust)）の[ルート証明書](https://ja.wikipedia.org/wiki/ルート証明書)によってクロス署名されており、幅広いプラットフォームに対応している。ただし、[フィーチャーフォン](https://ja.wikipedia.org/wiki/フィーチャーフォン)や[ニンテンドー3DS](https://ja.wikipedia.org/wiki/ニンテンドー3DS)など一部の端末は対応していない[[17\]](https://ja.wikipedia.org/wiki/Let's_Encrypt#cite_note-17)。




## インフラの準備（AlibabaCloud）
- GUIでECSを購入している前提です。
※サーバーさえ用意できれば何のプラットフォームでもOKです。

```
[root@nginx-redo /]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
```


## NGINXの設定（リバースプロキシ）
- NGINXをインストールするためのyumリポジトリを追加していきます。

```
[root@nginx-redo]# vim /etc/yum.repos.d/nginx.repo 
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
```

- NGINXをyum installします。

```
[root@nginx-redo]# yum -y install nginx
```


## NGINXの設定（リバースプロキシ）
- Nginxの設定ファイルが存在する/etc/nginx/conf.dに移動
- ファイル確認
- default.confをcpしてserver.confとして新しく設定

```
[root@nginx-redo ~]# cd /etc/nginx/conf.d
[root@nginx-redo conf.d]# ls
default.conf
[root@nginx-redo conf.d]# cp default.conf server.conf
[root@nginx-redo conf.d]# ls
default.conf  server.conf
```

- vimで`server.conf`を編集していきます。

#### デフォルトの状態

```
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
```



#### テスト用に編集した状態
- コメントアウトは分かりづらいのですべて削除
- listenポートを`443`に変更
- ssl を有効化（後ほどLet's Encrypteで設定しますが、先行してここでpathを入れてしまいます。）
- `location /`でQiitaのトップページを指定
  - ブラウザバーで、https://ドメイン名:443/でGETリクエストが合った場合に、proxy_passで設定したqiitaのトップページ(https://qiita.com)を返す様になっています。
- location /.well-known
  - ここではcertbotがアクセスした際の参照するディレクトリを指定しています

```
server {
    listen  443;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/[YOUR DOMAIN]/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/[YOUR DOMAIN]/privkey.pem;
    server_name  localhost;
    
    location /.well-known {
        root  /var/www/tnoce/;
     }
     
    location / {
        proxy_pass https://qiita.com:443/;
     }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

```



## SSL証明書（Let's Encrypt）の準備
#### 注意点
進まれる前に以下を対応する必要があります。
1. ドメイン取得済み
2. DNSレコードの設定で対応するAレコードを登録済み


- certbotのyum installを実行

```
[root@nginx-redo ~]# yum -y install certbot
```

- 仮想webrootとなるディレクトリを作成（certbotが参照するディレクトリ）

```
mkdir -p /var/www/tnoce
```

- 証明書の発行
  -  Congratulations!となれば成功です。

```
[root@nginx-redo ~]# certbot certonly --webroot -w /var/www/tnoce -d [YOUR DOMAIN]
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for [YOUR DOMAIN]
Using the webroot path /var/www/tnoce for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/[YOUR DOMAIN]/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/[YOUR DOMAIN]/privkey.pem
   Your cert will expire on 2020-09-15. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```



- Nginxの再起動

```
[root@nginx-redo ~]# systemctl restart nginx
```

## SSL証明書の更新

以下コマンドで対応できます。
今回はやりませんがcronにコマンドをセットすれば、周期的に実行して勝手に更新してくれるようになります。

```
certbot renew --webroot-path /var/www/tnoce/ --post-hook "systemctl reload nginx"
```



## 実際の画面へのアクセス

- しっかりとhttps://をヘッダーにつけて取得した独自ドメインを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/6f6c25e7-6ff2-1c9c-8106-8e940e861b3c.png)

- 取得したドメインでqiitaのトップページが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/354dbcf1-3313-b4aa-559e-8e20aa73ff72.png)

- 証明書も有効化されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/6a810385-31da-b168-81e4-118fbfd641b4.png)

ページ遷移を試してみた所、リバースプロキシドメイン経由でアクセスができています。（ここもしっかりSSL化されている）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/136811d5-632f-c94c-35c1-3f762490c0cf.png)


## 最後に
自身の備忘録として書いたものですが、どなたかの役に立てれば幸いです。
サーバー側のFWで80,443は開けておいてくださいね。