Skip to content

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

EMQXは、データの機密性、完全性、および可用性を確保するために、ノードレベルでの認証および認可機構、クラスター内ノード間の安全な通信を保証するためのシークレットクッキー、およびノード間トラフィックのエンドツーエンド暗号化を提供するTLS/SSL暗号化など、複数のセキュリティ機構を備えています。

また、ファイアウォールルールのプロビジョニングを支援するために、EMQXのブローカー間通信ポートマッピングルールについても触れます。

ノードクッキーの設定 ​

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

注意:クラスターに参加するすべてのノードは同じシークレットクッキーを使用する必要があります。使用されるマジッククッキーの詳細については、Distributed Erlang - 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をご覧ください。

ヒント

クラスターに参加するすべてのノードは同じセキュリティクッキーを使用する必要があります。使用されるマジッククッキーの詳細については、Distributed Erlang - Securityをご参照ください。

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

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

本節では、EMQXクラスターにおけるTLSの設定方法を紹介します。SSL/TLS証明書の取得方法については、SSL/TLS Certificatesをご参照ください。

クラスター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セキュリティグループやiptables)で内部に保つことが推奨されます。クラスターノード間にファイアウォールが存在する場合、他のノードが到達できるように従来のリスニングポートを許可する必要があります。本節では、ファイアウォールルールが正しく設定され、EMQXノードが相互に接続できるようにしつつ、外部からの不正アクセスを防止するためのポートマッピングルールを紹介します。

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

チャネル説明デフォルトポート
Erlang Distributionポートノード間通信に使用4370
クラスターRPCポートノードの管理タスク(ノードの参加や離脱など)に使用5370 または
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"
    ]
  }
}

ダッシュボードでのポリシー設定方法はルールエンジンセキュリティをご覧ください。

有効化すると、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やシークレットアクセスキーを省略してインスタンスメタデータサービスから認証情報を取得する場合、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への到達性を確保してください。