# SSL/TLS 接続の有効化

EMQX は、MQTT クライアントのアクセスを受け入れる際に、SSL/TLS を介して安全な接続を確立できます。SSL/TLS 暗号化機能はトランスポート層でネットワーク接続を暗号化し、通信データのセキュリティを強化するとともに、その完全性を保証します。

本ページでは、SSL/TLS 接続の機能と利点、およびクライアントと EMQX 間で SSL/TLS 接続を確立する方法について紹介します。

## セキュリティ上の利点

SSL/TLS 接続を有効にすることで、以下のセキュリティ上の利点が得られます。

1. **強力な認証**: 通信する双方が相手の X.509 デジタル証明書を検証し、相手の身元を確認します。これらの証明書は通常、信頼された認証局（CA）によって発行されており、偽造できません。
2. **機密性**: 各セッションは双方で交渉されたセッションキーで暗号化されます。第三者が通信内容を知ることはできず、仮にセッションキーが漏洩しても他のセッションの安全性には影響しません。
3. **完全性**: 暗号化通信においてデータが改ざんされる可能性は極めて低いです。

## 2つの利用モード

MQTT 接続を含むすべての接続に対して SSL/TLS 暗号化接続を有効にし、アクセスおよびメッセージ送信のセキュリティを確保できます。クライアントの SSL/TLS 接続については、利用シナリオに応じて以下の2つのモードから選択可能です。

| 利用モード                                                   | 利点                                                   | 欠点                                                |
| ------------------------------------------------------------ | ------------------------------------------------------ | --------------------------------------------------- |
| クライアントと EMQX 間で直接 SSL/TLS 接続を確立する。         | 利用が簡単で追加コンポーネントが不要。                   | EMQX のリソース消費が増加し、接続数が多い場合は CPU やメモリ消費が高くなる可能性がある。 |
| プロキシやロードバランサーを介して TLS 接続を終了させる。     | EMQX のパフォーマンスに影響がなく、ロードバランシング機能を提供できる。 | TCP SSL/TLS 終端をサポートするクラウドベンダーのロードバランサーは限られている。また、ユーザー自身で HAProxy などのソフトウェアをデプロイする必要がある。 |

プロキシやロードバランサーを介した TLS 接続終了の詳細は、[Cluster Load Balancing](../deploy/cluster/lb.md) を参照してください。

## 一方向認証／双方向認証

EMQX は包括的な SSL/TLS 機能をサポートし、X.509 証明書を用いたクライアント／サーバー間の一方向認証および双方向相互認証を実現できます。

| 認証方式               | 説明                                                      | 検証方法                                                  | 長所と短所                                               |
| ---------------------- | --------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------- |
| 一方向認証             | クライアントがサーバーの身元を検証するが、サーバーはクライアントの身元を検証しない。 | クライアントは通常証明書を提供する必要がなく、サーバー証明書が信頼された CA によって発行されていることのみを検証する。 | 通信データの機密性と完全性は保証できるが、通信相手の身元は保証できない。 |
| 双方向認証             | サーバーとクライアントが互いに身元を検証し合う。           | 各デバイスに証明書を発行し、サーバーがクライアント証明書の正当性を検証する。 | サーバーとクライアント間の相互信頼を保証し、中間者攻撃を防止できる。 |

## SSL/TLS 証明書

SSL/TLS 接続を確立する前に認証用の証明書を準備する必要があります。EMQX はテスト目的でのみ使用する証明書セット（インストールパッケージの `etc/certs` ディレクトリ内）を提供しています。実運用環境では、信頼された CA によって署名された信頼性のある証明書を使用してください。証明書の取得方法は [Obtain SSL/TLS Certificates](./tls-certificate.md) を参照してください。

## 一方向認証での SSL/TLS 有効化

EMQX はデフォルトでポート `8883` で SSL/TLS リスナーを有効にし、一方向認証を設定しています。ダッシュボードや設定ファイルで証明書の差し替えやその他の設定変更が可能です。

### ダッシュボードでの有効化

1. EMQX ダッシュボードにアクセスし、左側ナビゲーションメニューから **Management** -> **Listeners** をクリックします。

2. **Listeners** ページで、SSL リスナーの **Name** 列にある **default** をクリックします。

   - **TLS Verify**: 一方向認証のためデフォルトで無効。
   - **TLS Cert**、**TLS Key**、**CA Cert**: **Reset** ボタンをクリックして現在の証明書ファイルをプライベート証明書ファイルに差し替え可能。
   - **SSL Versions**: すべての TLS/DTLS バージョンをサポート。デフォルトは `tlsv1.3` と `tlsv1.2`。PSK 認証に PSK 暗号スイートを使う場合は `tlsv1.2`、`tlsv1.1`、`tlsv1` を設定してください。PSK 認証の詳細は [Enable PSK Authentication](./psk-authentication.md) を参照。
   - **Fail If No Peer Cert**: **TLS Verify** が有効な場合に使用。デフォルトは `false`。
     - `true` の場合、クライアントが空の証明書を送信すると検証失敗となり、SSL/TLS 接続は拒否される。
     - `false` の場合、無効な証明書を送信した場合のみ検証失敗となり、空の証明書は有効とみなされる（一方向認証）。
   - **Intermediate Certificate Depth**: 証明書パスの最大深度。デフォルトは `10`。
   - **Key Password**: プライベートキーがパスワード保護されている場合に入力。
   - **Enable OCSP Stapling**: デフォルトで無効。SSL/TLS 証明書の失効状態を取得する必要がある場合はトグルスイッチで有効化。詳細は [OCSP Stapling](./ocsp.md) を参照。
   - **Enable CRL Check**: デフォルトで無効。接続クライアント証明書の失効確認が必要な場合はトグルスイッチで有効化。詳細は [CRL Check](./crl.md) を参照。

3. 編集が完了したら、**Update** ボタンをクリックします。

   <img src="./assets/edit-listener.png" alt="リスナー編集" style="zoom:40%;" />

### 設定ファイルでの有効化

設定ファイルの `listeners.ssl.default` 設定グループを変更して SSL/TLS 接続を有効にすることも可能です。

1. プライベート SSL/TLS 証明書ファイルを EMQX の `etc/certs` ディレクトリに配置します。

2. インストール方法により `./etc` または `/etc/emqx/etc` ディレクトリにある設定ファイル `base.hocon` を開きます。

3. `listeners.ssl.default` 設定グループを編集し、証明書ファイルを自分の証明書ファイルに置き換えます。

   一方向認証を有効にする場合は `verify = verify_none` を追加します。

```bash
listeners.ssl.default {
  bind = "0.0.0.0:8883"
  ssl_options {
    # クライアント証明書の真正性を検証するためにリスナーが使用する信頼された CA（認証局）証明書を含む PEM ファイル。
    # 一方向認証の場合、ファイル内容は空でもよい。
    cacertfile = "etc/certs/rootCAs.pem"
    # リスナー用の SSL/TLS 証明書チェーンを含む PEM ファイル。
    # 証明書がルート CA から直接発行されていない場合、中間 CA 証明書をリスナー証明書の後に連結してチェーンを形成する必要がある。
    certfile = "etc/certs/server-cert.pem"
    # SSL/TLS 証明書に対応するプライベートキーを含む PEM ファイル。
    keyfile = "etc/certs/server-key.pem"
    # クライアント証明書の真正性を検証するために 'verify_peer' を設定。双方向認証（mTLS）では必須。
    # 任意のクライアント接続を許可する場合は 'verify_none' を設定。
    verify = verify_none
    # クライアントが証明書を送信しない場合にハンドシェイクを失敗させるかどうか。双方向認証（mTLS）では true に設定。
    # false の場合は無効な証明書を送信した場合のみ失敗（一方向認証）。
    fail_if_no_peer_cert = true
  }
}
```

### EMQX v4 の設定

**EMQX では、`mqtt:ssl` のデフォルトリスニングポートは 8883 です。**

OpenSSL ツールで生成した `emqx.pem`、`emqx.key`、`ca.pem` ファイルを EMQX の `etc/certs/` ディレクトリにコピーし、以下の設定を参考に `base.hocon` を修正します。

```shell
## listener.ssl.$name は MQTT/SSL の IP アドレスとポート
## 値: IP:Port | Port
listener.ssl.external = 8883

# SSL/TLS 証明書に対応するプライベートキーを含む PEM ファイル
listener.ssl.external.keyfile = etc/certs/emqx.key

# SSL/TLS 証明書チェーンを含む PEM ファイル
        fail_if_no_peer_cert = false
      }
    }
```

4. 設定を反映するために EMQX を再起動します。

## 一方向認証でのクライアント接続テスト

[MQTTX CLI](https://mqttx.app/cli) を使ってテストできます。一方向認証ではクライアントが CA 証明書を提供し、サーバーの身元を検証します。

```bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt
```

サーバー証明書の Common Name (CN) がクライアントが接続時に指定したサーバーアドレスと一致しない場合、以下のエラーが発生します。

```bash
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: localhost. is not cert's CN: Server
```

この場合、クライアント証明書の CN をサーバーアドレスに合わせるか、`--insecure` オプションで証明書 CN の検証を無視できます。

```bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --insecure
```

## 双方向認証での SSL/TLS 有効化

双方向認証は一方向認証の拡張で、EMQX がクライアント証明書を検証し、クライアントの正当性を保証します。

これに加えて、クライアント用の証明書を発行する必要があります。具体的な手順は [Issue Client Certificates](./tls-certificate.md#issue-client-certificates) を参照してください。

ダッシュボードでは、**TLS Verify** を **Enable** に設定し、**Fail if No Peer Cert** を `true` に設定することで双方向認証を強制できます。

設定ファイルの `listeners.ssl.default` 設定グループに以下を追加しても構いません。

```bash
listeners.ssl.default {
  ...
  ssl_options {
    ...
    # ピア検証を有効化
    verify = verify_peer
    # 双方向認証を強制。クライアントが証明書を提供できない場合、SSL/TLS 接続は拒否される。
    fail_if_no_peer_cert = true
  }
}
```

## 双方向認証でのクライアント接続テスト

[MQTTX CLI](https://mqttx.app/cli) を使ってテストできます。双方向認証では CA 証明書に加え、クライアント自身の証明書も提供する必要があります。

```bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --cert certs/client-0001.crt \
  --key certs/client-0001.key
```

サーバー証明書の CN がクライアントが接続時に指定したサーバーアドレスと一致しない場合、以下のエラーが発生します。

```bash
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: localhost. is not cert's CN: Server
```

この場合、クライアント証明書の CN をサーバーアドレスに合わせるか、`--insecure` オプションで証明書 CN の検証を無視できます。

```bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --cert certs/client-0001.crt \
  --key certs/client-0001.key \
  --insecure
```

## SSL/TLS 証明書の更新

プライベート SSL/TLS 証明書ファイルの有効期限が切れた場合は、`./etc` または `/etc/emqx/etc` ディレクトリ内の古い証明書を新しいものに手動で差し替えて更新してください。

EMQX は再起動なしで SSL/TLS 証明書のローテーションをサポートしています。デフォルトで EMQX は 120 秒ごとに SSL/TLS 証明書をリロードします。
