Rosenpass
関連記事
Rosenpass は、将来の量子コンピュータの脅威から WireGuard VPN 接続を保護するために設計された、オープンソースの耐量子安全な鍵交換プロトコルです。Rosenpass は WireGuard と並行して動作し、耐量子安全な共有シークレットを WireGuard の事前共有鍵インターフェイスに注入します。すべての VPN トラフィックは引き続き WireGuard のみを通過し、WireGuard のバイナリとプロトコルは変更されないため、WireGuard 単体が持つすべてのセキュリティ保証は維持されます。
Rosenpass は Rust で書かれており、主な開発は GitHub で調整されています。また、MIT ライセンスおよび Apache 2 ライセンスの下で公開されています。
インストール
Rosenpass とヘルパーツール rp を提供する rosenpass パッケージをインストールしてください。
テスト
インストールが成功したことを簡単に確認するには、rosenpass と rp の両方のツールで help コマンドを実行し、短い使用方法のヒントを表示します:
$ rosenpass help
$ rp help
設定
このセクションでは、2 つのピア間で Rosenpass により強化された WireGuard 接続をセットアップする方法を示します。技術的には、2 つのピアに違いはありません。ただし、わかりやすくするために、それぞれ server と client という名前を付けています。
鍵ペアの準備
各ピアは、シークレット鍵と公開鍵で構成される鍵ペアを生成する必要があります。
両方のピアのシークレット鍵を生成する
以下のコマンドはシークレット鍵を生成し、新しく作成される server.rosenpass-secret および client.rosenpass-secret ディレクトリに保存します:
[server]$ rp genkey server.rosenpass-secret
[client]$ rp genkey client.rosenpass-secret
公開鍵を抽出する
以下のコマンドは公開鍵を計算し、新しく作成される server.rosenpass-public および client.rosenpass-public ディレクトリに保存します:
[server]$ rp pubkey server.rosenpass-secret server.rosenpass-public
[client]$ rp pubkey client.rosenpass-secret client.rosenpass-public
各 -public ディレクトリを相手側のピアへコピーする
両方のピアには、それぞれ相手側ピアの -public ディレクトリが必要です。また、それは既に存在している -secret および -public ディレクトリの隣に配置する必要があります。両方のマシンへ SSH アクセスできる場合は、以下のコマンドを使用できます:
[server]$ scp -r server.rosenpass-public user@client:/path/to/directory
[client]$ scp -r client.rosenpass-public user@server:/path/to/directory
これで鍵ペアのセットアップは完了です。
Rosenpass により強化された WireGuard VPN を起動する
以下の 2 つのコマンドでは、$SERVERIP を client が server に到達できる IP アドレスに置き換えてください。これはパブリックにルーティング可能な IP アドレス、ローカルネットワーク内の IP アドレス、あるいはループバックアドレス 127.0.0.1 でもかまいません。
同様に、$DEVICE は、server が $SERVERIP 宛てのパケットを受信するネットワークデバイスの名前に置き換えてください。
ネットワークデバイスと IP アドレスに関する情報は、以下のコマンドで確認できます:
[server]$ ip a
VPN を起動する
server と client の両方で Rosenpass と WireGuard プロセスを起動します。これにより、rosenpass0 という名前の WireGuard ネットワークインターフェイスが作成されます。次の手順で、このインターフェイスに内部 IP アドレスを割り当て、内部ネットワーク用のルートを追加します。
以下の 2 つのコマンドでは、$SERVERIP を client が server に到達できる IP アドレスに置き換えることを忘れないでください。
[server]# rp exchange server.rosenpass-secret \ dev rosenpass0 \ listen $SERVERIP:9999 \ peer client.rosenpass-public \ allowed-ips 192.168.21.0/24
[client]# rp exchange client.rosenpass-secret \ dev rosenpass0 \ peer server.rosenpass-public \ endpoint $SERVERIP:9999 \ allowed-ips 192.168.21.0/24
IP アドレスを割り当てる
この例では、VPN 内部ネットワークとして 192.168.21.0/24 のアドレスを使用します。他のアドレスを試してもかまいませんが、必要に応じてすべてのコマンド内の IP アドレスとネットワークを調整してください。
[server]# ip a add 192.168.21.1 dev rosenpass0
[client]# ip a add 192.168.21.2 dev rosenpass0
WireGuard ネットワーク用のルートを追加する
ルーティングテーブルに内部ネットワーク 192.168.21.0/24 用のエントリが含まれていることを確認してください。これは以下のコマンドで確認できます:
$ ip route
出力には、192.168.21.0/24 ネットワークに関する行が含まれ、インターフェイス rosenpass0 が示されているはずです:
… 192.168.21.0/24 dev rosenpass0 scope link …
このような行が存在しない場合は、以下のコマンドでルートを追加できます:
# ip route add 192.168.21.0/24 dev rosenpass0
server と client の両方で確認し、必要に応じて実行することを忘れないでください。
ファイアウォールを設定する
ファイアウォールの背後にいるかどうかわからない場合 は、この手順をスキップして、接続できない場合に戻ってきてもかまいません。
この例では、server は 2 つのポートで到達可能である必要があります。Rosenpass 接続用の 9999 と、WireGuard 接続用の 10000 です。ポート 9999 は次の手順で使用するコマンド内で明示的に設定されています。WireGuard のポートは、rp ツールによって Rosenpass のポート番号に 1 を加えた値に暗黙的に設定されます。この例では 10000 です。
ファイアウォールを設定 して、ポート 9999 および 10000 への受信 UDP パケットを許可してください。
Uncomplicated Firewall を使用している場合は、この例のセットアップに必要な受信接続を許可するルールを追加するために、以下のコマンドを使用できます。$SERVERIP を client が server に到達できる IP アドレスに、$DEVICE を server が $SERVERIP 宛てのパケットを受信するネットワークデバイス名に置き換えることを忘れないでください。
[server]# ufw allow in on $DEVICE \ from any to $SERVERIP \ port 9999 \ proto udp \ comment 'Rosenpass'
[server]# ufw allow in on $DEVICE \ from any to $SERVERIP \ port 10000 \ proto udp \ comment 'WireGuard'
新しいファイアウォールルールは以下のようになります:
server # ufw status
Status: active To Action From -- ------ ---- $SERVERIP 9999/udp on $DEVICE ALLOW Anywhere # Rosenpass $SERVERIP 10000/udp on $DEVICE ALLOW Anywhere # WireGuard
nftables を使用している場合は、Rosenpass の要件を満たすルールを追加するために、以下のコマンドを使用できます。このコマンドは、適切なファイアウォールテーブルとチェインが filter および input という名前であることを前提としています。これらは nftables のサンプル設定で使用される標準的な名前です。$SERVERIP を client が server に到達できる IP アドレスに、$DEVICE を server が $SERVERIP 宛てのパケットを受信するネットワークデバイス名に置き換えることを忘れないでください。
[server]# nft add rule \
inet filter input iif $DEVICE \
udp dport { 9999, 10000 } \
ip daddr $SERVERIP accept
再起動後もこのルールが維持されるように保存してください。方法の 1 つは、/etc/nftables.conf に追加することです。
セットアップを検証する
Rosenpass ハンドシェイクをテストする
最初のテストとして、Rosenpass が共有シークレットを交換し、それを事前共有鍵 (PSK) として WireGuard に渡せているか確認します。
server と client の両方で、以下のコマンドを実行すると、WireGuard が接続に使用している事前共有鍵を確認できます。これは秘密であるべき暗号鍵素材を表示するため、コンピュータの画面を誰が見られる状態にあるか注意してください:
# wg show rosenpass0 preshared-keys
出力には、スペースで区切られた 2 つの base64 エンコード文字列からなる 1 行が表示されるはずです。2 番目の文字列が事前共有鍵です。これは両方のマシンで同じである必要があります。Rosenpass はこれをおよそ 2 分ごとに変更します:
q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I= (redacted)
同様に、server と client の両方で WireGuard 接続の状態を表示できます:
# wg show rosenpass0
client では以下のような出力が表示されるはずです。ここで $SERVERIP は以前に設定した IP アドレスと一致します:
interface: rosenpass0 public key: 1NQJ1iObOnkkWlqDU6bhqGPEjCIIvKTKjI10XE0t7DA= private key: (hidden) listening port: 52922 peer: q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I= preshared key: (hidden) endpoint: $SERVERIP:10000 allowed ips: 192.168.21.0/24
server では以下のような出力が表示されるはずです。WireGuard の待ち受けポートは 10000 です:
interface: rosenpass0 public key: q1ySvWXjsS2l0Apu2f9YZLw7pLT4+QXfIZVTpMBO01I= private key: (hidden) listening port: 10000 peer: 1NQJ1iObOnkkWlqDU6bhqGPEjCIIvKTKjI10XE0t7DA= preshared key: (hidden) allowed ips: 192.168.21.0/24
表示される server の公開鍵は client 側の peer の ID として表示され、逆も同様である必要があります。
WireGuard トンネルとその事前共有鍵の現在の状態を継続的に監視したい場合は、client と server の両方で以下のコマンドを使用できます。これはデバッグ時に便利です。たとえば、両側が同じ事前共有鍵を使い続け、それを同期して交換しているかを確認できます。このコマンドは、上記の 2 つのコマンドを組み合わせ、2 秒ごとに繰り返します:
# watch 'wg show all; wg show all preshared-keys'
WireGuard 接続をテストする
client ピアから server の内部 IP アドレスへ ping を送信し、その逆も行うことで、WireGuard 接続をテストできます:
[server]$ ping 192.168.21.2
[client]$ ping 192.168.21.1
server から client への ping は、client から server への ping を開始した後にのみ通る場合があります。
すべて完了し、ping テストが成功しましたか?
これで Rosenpass は、およそ 2 分ごとに WireGuard 用の新しい PSK 鍵を生成し、WireGuard VPN 接続を量子コンピュータによる将来の攻撃から保護し続けます。