はじめに

こんにちは。ブロックチェーン推進室の鈴木です。

私の所属するブロックチェーン推進室では、企業間取引に特化したエンタープライズブロックチェーンプラットフォーム:Cordaに関して機能調査を行っております。
Cordaは世界で350社を超える金融機関、規制当局、中央銀行、業界団体、システム・インテグレーターやソフトウェアベンダーにより構成されるR3エコシステムから、エンドユーザー目線で設計・開発されています。
また、4半期に1度のバージョンアップにより機能追加がされていますが、その機能がお客様に活用できるものなのか、ドキュメントだけではわからないことも多く、ブロックチェーン推進室独自で調査を進めています。

このブログでは、そういったCordaの機能調査をした結果を機能の使い方含めて紹介していきます。

Cordaの導入方法についてはこちらのドキュメントをご参照ください。

今後以下の内容で紹介しようと思います。

    1. Corda JMeterの使い方

    2. Corda Enterprise Performance検証 ノードスペックを変化することによる性能変化

    3. Corda Tokens SDK and Accounts

    4. Corda Enterprise Collaborative Recovery

    5. Corda Enterprise Archive Service

    6. Corda Firewallの設定方法(←今回はこちらの記事)

    7. Corda re-issuance Tokens SDK and Accountsを利用した一括「re-issuance」

    8. Corda Time-windows

    9. Corda Oracle

    10. Corda attachment

    11. Corda Webアプリケーション開発について

    12. Cordaを用いたNonFungibleTokenの実装

    13. CordaのTokens SDKでNFTマーケットプレイスを作ってみた

    (以降、バージョンアップの都度、新機能を紹介予定)

    第6回目は「Corda Firewallの設定方法」について紹介します。

    概要

    Corda Firewallは「Corda Enterprise 3.1」で導入されました。以降、Cordaのバージョンアップ毎に、Corda Firewallも機能追加・改善が行われてきました。 Corda Firewallの概要を「Corda Enterprise 4.7」のドキュメントより以下、引用します。

    Corda Firewall (bridge/float) コンポーネントは、エンタープライズ環境向けに設計されており、インターネットに接続するすべてのエンドポイントにおいて、アプリケーションレベルのファイアウォールおよびプロトコルブレークとして機能します。
    corda-firewall.jar は、基本的な Corda Enterprise ノードのピアネットワーク機能をカプセル化し、セキュリティに敏感なノードの JVM ランタイムとは別に運用できるようにしています。
    これにより、機能が分離され、法的なアイデンティティキーがインターネットのTLS接続と同じプロセスで使用されないことが保証されます。
    また、ブリッジコンポーネントのみがフロートへの接続を開始することで、ノードのインターネットアクセスポイントの分離性を高めています。
    高可用性(HA)やSOCKSプロキシのサポートなど、企業の導入要件に対応した機能も追加されています。
    ファイアウォールは2つ以上のノードに対応しているため、同一ネットワーク内に複数のノードを設置する際の複雑さを軽減することができます。

    ※「https://docs.corda.net/docs/corda-enterprise/4.7/node/corda-firewall-component.html」よりDeepL翻訳を通じて引用。

    今回は、簡単ながらCorda Firewall の設定方法と、設定時のポイントや注意点、TPSの変化の有無を紹介いたします。
    本記事では「Full production HA DMZ ready mode (hot/cold node, hot/warm bridge)」を参考に、Bridge/FloatのみHA構成で構築します。
    https://docs.corda.net/docs/corda-enterprise/4.8/node/corda-firewall-component.html#full-production-ha-dmz-ready-mode-hotcold-node-hotwarm-bridge

    今回こちらの環境で設定した最終的な構成イメージ図は下記の通りです。 なお、今回は一般的に言われるFirewallやLoad Balancerは配置していないため、Cordaのドキュメントに記載されているイメージ図とは若干差異があること、ご了承ください。

    図1:Corda Firewall構成イメージ図

    実行環境

    AWS EC2(t3a.medium)を5台用意し、各種Node等の配置は下表・図の通りです。
    Server1には、NodeA、Corda Firewallを設定し、ZooKeeperも併せて設定します。DBも、同一サーバ内に建ててあります。
    Server2はNodeBを設定し、Corda Firewallは設定していません。Server3にはNodeB用のDBを構築しています。
    Server4にはNotaryとCENMを設定し、Server5にNotary用のDBが構築してあります。なお、CENM(IdentityManager)用のDBは、Server4に構築してあります。

    また、全Nodeは、プライベートなCorda Networkに参加しているものとします。

    表1:実行環境

    図2:実行環境イメージ図

    必要ツール

    Corda関連のパッケージはCorda Enterpriseのパッケージから、ZooKeeperは公式サイトより入手してください。
    各種、検証時点での最新バージョンを使用しています(2021年11月現在ではCorda4.8、zookeeper3.6.3が最新)。

    ZooKeeper:https://zookeeper.apache.org/releases.html#download

    表2:必要ツール群

    フォルダ構成

    今回は下記のようなフォルダ構成で実施します。フォルダ名等は適宜変更してください。
    ZooKeeperはダウンロード後、解凍したフォルダをfirewall直下に配置してください。

    図3:フォルダ構成1

    設定手順

    1.Firewallの鍵(Bridge―Float間のトンネリング用キーペア)生成

    cd /firewall
    java -jar corda-tools-ha-utilities-4.7.jar generate-internal-tunnel-ssl-keystores -p tunnelStorePass -e tunnelPrivateKeyPassword -t tunnelTrustPass -o Node -l Tokyo -c JP

    ▼オプション

    表3:generate-internal-tunnel-ssl-keystoresコマンドのオプション

    https://docs.corda.net/docs/corda-enterprise/4.8/ha-utilities.html#self-signed-internal-tunnel-ssl-keystore

    ▼実行結果

    実行したディレクトリに「tunnel」フォルダが作成され、その配下にキーペアが生成されます。 ※nodeディレクトリは省略。

    図4:フォルダ構成2

    2.Artemisの鍵(Bridge―Artemis間のトンネリング用キーペア)生成

    cd /firewall
    java -jar corda-tools-ha-utilities-4.7.jar generate-internal-artemis-ssl-keystores -p artemisStorePass -t artemisTrustPass

    ▼オプション

    表4:generate-internal-artemis-ssl-keystoresコマンドのオプション

    https://docs.corda.net/docs/corda-enterprise/4.8/ha-utilities.html#self-signed-internal-artemis-ssl-keystore

    ▼実行結果

    実行したディレクトリに「artemis」フォルダが作成され、その配下にキーペアが生成されます。 ※nodeディレクトリは省略

    図5:フォルダ構成4

    3.node.confの修正

    ※Corda Firewallに関係する部分のみ抜粋

    表5:node.confのCorda Firewallに関する設定の説明

    図6:node.conf

    4.Firewall.confの作成

    今回は、Bridge、FloatともにHA(2台)構成とするため、それぞれディレクトリを作成し、設定ファイルを作成します。
    また、Nodeのcertificatesディレクトリとnetwork-parametersをコピーし、BridgeとFloatの各ディレクトリに配置します。
    設定ファイルの詳細については、公式ドキュメントを参照ください。
    https://docs.corda.net/docs/corda-enterprise/4.8/node/corda-firewall-configuration-fields.html

    ▼フォルダ構成

    ※nodeディレクトリは省略

    図7:フォルダ構成5

    4-1.bridge.confの作成

    当該ディレクトリにcertificatesディレクトリを作成している場合は、3~6行目のsslKeystore~trustStorePasswordは不要ですが、今回は例として記述してあります。

    表6:bridge用設定ファイルの説明

    図8:bridge.conf

    4-2.bridge2用bridge.confの作成

    bridgeをHA構成にする為、 bridgeのフォルダをコピーします。

    4-3.float.confの作成

    表7:float用設定ファイルの説明

    図9:float.conf

    4-4.float2用float.confの作成

    FloatをHA構成にする為、 floatフォルダをコピーし、float2/float.confのfloatAddressを変更します。変更箇所を赤字で表示しています。

    図10:float2.conf

    5.ZooKeeperの設定

    複製モードで実行する場合の設定方法です。
    ZooKeeperを複製モードで設定するには、クラスタノード毎に設定が必要になります。
    今回は「u1」「u2」「u3」というディレクトリを作成し、配下に設定ファイルなどを作成します。
    設定方法や設定ファイルについての詳細は公式ドキュメントを参照ください。
    https://zookeeper.apache.org/doc/r3.6.2/zookeeperStarted.html

    5-1.設定ファイル(zoo.cfg)作成

    クラスタノード毎に作成します。

    表8:ZooKeeper設定ファイルの説明

    図11:u1,u2,u3のzoo.cfg

    5-2.スナップショット格納用ディレクトリ作成

    ZooKeeperがインメモリDBのスナップショットを格納するためのディレクトリを作成します。
    ディレクトリ名は、上記cfgのdataDirと同じです。

    5-3.myidファイル作成

    先の項番で作成したディレクトリに、myidファイルを作成します。この整数値は、メンバを識別する値です。

    図12:u1,u2,u3のmyid

    6.フォルダ構成

    ※一部フォルダは省略

    図13:フォルダ構成6

    実行手順

    起動順序に制約はありませんが、Float→Node→ZooKeeper→Bridgeの順が望ましいです。
    Bridgeは相手先であるFloatやNode、ZooKeeperが起動していない場合、起動はするもののエラーメッセージを出力します。
    一方、FloatやNode、ZooKeeperはListen Portを開くだけなので、単独起動してもエラーメッセージは出力しません。

    1.Float起動

    cd /firewall
    java -jar corda-firewall-4.7.jar -f float/float.conf
    java -jar corda-firewall-4.7.jar -f float2/float.conf

    ▼オプション(Bridge/Float共通)

    表9:firewallコマンドのオプション

    2.Node起動

    cd /node
    java -jar corda-4.7.jar

    3.ZooKeeper起動

    cd /firewall/apache-zookeeper-3.6.2-bin
    ./bin/zkServer.sh start u1/zoo.cfg
    ./bin/zkServer.sh start u2/zoo.cfg
    ./bin/zkServer.sh start u3/zoo.cfg

    4.Bridge起動

    cd /firewall
    java -jar corda-firewall-4.7.jar -f bridge/bridge.conf
    java -jar corda-firewall-4.7.jar -f bridge2/bridge.conf

    設定時のポイント及び注意点

    設定時に気をつけるポイントは、大きく2点です。

    1. FloatのinboundConfig.listeningAddressのアドレスは、デフォルトルート(0.0.0.0)を設定する。
      同アドレスは、String型で1つのみ指定可能です。HA構成とする場合、それぞれの設定ファイルで異なるアドレスを指定することは出来ません。
      本来であれば、一般的に言われるFirewallやLoadBalancerの外側のアドレスを指定します。しかし、今回は配置していないため、デフォルトルートを設定することで、ポート番号でInbound許可を設定します。
    2. Nodeのsslkeystore.jksのパスワードは、特に設定していない場合はデフォルト値が設定されている。
      Bridgeの設定ファイルで、Nodeのsslkeystore.jksを指定する時に使用します。
      未設定の場合はデフォルト値が設定されるので「パスワードは何?」と思うかもしれません。公式ドキュメントには、各フィールドのデフォルト値が記載されています。
      https://docs.corda.net/docs/corda-enterprise/4.8/operations/deployment/corda-configuration-fields.html#keystorepassword

    各サービスの生死状態における通信可否の検証

    Bridge、Float、ZooKeeperの各サービスが生死状態において、通信が行えるかを検証しました。

    ▼検証内容

    NodeA(Corda Firewall有)からNodeB(Corda Firewall無)へStateを送る。
    それぞれの生死状態で計算すると「Bridge2台、Float2台、ZooKeeper3台の生死状態 = 2⁷ = 128件」となり、冗長なテストケースもあるため、1台停止・全台停止などを組合せた計29件を検証対象としています。

    ▼検証結果

    表10:各サービスの生死状態における通信可否の検証結果

    結果は上表の通りになりました(実施対象のみ抜粋)。

    合否の列は、通信の可否を表しています。
    BridgeとFloatはHot-Warmスタンバイのため、Hotが停止した際にWarmがHotとして切り替わり、Warmのみが起動ということはありませんが、表示の便宜上このような記載になっていることをご了承ください。

    各サービスで全台停止がある場合(例:「Bridgeが全台停止」など)のみ、通信が止まるという結果になりました。停止した通信は、当該サービスを起動することで、通信を再開します。

    Corda Firewall 設定におけるTPSの変化

    Corda JMeterを用いて、Corda Firewallの有無でTPSに変化があるのかを検証しました。 Corda JMeterの使用方法については、過去記事を参照ください。 ※Corda JMeterの使い方

    ▼検証内容

    • NodeBでJMeterを実行
    • NodeB(Corda Firewall無)からNodeA(Corda Firewall有)へStateを送る
    • NodeAのCorda Firewallの設定を有無でそれぞれ5回ずつ実施 スレッド数:10、Ramp-up:0、ループ:5

    ▼検証結果

    結果は下表の通りとなりました。Corda Firewallを設定することで、1割程度の処理低下が見られますが、許容範囲内に収まっているかと思います。

    表11:Corda Firewall設定におけるTPSの変化検証の結果

    表12:Corda Firewall設定におけるTPSの変化検証の平均・最長・最短時間

    おわりに

    今回はCorda Firewallの設定方法と設定時のポイントや注意点、TPSの変化の有無を紹介しました。
    躓いた点としては、先に挙げた通り、一般的に言われるFirewallやLoad Balancerを配置していないため、Floatの設定ファイルで記述する「inboundConfig.listeningAddress」をデフォルトルートとして設定しなければならなかったという所でした。
    NodeBのアドレスを指定すればNotaryの署名時に、Notaryを指定すればそもそもNodeBとの通信時に弾かれてしまい、当初は思うように通信が行えていませんでした。
    しかし、裏を返せば、Corda Firewallが正常に動作していることの証明とも言え、歯がゆい数日間を過ごしました。
    上記以外は特に躓くこと無く設定が行えたため、ドキュメントの記述量の割に難易度は比較的低いかと思います。

    以上です。