Corda Firewallの概要・メリット・実装方法が理解できる。
はじめに
本稿について
本稿は、Corda Enterpriseの機能である「Corda Firewall」の概要及び設定について説明したものです。英語のドキュメントはこちらをご覧ください。
※Corda FirewallはCorda Enterpriseのみに含まれるコンポーネントです。
Corda Firewallの概要
Corda Firewallとは
Cordaは参加許可型のネットワークであるため、ある程度は信頼のおける主体がネットワークに参加している前提です。しかし、デフォルトではNodeが他Nodeと直接通信する形になっていて、セキュリティや冗長性に関して少し心配になるかもしれません。
そこでCorda Firewallを採用することで、Nodeをセキュアな環境に強化することができます。
基本用語
- bridge Corda Firewall のbridgeコンポーネントは、アウトバウンドメッセージを処理します。Node内でもNode外でも自由に設置することができます。自Nodeが相手Nodeにメッセージを送信したい場合、Nodeはまずbridgeに対して送信します。bridgeは、相手Nodeとの間で、安全なTLS暗号化された接続を確立しアウトバウンドキューからメッセージを消費し、Nodeのネットワーク外にいるリモートピアにメッセージを送信します。bridgeから外部への接続は AMQP 1.0/TLS 1.2 です。
- float float は、相手Nodeからの受信パケットのリスナーとして動作します。これらはTLS暗号化されAMQPを通じてbridgeに転送されます。また、相手Nodeへ確認応答を送信する責任があります。floatは、Nodeのシールドとして機能します。すなわち、Nodeにパケットを送る前にデータを検証し正しいメッセージのみを転送し、それ以外をドロップします。パケットのフィルタリングは、設定でよりセキュアなものにすることができます。なお、floatは内部ネットワークではなく、DMZに配置する必要があります。
- SOCKSプロキシSOCKSプロキシに対応しています。SOCKSプロキシを構築する場合は、上記のbridgeはSOCKSプロキシと接続して、SOCKSプロキシが相手NodeとP2P接続を確立します。
- HTTPプロキシHTTPプロキシにも対応しています。HTTPS取得要求を介してDoormanとネットワークマップに接続します。
- Artemis BrokerArtemis ブローカーは、インバウンドキューと相手Node固有の複数のアウトバウンドキューを作成するために使用されます。ブリッジは、相手Nodeとの間でTLSリンクを確立し、このアウトバウンドキューからメッセージを消費し、相手Nodeに送信し、相手Nodeからの確認応答を得たときにキューから削除します。インバウンドキューは、相手Nodeからのインバウンドメッセージを格納するために使用されます。Artemis ブローカーは、デフォルトではNode内に埋め込まれていますが、プロセスの外にArtemisを設定するように設定することもできます。
Corda Firewallを導入するメリット
- Corda Firewallは、Nodeのシールド/プロキシとして機能し、プロトコルブレークを提供し、DMZに配置することができます。floatは、NodeとArtemisサーバが他Nodeにさらされるのを防ぎます。
- 「他Node - float間」、「float - bridge間」、「自Node- bridge間」はTLS暗号化されています。float - bridge間のトンネルは、異なるセットのTLS証明書を使用し、Nodeの証明書を使用しません。DMZ デバイスを通過するデータは暗号化された TLSチャネルを介して送信されるため、floatが漏洩してもこのデータは漏洩しません。
- Corda Firewall は CRL をサポートしており、設定されている場合は、証明書パス内の各証明書が CRL と照合されます。
- 監査の観点からは、bridgeとfloatのビジネスクリティカルなイベントはファイルに記録されます。将来の実装では、エンタープライズサービスにデータをポストするように強化される予定です。
- メッセージはfloatで削除され、検証を満たさない場合はログに記録されます。
- Corda Firewallのbridgeは、SOCKS 4/5プロキシサーバーを介して外の世界に接続することができます。SOCKS 5は追加のセキュリティをサポートしています。また、bridgeを持つことで、NodeがパブリックIPアドレスを持たないようになります。
- 接続はbridge制御によって外部floatへの接続が開始され、双方向の接続が確立されます。接続はDMZデバイスから内部ネットワークへの接続は決して開始されず、bridgeによって開始されます。
- floatとbridgeはステートレスであり、いかなる情報も保存しません。
- Artemis BrokerはNodeから取り出すことができます。したがって、1つのArtemisを複数のNodeで使用することができます。
- Corda Firewallは、HSMを使用してTLS署名を有効にする機能を持っています。
Node間通信の仕組み
Corda NodeはFirewallを使用しない場合でもTLSを用いた安全なNode間接続を実現していますが、
Corda Firewallを使う事でよりセキュアな通信を実現できます。ここでは、一番シンプルなピアツーピアの通信をシナリオにどのような処理が内部で行われているか説明します。
※このシナリオは送信Node/受信Node両方でCorda Firewallを構築している前提です。
【送信Node】
- Flowは sendまたは sendAndReceiveを呼び出して、メッセージを相手に送信します。これにより、StateMachine 内のフロー・ファイバーのチェックポイントが記録された後、Node内部の MessagingService にメッセージがポストされます。これにより、エラーが発生した場合でも、メッセージをさらに永続的に送信する前に、送信アクティビティが再試行されることを保証します。
- MessagingService は、新しい宛先Nodeであるかどうか、また、既存のアウトバウンドキューとbridgeがArtemisに存在するかどうかをチェックします。もし既存のアウトバウンドキューが存在しない場合、Artemisでの作成が行われます。アウトバウンドキューは、相手NodeのLegal Identityの公開鍵のハッシュを元に一意的な名前が付与されます。
- キューの作成が完了すると、併せてbridge作成要求もbridge制御プロトコルを介してArtemisバスに発行されます。この作成要求は、ネットワークマップからの情報を使用して、アウトバウンドキューをターゲットホストとポート、TLS資格情報にリンクします。Flowは、この時点で応答を待つ必要はなく、Artemis アウトバウンドキューにメッセージを送信し続けることができます。
- bridgeプロセスはすべてのキューを監視し、メッセージがキューの1つに格納されるとすぐに、bridgeは相手NodeへのTLS接続を開始します(任意に、この接続はSOCKS4/5プロキシを介することもできます)。接続時に、TLS リンクの両者は証明書を交換し、証明書パスがネットワーク・ルート証明書に固定されていること、および X500 のサブジェクトが、ネットワークマップに含まれる詳細情報を使用して bridge作成要求で指定された期待されるターゲットに一致していることを確認します。P2Pメッセージングのセットアップコストを削減するために、リンクはある程度存在し続けます。
- 発信TLS 1.2リンクが正常に作成された場合、bridgeはArtemisのアウトバウンドキュー上にコンシューマをオープンします。保留中のメッセージはその後、AMQP 1.0 を使用して相手Nodeに送信されますが、アウトバウンドキューからの最終的な削除は、相手Node側がメッセージの受信を完全に確認できた後に行われます。これは、少なくとも一度の配信セマンティクスを保証します。(※Nodeまたはbridgeのいずれかの起動時に、bridge制御プロトコルは、すべてのアウトバウンドキューがアクティブなbridgeを持つように、bridge状態を再同期化されます)
- NodeはArtemisからのack応答を受け取ると、StateMachineは、レスポンスを待っていなければ、Flowを続けることができます。そうでない場合は、応答を待つために中断状態になります。
【受信Node】
- 受信側は、直前のTLSハンドシェイクを受け入れた時点で、TLSオリジネーターの正当性を確認しています。しかし、floatは受信したメッセージとその関連するヘッダについて、さらに基本的なチェックを行います。例えば、メッセージは受信トレイのアドレスと等しいことや、ネットワークパラメータで定義されたmaxMessageSize以下であるかということをチェックします。
- メッセージの初期チェックに成功したfloatは、メッセージと送信者をペイロードとしてバンドルし、DMZ内部ファイアウォールを越えてbridgeに送信します。このインバウンドメッセージパスは、別のAMQP 1.0/TLS 1.2制御トンネルを使用します。このリンクは、トラストゾーンのbridgeからDMZのfloatに向けて開始されます。簡単なファイアウォールルールを設定して、DMZから内部ネットワークを調査しようとする試みをブロックすることもできます)。メッセージが転送されるとfloatは配信確認を追跡するため、送信者がソースキュー内のメッセージを消費扱いとするのは、相手の受信トレイに最終的に配信されてからになります。切断や問題が発生した場合は、拒否ステータスが送信され送信元からの再送信が行われます。
- メッセージを受け取ったbridgeは、そのメッセージが正常であることをさらに確認します。このチェックでは、メッセージの構造と、送信元と送信先が有効であることを確認します。メッセージの検証に失敗した場合は、再配信を防ぐために確認を行い、監査のために検証エラーを記録し、メッセージを破棄します。
- これが普通のメッセージであると仮定した場合、Artemisの受信トレイに渡され、配送の確認が行われると、数珠つなぎに送信元に情報が返されます。つまりArtemisのack応答が、トンネルAMQPパケットのack応答につながり、AMQPは送信ブリッジに認知され、最終的にはArtemisのアウトキューアイテムが消費されたことを示すことになります。このように、次々とメッセージが渡されることが、遅延の原因になることを防ぐために、AMQPチャンネルはスライディングウィンドウを使用しています。(現在のところ、実用的なデフォルトが内部で設定されており、ウィンドウサイズをユーザーが設定することはできません)。
- 受信Nodeの MessagingServiceは、Artemis の 受信トレイからメッセージを受け取り、必要な重複排除を行います。重複排除が必要な理由は、Corda Wireプロトコルの分散中断可能なロジックでは、「少なくとも1回」の配信しか保証されないからです。このようにして得られた一意のメッセージは、StateMachineに渡され、Responder Flow実行のトリガーになります。
- 応答メッセージは、floatによって付けられた認証済みオリジネーターフラグを使用して、応答を正しいオリジネーターに戻します。
Corda Firewallの設定
※Firewallを設定するためには、Nodeが事前に任意のネットワークに登録済であることが前提です。
Corda Firewallの設定方法には様々な種類があります。
今回紹介するのは、Corda doc上「DMZ ready (node + bridge + float)」に分類されているものです。
具体的には、以下の様な特徴を持ちます。
・bridgeとfloatを分離する。
・floatをDMZに配置する。
・bridgeは相手Nodeに送信するときに、floatを経由する。
Corda Firewallの設定手順
Nodeディレクトリ
- Nodeを停止します。
- corda-tools-ha-utilitiesを用いて、bridge - Node(artemis)間のトンネリング用キーペアを生成します。
- Nodeのベースディレクトリにartemisディレクトリを作成し「2」で生成したキーストアを配置します。
- node.confを修正します。(node.confの修正例を参照ください)
floatディレクトリ
- floatのベースディレクトリ配下にcertificatesディレクトリを作成し、Nodeが保有する以下のキーストアを配置します。
- nodekeystore.jks
- sslkeystore.jks
- truststore.jks
- float のベースディレクトリにNodeの network-parameters をコピーします。
- bridge - float 間のトンネリング用キーペアを生成します。成功した場合、ベースディレクトリ配下に、tunnel ディレクトリが生成&配下にキーペアが生成されます。
bridgeディレクトリ
- bridgeのベースディレクトリ配下にcertificatesディレクトリを作成し、Nodeが保有する以下のキーストアを配置します。
- nodekeystore.jks
- sslkeystore.jks
- truststore.jks
- bridgeのベースディレクトリにNodeの network-parameters をコピーします。
- bridge- float 間のトンネリング用キーペアを bridgeにコピーします。(ベースディレクトリにtunnelディレクトリを作成し、配置します。
- Nodeディレクトリで生成した以下のキーストアをベースディレクトリのartemis ディレクトリ配下に配置します。
- artemis-truststore.jks
- artemis.jks
コンポーネントの起動
bridgeおよびfloatは、corda-firewall.jarをベースディレクトリに配置して以下のコマンドで実行します。
推奨する起動順序は「float」→「Node」→「bridge」です。これはbridgeがNodeやFloatが起動していない場合、接続先なしと検知してエラーを出力してしまうためです。
node.confの設定例
node.confは通常と同様Nodeディレクトリに配置します。
項目 | 説明 | 設定例 |
p2pAddress | 一般的には、外部からアクセスされるアドレスを設定します。float.confのlisteningAddressはこの値と等しくなります。 | p2pAddress = "banka.com:10005" |
messagingServerAddress | bridgeと対話するArtemisのアドレスとポートを設定します。
bridgeのnode.confの「artemisBrokerAddress」と同じ値になります。 | messagingServerAddress = "nodeserver:11005" |
messagingServerExternal | bridgeと対話するartemisブローカーが外部ホストに設定するか否かをtrue/falseで設定します。 | messagingServerExternal = false |
externalBridge
※enterpriseConfiguration内に設定 | Corda Firewallの使用有無をtrue/falseで設定します。 | externalBridge = true |
messagingServerConnectionConfiguration
※enterpriseConfiguration内に設定 |
外部Artemisと通信をするときのリトライ回数やリトライ間隔を設定するモードです。現状は、「DEFAULT」、「FAIL_FAST」、「CONTINUOUS_RETRY」があります。 | messagingServerConnectionConfiguration = "CONTINUOUS_RETRY" |
messagingServerSslConfiguration
※enterpriseConfiguration内に設定 | bridgeとのトンネリング用キーペア情報。キー生成時の情報を設定します。 | messagingServerSslConfiguration = {sslKeystore = artemis/artemis.jkskeyStorePassword = artemisStorePasstrustStoreFile = artemis/artemis-truststore.jkstrustStorePassword = artemisTrustpass} |
bridge.confの設定
bridge.confはbridgeディレクトリに配置します。
項目 | 説明 | 設定例 |
firewallMode | Firewallのモードを設定します。
BridgeInner:bridge機能のみ有効
SenderReceiver:bridge機能とfloat機能を備えたModeです。 | firewallMode = BridgeInner |
artemisBrokerAddress
※outboundConfig内に設定 | bridgeと対話するArtemisのアドレスとポートを設定します。node.confの「messagingServerAddress」と同じ値になります。 | artemisBrokerAddress = "nodeserver:11005" |
artemisSSLConfiguration
※outboundConfig内に設定 | Artemisとのトンネリング用キーペア情報。キーペア生成時の情報を提供します。 | artemisSSLConfiguration {keyStorePassword = "artemisStorePass"trustStorePassword = "artemisTrustpass"sslKeystore = "artemis/artemis.jks"trustStoreFile = "artemis/artemis-truststore.jks"} |
floatAddresses
※bridgeInnerConfig内に設定 | floatにFlowを取りに行く際のアドレス。floatのnode.confの同プロパティと同じ値にします。 | floatAddresses = ["172.18.1.112:62201"] |
expectedCertificateSubject
※bridgeInnerConfig内に設定 | floatから提示されるクライアント証明書内のX500に含まれるべき文字列が入っています。 | expectedCertificateSubject = "CN=float,O=Node,L=Tokyo,C=JP" |
tunnelSSLConfiguration
※bridgeInnerConfig内に設定 | floatとのトンネリング用キーペア情報。キーペア生成時の情報を設定します。 | tunnelSSLConfiguration {keyStorePassword = "tunnelStorePass"keyStorePrivateKeyPassword = "tunnelPrivateKeyPassword"trustStorePassword = "tunnelTrustpass"sslKeystore = "tunnel/bridge.jks"trustStoreFile = "tunnel/tunnel-truststore.jks"} |
networkParametersPath | Nodeからコピーしたnetworkparameterを配置したパスを設定します。 | networkParametersPath = ./network-parameters |
float.confの設定
float.confはfloatディレクトリに配置します。
項目 | 説明 | 設定例 |
firewallMode | Firewallのモードを設定します。
FloatOuter:float機能を有効化します。これが定義されたInstanceは、bridgeからの接続を待つ状態になります。 | firewallMode = FloatOuter |
listeningAddress
※inboundConfig内に設定 | 外部からのメッセージのリスナーになるアドレスを設定します。一般的には、node.confのp2pAddressと同じ値になります。 | listeningAddress = "0.0.0.0:63201" |
floatAddress
※floatOuterConfig内に設定 | bridgeとの通信用のアドレスを設定します。
bridgeのnode.confの同プロパティと同じ値にします。 | floatAddress = "0.0.0.0:62201" |
expectedCertificateSubject
※floatOuterConfig内に設定 | bridgeから提示されるクライアント証明書内のX500に含まれるべき文字列が入っています。 | expectedCertificateSubject = "CN=bridge,O=Node,L=Tokyo,C=JP" |
tunnelSSLConfiguration
※floatOuterConfig内に設定 | bridgeとのトンネリング用キーペア情報。キーペア生成時の情報を設定します。 | tunnelSSLConfiguration {keyStorePassword = "tunnelStorePass"keyStorePrivateKeyPassword = "tunnelPrivateKeyPassword"trustStorePassword = "tunnelTrustpass"sslKeystore = "tunnel/float.jks"trustStoreFile = "tunnel/tunnel-truststore.jks"} |
おわりに
Corda Firewallは商用環境では必須と言える機能ですが、構築が複雑なため最初は混乱するかもしれません。この記事がご参考になればと思います。また構築や運用に関することでご不明点等ありましたら、弊社のプロフェショナルサービスのご利用もご検討くださいませ。
<ご質問・ご要望の例>
- Corda Portalの記事について質問したい
- ブロックチェーンを活用した新規事業を相談したい
- 企業でのブロックチェーン活用方法を教えて欲しい 等々
SBI R3 Japan エンジニアリング部所属
ソリューションアーキテクト/PoC支援
This is the way. みんなでキャズムを超えていきましょう!