# クラスターセキュリティ

EMQXは、データの機密性、完全性、および可用性を確保するために、ノードレベルでの[認証](../access-control/authn/authn.md)および[認可](../access-control/authz/authz.md)機構、クラスター内のノード間通信を安全にするための[シークレットクッキー](#set-node-cookie)、およびノード間トラフィックのエンドツーエンド暗号化を提供する[TLS/SSL暗号化](#configure-tls-ssl-to-secure-cluster-connections)など、複数のセキュリティ機構を提供しています。

また、ファイアウォールルールのプロビジョニングを支援するために、EMQXのブローカー間[通信ポートマッピングルール](#port-mapping)についても説明します。

## ノードクッキーの設定

セキュリティ上の理由から、クラスターに参加するすべてのノードの`emqx.conf`でデフォルトのクッキー設定をシークレットクッキーに変更することを推奨します。

注意：クラスターに参加するすべてのノードは同じシークレットクッキーを使用する必要があります。使用されるマジッククッキーの詳細については、[Distributed Erlang - Security](https://www.erlang.org/doc/reference_manual/distributed.html#security)を参照してください。

```
node {
  cookie = "<シークレットクッキー>"
}
```

EMQX 6.3.0以降では、`node.cookie`に通常のファイルまたはFIFO（名前付きパイプ）を参照するファイルURLを設定することで、`emqx.conf`にクッキーを平文で保存することを回避できます。

```hocon
node.cookie = "file:///run/secrets/emqx-cookie"
```

`EMQX_NODE__COOKIE`環境変数も`file://` URLを受け入れます。すべてのノードでファイルまたはFIFOをプロビジョニングし、すべてのノードが同じクッキーを読み込むようにしてください。起動時の読み込みやFIFOの要件については、[Load the Node Cookie from a File](../configuration/secret-from-file.md#load-the-node-cookie-from-a-file)を参照してください。

:::tip ヒント

クラスターに参加するすべてのノードは同じセキュリティクッキーを使用する必要があります。使用されるマジッククッキーの詳細については、[Distributed Erlang - Security](https://www.erlang.org/doc/reference_manual/distributed.html#security)を参照してください。

:::

## クラスター接続を保護するためのTLS/SSLの設定

EMQXは、ノード間の通信チャネルをTLSで保護し、交換されるデータの機密性、完全性、および真正性を守ることもサポートしています。TLSの使用はCPU負荷およびメモリ使用量の増加を伴います。ビジネスニーズに応じて適切に設定してください。

このセクションでは、EMQXクラスターでTLSを設定する方法を紹介します。SSL/TLS証明書の取得方法については、[SSL/TLS Certificates](../network/tls-certificate.md)を参照してください。

## クラスターRPC接続にTLS/SSLを使用する

クラスターRPCにTLS/SSLを設定するには、以下の設定項目を`emqx.conf`に設定してください。

```
rpc {
  driver = ssl
  # リスナーがクラスターのピアの真正性を検証するために使用する信頼されたCA（認証局）証明書を含むPEM形式のファイル
  cacertfile = "/path/to/cert/ca.pem"
  # リスナーのSSL/TLS証明書チェーンを含むPEM形式のファイル。証明書がルートCAから直接発行されていない場合、中間CA証明書をリスナー証明書の後に連結してチェーンを形成する必要があります。
  certfile = "/path/to/cert/domain.pem"
  # SSL/TLS証明書に対応する秘密鍵を含むPEM形式のファイル
  keyfile = "/path/to/cert/domain.key"
  # クライアント証明書の真正性を検証する場合は'verify_peer'に設定し、それ以外は'verify_none'に設定
  verify = verify_peer
  # trueに設定すると、ピアが証明書を送信しない（空の証明書を送信）場合にハンドシェイクが失敗します。falseの場合は、無効な証明書を送信した場合のみ失敗します（空の証明書は有効とみなされます）。
  fail_if_no_peer_cert = true
}
```

### Erlang DistributionにTLS/SSLを使用する

EMQXコアノードは、データベースの更新同期やクラスター内ノードの管理（コンポーネントの起動/停止、ランタイムメトリクスの収集など）にErlang Distributionを使用しています。

* `etc/ssl_dist.conf`ファイルにキーと証明書への正しいパスが設定されていることを確認してください。
* 設定`cluster.proto_dist`が`inet_tls`に設定されていることを確認してください。

## ポートマッピング

クラスターのポートを内部に限定し、ファイアウォールルール（例： [AWSセキュリティグループ](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)や[iptables](https://en.wikipedia.org/wiki/Iptables)）で制御することは良いプラクティスです。クラスターノード間にファイアウォールがある場合、他のノードが到達できるように従来のリスニングポートを許可する必要があります。本セクションでは、ファイアウォールルールが正しく設定され、EMQXノード間の接続を許可しつつ外部からの不正アクセスを防ぐためのポートマッピングルールを紹介します。

EMQXは、ノード間通信の信頼性と効率を確保するためにクラスター用のポートマッピングルールを使用しています。EMQXノードは、Erlang DistributionポートとクラスターRPCポートという2つの異なるチャネルを通じて通信します。

| チャネル                      | 説明                                                        | デフォルトポート                                     |
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------- |
| **Erlang Distributionポート** | ノード間通信用                                              | `4370`                                             |
| **クラスターRPCポート**       | ノードの管理タスク（ノードの参加や離脱など）用              | `5370` または<br />Docker経由のEMQXの場合は`5369` |

EMQXはErlang DistributionポートとクラスターRPCポートに同じポートマッピングルールを適用します。

```
ListeningPort = BasePort + Offset
```

オフセットはノード名の数値サフィックスに基づいて計算されます。ノード名に数値サフィックスがない場合、オフセットは0に設定されます。例：

- ノード`emqx@192.168.0.12`は数値サフィックスがないため、Erlang Distributionポートは`4370`（クラスターRPCポートは`5370`）になります。
- ノード`emqx1@192.168.0.12`は数値サフィックスが1のため、ポートは`4371`（クラスターRPCポートは`5371`）になります。

## ルールエンジンポリシーとファイアウォールルールによるSSRFの緩和

EMQXのコネクター、ブリッジ、およびアクションは外部サービスへのアウトバウンドネットワーク接続を開きます。制御がなければ、誤設定や悪意のあるターゲットにより、EMQXが内部や機密性の高い宛先に意図しないリクエストを送信する可能性があり、これはServer-Side Request Forgery（SSRF）と呼ばれる脆弱性の一種です。EMQXは、限定的なコネクターカバレッジの組み込みルールエンジンSSRFポリシーと、ランタイムでコネクタータイプを横断してネットワーク境界を強制するホストレベルのイグレスフィルタリングという2つの補完的な防御策を提供します。

### HTTPおよびMQTTコネクターに対する`rule_engine.ssrf`の使用

EMQX `6.0.3`以降、アウトバウンドルールエンジンターゲットに対するクラスター単位のSSRFポリシーを提供しています。EMQX `6.0.4`以降、このポリシーはHTTPコネクターの`url`フィールドおよびMQTTコネクターの`server`フィールドにのみ適用されます。

```hocon
rule_engine {
  ssrf {
    enable = true
    allow_cidrs = []
    deny_cidrs = [
      "127.0.0.0/8",
      "::1/128",
      "169.254.0.0/16",
      "fe80::/10",
      "10.0.0.0/8",
      "172.16.0.0/12",
      "192.168.0.0/16",
      "fc00::/7",
      "0.0.0.0/32",
      "224.0.0.0/4",
      "ff00::/8",
      "100.100.100.200/32",
      "169.254.169.253/32"
    ]
    deny_hosts = [
      "metadata.tencentyun.com",
      "metadata.google.internal",
      "metadata.azure.internal"
    ]
  }
}
```

ダッシュボードでのポリシー設定については、[ルールエンジンセキュリティ](../dashboard/cluster_settings.md#rule-engine-security)を参照してください。

有効化すると、EMQXはコネクター設定のテスト、作成、更新時にこれらのHTTPおよびMQTTコネクターターゲットを検証します。`deny_hosts`の完全一致は即座に拒否されます。解決されたIPはまず`allow_cidrs`と照合され、許可リストに一致しなければ`deny_cidrs`と照合されます。

このポリシーは他のコネクタータイプ、コネクターの有効化/無効化操作、コネクター削除、またはランタイムのアウトバウンド接続は検証しません。作成後にブロック対象となるHTTPまたはMQTTコネクターターゲットがあっても、コネクターは有効化できます。コネクターの削除もポリシーによってブロックされません。

このポリシーは互換性のためデフォルトで無効です。ブロック対象のターゲットを持つHTTPおよびMQTTコネクター設定が接続テストを通過したり作成・更新されるのを防ぎたい場合に有効にしてください。これらのコネクターが内部サービスにアクセスする必要がある場合は、ポリシーを有効にする前に`allow_cidrs`および`deny_cidrs`を見直し調整してください。

### `rule_engine.ssrf`だけで十分な場合

以下の条件すべてを満たす場合、`rule_engine.ssrf`だけで通常は十分です。

- SSRF保護が必要なすべてのルールエンジンターゲットがHTTPまたはMQTTコネクターを使用している。
- ポリシーはコネクター作成前に有効化され、信頼できる管理者のみが設定を更新できる。
- アウトバウンドターゲットは固定されたSaaSエンドポイントや明示的に承認された公開サービスなど安定している。
- HTTPまたはMQTTコネクター設定のテスト、作成、更新時に誤設定や明らかなSSRFターゲットを防止したい。
- 後に異なるアドレスに再バインドされる可能性のあるDNS名を使用していない。

### ファイアウォールルールも追加すべき場合

以下のいずれかに該当する場合は、`iptables`、`nftables`、クラウドセキュリティグループ、Kubernetesネットワークポリシーなどによるホストレベルのイグレスフィルタリングを追加してください。

- HTTPまたはMQTT以外のコネクタータイプを使用している。
- ポリシー変更を保存済みコネクター設定、有効化操作、またはランタイム接続に適用する必要がある。
- 委任管理者がネームスペーススコープのリソースを設定できる。
- 設定時の検証を通過しても、EMQXが内部サービス、メタデータエンドポイント、管理ネットワークに到達できてはならない。
- DNS再バインディングや検証後のアドレス変更が脅威モデルに含まれる。
- マルチテナント、高リスク、またはランタイムで厳格なアウトバウンドネットワーク境界を強制する必要がある。

イグレス制限を計画する際は以下を考慮してください。

- IDプロバイダー、Webhook、コネクターバックエンドなど、デプロイメントで必要な宛先のみを許可する。
- ループバック、リンクローカル、インスタンスメタデータエンドポイントなど、SSRF攻撃で悪用されやすい機密アドレスへのアクセスは、デプロイメントで明示的に必要でない限り拒否する。特に以下のメタデータエンドポイントはブロックを検討してください：
  - Alibaba Cloudメタデータサービス用の`100.100.100.200`
  - AWS外部メタデータサービス用の`169.254.169.253`
  - AWSおよびAzureメタデータサービス用の`169.254.169.254`
  - AWS IPv6メタデータサービス用の`fd00:ec2::254`
- EC2上のAWSベースのコネクターやアクションでアクセスキーIDおよびシークレットアクセスキーを省略し、EMQXがインスタンスメタデータサービスから認証情報を取得する場合は、`169.254.169.254`をブロックしないでください。これはAmazon MSK IAMだけでなく、S3、S3 Tables、DynamoDB、Kinesisなどの統合にも該当します。同様の例外を`iptables`や`nftables`ルールにも反映してください。
- 本番環境に適用する前にステージング環境でルールを慎重に検証してください。
- EMQXがコンテナやKubernetes上で動作する場合は、コンテナホストのファイアウォール、クラウドセキュリティグループ、Kubernetesネットワークポリシーで同等のイグレス制御を適用してください。

`rule_engine.ssrf`はこれらのネットワーク層制御の代替ではありません。SSRFポリシーはコネクター設定のテスト、作成、更新時にHTTPおよびMQTTコネクターターゲットのみを検証します。その他のコネクタータイプ、ポリシー変更後に有効化された保存済み設定、DNS再バインディング、検証後に解決アドレスが変わる可能性があるケースではランタイムのネットワーク制御が必要です。

以下の`iptables`例は一般的なアプローチを示しています。環境に合わせてインターフェース名、ポート、宛先アドレスを調整してください。ホストに`iptables`がない場合は、同等のルールを`nftables`で適用してください。

```bash
# 確立済みのアウトバウンド接続を許可
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# ホストで必要な場合はDNSおよびNTPを許可
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

# 承認された外部サービスへのアクセスのみ許可
iptables -A OUTPUT -p tcp -d 198.51.100.10 --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d 203.0.113.20 --dport 443 -j ACCEPT

# 一般的なメタデータおよびローカル限定宛先をブロック
iptables -A OUTPUT -d 127.0.0.0/8 -j REJECT
# EC2上のAWSベースのコネクターやアクションがインスタンスメタデータサービスから認証情報を取得する場合は、
# 169.254.169.254への一括拒否を適用しないでください。代わりにより具体的な許可ルールを追加してください。
iptables -A OUTPUT -d 169.254.0.0/16 -j REJECT
iptables -A OUTPUT -d 100.100.100.200 -j REJECT
ip6tables -A OUTPUT -d fd00:ec2::254 -j REJECT

# その他の新規アウトバウンド接続はデフォルトで拒否
iptables -A OUTPUT -m conntrack --ctstate NEW -j REJECT
```

ホストが`iptables`ではなく`nftables`を使用している場合も、`100.100.100.200`、`169.254.169.253`、`169.254.169.254`、`fd00:ec2::254`などの既知のメタデータエンドポイントに対する明示的な拒否を含め、同じポリシーを実装してください。EC2上のAWSベースのコネクターやアクションがインスタンスメタデータサービスから認証情報を取得する場合は、`169.254.169.254`へのアクセスが可能な状態を維持してください。
