本日、SingLinkVPNを開発するチームSingLinkLabsは、SingLinkプロトコルの全ソースコードをApache-2.0ライセンスのもとGitHubで公開しました。仕様書を読む、コードを動かす、セキュリティを検証する、その上に新しいものを作る。これらすべてが、誰にでもできるようになりました。

SingLinkVPNオープンソース計画を発表した際、VPNプロトコルとVPNクライアントを段階的に公開するとお伝えしました。今回がその一歩です。プロトコルは、その上で動作するSingLinkVPNアプリの初代プロトタイプと同時に公開します。詳しくは「SingLinkVPNアプリのプロトタイプをオープンソース化しました」をご覧ください。

リポジトリ: SingLinkLabs / singlink-protocol · バージョン: 1.0.0-draft(ワイヤー名SingLink/1、仕様ドラフト第2版) · ライセンス: Apache-2.0 · 言語: Go(標準ライブラリのみ)

今回公開するもの

  • 仕様書。 SPEC.mdはワイヤーフォーマットをバイト単位で記述しているため、このプロトコルを独自に実装することもできます。

  • Goによるプロトコルライブラリ。 暗号処理にはGo標準ライブラリだけを使い、サードパーティへの依存は一切ありません。

  • コマンドラインツール。 鍵の生成、アクセスパスの発行、接続リンクの作成、ノードとクライアントの実行、1台のマシンで完結するデモの起動ができます。

  • アプリ向けのローカルプロキシ(SOCKS5とHTTP)とCライブラリインターフェース(libsinglink)。どのプラットフォームのアプリにもプロトコルを組み込めます。

  • デプロイ例。 ノード設定のサンプルと、堅牢化したsystemdサービスファイル。

  • 内部セキュリティレビュー。 すべての指摘事項と修正内容をSECURITY-AUDIT.mdにまとめています。

公式SingLinkVPNアプリは、SingLink 2.0をはじめとする当社の本番用プロトコルで動作しています。SingLink 2.0のコアソースコードは今回の公開には含まれず、引き続き非公開です。

本日公開したSingLinkプロトコル(SingLink 2.0と区別する必要があるときは「SingLinkオープンプロトコル」と呼びます)は、SingLinkLabsがオープンな開発のためにゼロから設計した別のプロトコルです。現時点で公式アプリはこのプロトコルを使っていません。既存のユーザーにとっては何も変わらず、アプリもアカウントも接続もこれまでどおりです。

オープンソースにする理由

  • セキュリティの主張は検証できるべきだから。 耐量子鍵交換、デバイスバインディング、プローブ耐性は、うたうだけなら簡単です。コードと仕様が公開されていれば、誰でも確かめられます。

  • 多くの目があれば、問題は早く見つかるから。 社外の研究者やエンジニアは、社内チームが見落とした問題に気づくはずです。

  • 誰もがその上に構築できるから。 開発者はテストしたり、自分のプロジェクトに組み込んだり、改善を提案したりできます。

  • 計画を約束どおりに進めるため。 プロトコルの公開は、私たちが約束した段階の一つでした。

仕組みをわかりやすく

一言でいえば、外から見るとユーザーはごく普通のHTTPSウェブサイトを訪れているだけです。その中に暗号化されたアクセス要求が隠されていて、サーバーは有効なパスを持つ人のためだけに通信を中継します。

設計には3種類の鍵を使います。オフィスビルのセキュリティにたとえてみましょう。

  • ノード鍵は、ドアの錠。 サーバーごとに固有の鍵があります。ユーザーの要求を開けられるのはそのサーバーだけで、これによりユーザーが本物のサーバーにたどり着いたことも証明されます。

  • 発行者鍵は、人事部の印鑑。 アカウントのバックエンドに保管され、各アクセスパスにプラン、有効期限、速度制限、デバイス数の上限を記して押印します。

  • デバイス鍵は、ユーザーの指紋。 ユーザーのスマートフォンやコンピューターに保管され、すべての接続に署名して、パスが正当な持ち主によって使われていることを証明します。

サーバーは印鑑の印影さえ知っていれば、パスを単独で確認できます。だからノードはユーザーデータベースを持たず、ユーザーデータも一切保存しません。

1回の接続で起きること

  1. アプリは、ウェブサイトへのごく普通のHTTPS接続に見える接続を開きます。

  2. 最初のパケットには、この接続専用の使い捨て鍵、耐量子暗号文、そして封印されたセクションが入っています。封印部分には接続先、アクセスパス、実データの先頭最大8 KB、要求全体に対するデバイス署名が含まれます。追加の往復通信は必要ありません。

  3. サーバーはすべてを確認します。要求を復号できるか、印鑑が本物か、デバイス署名が一致するか、時刻が正しいか、そして要求がリプレイでなく、期限切れでも失効済みでもないか。

  4. すべての確認に合格した場合にのみ応答し、中継を始めます。一つでも失敗すれば、接続には一切手を加えずに本物のウェブサイトへ引き渡します。サーバーを探ろうとする者には普通のウェブサイトしか見えず、応答時間にも違いはありません。

  5. 双方がそれぞれの使い捨て鍵を組み合わせて、この接続のセッション鍵を作ります。データはチャンク単位で暗号化され、最初のいくつかのチャンクにはパディングが加えられ、一定量を使うと鍵は自動的に更新されます。

セキュリティ特性

  • 二重の暗号化。 外側のHTTPSに加えて、内側にプロトコル独自のAES-256-GCM層があるため、HTTPSを終端するCDNであっても中身は見えません。

  • 耐量子保護。 鍵交換は従来のX25519とML-KEM-768(FIPS 203)を組み合わせています。攻撃者は両方を破らなければなりません。

  • 前方秘匿性。 接続ごとに使い捨ての鍵を使うため、後からサーバーが侵害されても過去の通信は復号できません。ただし最初のパケットは例外です(後述の制限事項を参照)。

  • デバイスバインディング。 どこかからコピーしたアクセスパスは、発行先のデバイス鍵がなければ役に立ちません。

  • リプレイ対策。 傍受したパケットを再送しても通用しません。サーバーを再起動した後でも同じです。

  • プローブ耐性。 期限切れ、失効済み、リプレイ、偽造の要求はすべて同じ扱いを受け、本物のウェブサイトへ引き渡されます。

  • 一元管理。 アカウントやデバイスを失効させると、すべてのサーバー上で稼働中の接続が約10秒以内に切断されます。

  • 堅牢化されたサーバー。 サーバー単位とIP単位の接続数制限、ハンドシェイク用のCPU予算、プライベートアドレスと特殊用途アドレスを網羅したブロックリストを備えています。

設計の着想元

SingLinkプロトコルは、実績のある設計から学んでいます。VLESSとTrojanの単一リクエスト接続、Trojanとobfs4の「失敗した接続を本物のウェブサイトへ引き渡す」手法、Noise NKハンドシェイクパターン、TLS 1.3の鍵導出と0-RTTの扱い、X-Wingドラフト標準のハイブリッド耐量子鍵交換、Shadowsocks AEADのチャンク暗号化、JWTとPASETOの署名付きトークン、OAuth DPoPのデバイスに紐づくトークン、HAProxy PROXY protocol、そしてWireGuardのリプレイ対策と負荷対策です。

参考にしたのは設計のアイデアだけです。コードはすべてゼロから書きました。Xray、V2Ray、sing-box、WireGuardのコードは一切含まれていません。

現状と既知の制限

  • ドラフト段階です。 バージョンは1.0.0-draftで、ワイヤーフォーマットは今後変わる可能性があります。

  • 現時点では内部セキュリティレビューのみです。 2名のレビュアーが暗号設計と実装をそれぞれ別に検証し、31件の指摘事項を記録しました。内訳はHighが2件、Mediumが14件、残りはLowまたは情報提供レベルです。ユーザー通信の機密性や認証を破るものはありませんでした。HighとMediumの指摘はすべて修正または緩和済みで、それぞれに回帰テストを用意し、すべてのパーサーをファジングテストでカバーしています。

  • 第三者監査はまだ受けていません。 独立した監査を受けるまでは、リスクの高い用途でこのプロトコルに頼らないことをおすすめします。安定版と呼ぶ前に、監査を実施する予定です。

  • 最初のパケットには前方秘匿性がありません。 サーバーの長期鍵で保護されているため、サーバー鍵は定期的にローテーションしてください。鍵のローテーションには対応しています。

  • 中国本土での実地検証は行っていません。 TLSフィンガープリントと最初のパケットのサイズは、まだ識別できてしまいます。中国本土のユーザー向けには、公式SingLinkVPNアプリが引き続き既存の本番用プロトコルを使います。

  • サーバーには独自のドメインが必要です。 さらに、ブラウザが受け入れる証明書と、背後で動く本物のウェブサイトも必要です。

試してみる・参加する

Go 1.24以降があれば、make testでテストスイートを実行し、make cliでコマンドラインツールをビルドし、singlink demoで1台のマシン上にローカルのサーバーとクライアントを起動できます。サーバーの運用方法はリポジトリのREADMEで説明しています。

質問、バグ報告、Pull RequestはGitHubでお待ちしています。セキュリティ脆弱性は公開のIssueではなく、非公開で報告してください。手順はSECURITY.mdに記載しています。

ライセンスと商標

コードはApache-2.0ライセンスで提供します。ライセンスの条件に従えば、商用を含めて使用、改変、再配布できます。「SingLink」「SingLinkVPN」の名称とロゴはSingLinkLabsの商標であり、ライセンスは、成果物の出所を説明する範囲を超えてこれらを使用する許可を与えるものではありません。改変版やフォークは、独自の名称とアイコンで公開してください。

あわせて読みたい