Apache2.4でmod_nssを使用してHTTPS(TLS/SSL)の設定をする


# はじめに

ApacheでHTTPS(TLS/SSL)通信を実現するためには、mod_sslかmod_nssを組み込む必要があります。
この記事ではmod_nssを組み込んでTLS通信をする方法をまとめました。

# 実行環境

- OS：CentOS 7.3
- Apache : v2.4.23(Fedra Core25のRPMがベース)

　- 下記の手順でインストールしたものです。
　- 下記記事の説明にも書いてありますが、mod_nssを入れる予定があったため、mod_sslは未インストールです。
　　-  [CentOS7.3のApache 2.4をRPMでアップデートする方法(1)](https://qiita.com/tomluck/items/373d61125bb6b7be9562)
　　-   [CentOS7.3のApache 2.4をRPMでアップデートする方法(2)](https://qiita.com/tomluck/items/1cbe7a9d058730a66796)

- mod_nss：1.0.14


# mod_nssのインストール

yumのリポジトリからmod_nssをインストールします。

```
$ sudo yum install mod_nss
```

# 起動時のwarningの修正

```console
[root@localhost httpd]# httpd -k start
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message
```

修正しなくても起動はできますが、デフォルト設定で起動するごとにServerName関連のwarningが出るので修正します。

CentOS7.3の場合、httpd.confが/etc/httpd/conf/httpd.confにあるので、次のようにServerNameディレクティブを追記します。ここではlocalhostとしています。

```apache
ServerName localhost
```

# error_logのエラーを修正する

```console
[root@localhost httpd]# less logs/error_log 
[Thu Nov 16 18:56:10.018381 2017] [suexec:notice] [pid 16394] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Thu Nov 16 18:56:10.018495 2017] [:warn] [pid 16394] NSSSessionCacheTimeout is deprecated. Ignoring.
[Thu Nov 16 18:56:10.268668 2017] [:error] [pid 16394] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
[Thu Nov 16 18:56:10.371067 2017] [auth_digest:notice] [pid 16396] AH01757: generating secret for digest authentication ...
[Thu Nov 16 18:56:10.372220 2017] [lbmethod_heartbeat:notice] [pid 16396] AH02282: No slotmem from mod_heartmonitor
[Thu Nov 16 18:56:10.372901 2017] [:warn] [pid 16396] NSSSessionCacheTimeout is deprecated. Ignoring.
[Thu Nov 16 18:56:10.389073 2017] [mpm_prefork:notice] [pid 16396] AH00163: Apache/2.4.23 (centos) mod_nss/1.0.14 NSS/3.21 Basic ECC PHP/5.4.16 configured -- resuming normal operations
[Thu Nov 16 18:56:10.389114 2017] [core:notice] [pid 16396] AH00094: Command line: 'httpd'
[Thu Nov 16 18:56:10.818705 2017] [:error] [pid 16400] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
[Thu Nov 16 18:56:10.922623 2017] [:error] [pid 16404] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
[Thu Nov 16 18:56:10.996898 2017] [:error] [pid 16407] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
[Thu Nov 16 18:56:11.017573 2017] [:error] [pid 16405] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
[Thu Nov 16 18:56:11.029080 2017] [:error] [pid 16401] Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
```

errorレベルのログは次の1種類で、それが複数出ていることが分かります。

```console
Misconfiguration of certificate's CN and virtual name. The certificate CN has localhost4.localdomain4. We expected localhost.localdomain as virtual name.
```

## 仕様の確認

### nss.confの設定内容の確認

CentOS7.3の場合は、/etc/httpd/conf.d/nss.confにNSS関連の設定が記述されています。

その中で、NSSNicknameというディレクティブがTLS通信の際にサーバ証明書として使用される証明書名です。

私の環境下では次のように設定されていました。

```apache:nss.conf
NSSNickname Server-Cert
```

### 格納されている証明書の確認

Server-CertがNSS DBへ格納されているかをcertutilで確認します。
なお、certutilの使い方については、次の記事を参照してください。

[Qiita:certutilでNSS DBを操作する方法](https://qiita.com/tomluck/items/2f8e73ff9ea3d79a3e3d)

```console
[root@localhost httpd]# certutil -L -d /etc/httpd/alias

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

cacert                                                       CTu,Cu,Cu
beta                                                         u,pu,u
alpha                                                        u,pu,u
Server-Cert                                                  u,u,u
```

NSS DBへは格納されていることが分かりました。

次に、Server-Certの詳細を確認します。

```console
[root@localhost httpd]# certutil -L -n Server-Cert -d /etc/httpd/aliasCertificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4 (0x4)
        Signature Algorithm: PKCS #1 SHA-256 With RSA Encryption
        Issuer: "CN=Certificate Shack,O=example.com,C=US"
        Validity:
            Not Before: Tue Nov 14 06:25:06 2017
            Not After : Sun Nov 14 06:25:06 2021
        Subject: "CN=localhost4.localdomain4,O=example.com,C=US"
        Subject Public Key Info:
(以下略)
```

Subject欄には「CN=localhost4.localdomain4」となっており、httpd.confのServerNameと異なっています。エラー内容が「Misconfiguration of certificate's CN and virtual name.」となっているので、これがエラーの原因と考えられます。

## 修正内容

証明書のCNの内容がServerNameと一致したものをサーバ証明書として指定する必要があります。
既存の証明書のCNでServerNameと一致したものはないので証明書を新規作成します。ここではSelfSignedCertificateという名前にして、CNをServerNameと合わせます。

```console
[root@localhost httpd]# certutil -S -n SelfSignedCertificate -s "C=XX,CN=localhost" -v 12 -x -t "Pu,Pu,Pu" -d /etc/httpd/alias
 
A random seed must be generated that will be used in the
creation of your key.  One of the easiest ways to create a
random seed is to use the timing of keystrokes on a keyboard.

To begin, type keys on the keyboard until this progress meter
is full.  DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!


Continue typing until the progress meter is full:

|************************************************************|

Finished.  Press enter to continue: 


Generating key.  This may take a few moments...

Notice: Trust flag u is set automatically if the private key is present.

```

合わせてnss.confのNSSNickNameディレクティブを作成した証明書に変更します(上記の場合、SelfSignedCertificate)

```diff:nss.conf
- NSSNickname Server-Cert
+ NSSNickname SelfSignedCertificate
```


Apacheを再起動すると、error_logからerrorレベルのログがなくなりました。warnなどerror以外はとりあえずそのままです。

```console
[Mon Nov 20 16:12:01.112963 2017] [mpm_prefork:notice] [pid 14330] AH00169: caught SIGTERM, shutting down
[Mon Nov 20 16:12:11.289577 2017] [suexec:notice] [pid 15007] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Mon Nov 20 16:12:11.289742 2017] [:warn] [pid 15007] NSSSessionCacheTimeout is deprecated. Ignoring.
[Mon Nov 20 16:12:11.805896 2017] [auth_digest:notice] [pid 15009] AH01757: generating secret for digest authentication ...
[Mon Nov 20 16:12:11.807647 2017] [lbmethod_heartbeat:notice] [pid 15009] AH02282: No slotmem from mod_heartmonitor
[Mon Nov 20 16:12:11.808673 2017] [:warn] [pid 15009] NSSSessionCacheTimeout is deprecated. Ignoring.
[Mon Nov 20 16:12:11.832130 2017] [mpm_prefork:notice] [pid 15009] AH00163: Apache/2.4.23 (centos) mod_nss/1.0.14 NSS/3.21 Basic ECC PHP/5.4.16 configured -- resuming normal operations
[Mon Nov 20 16:12:11.832181 2017] [core:notice] [pid 15009] AH00094: Command line: 'httpd'
```

# 動作確認

下記のURLへアクセスするとテストページが表示されます。
私の環境ではnss.confのListenディレクティブが8443となっていたので、ポート番号は8443を指定してアクセスします。

```
https://(IPアドレス):8443
```

自己署名証明書のためブラウザでプライバシーエラーの警告画面が出ますが、詳細設定で「アクセスする」のリンクをクリックすると接続できるはずです。

# おわりに

ApacheでHTTPS(TLS/SSL)通信をする場合、mod_sslを使うことが多いと思いますが、mod_nssを使う必要がある時に、本記事が参考になれば幸いです。

一般的にApache標準でmod_sslがインストールされていることが多いです。そのため、mod_nssは後からインストールされ、mod_sslと2つ存在していることもあります。

その場合でもListenポートが異なればエラーにならないと思いますが、未確認です。(私の環境ではmod_sslがなくmod_nss単独の状態なので)