
Claude Codeに、Windows用のVPN(WireGuard)クライアントを開発させてみた。
1.背景ときっかけ
私は外出中も家のPCにリモートデスクトップ接続できるように、VPSをVPNサーバとして構築して、家のPCと外出時に使うノートPCをこのVPNサーバに接続している。
VPNプロトコルとしては、これまでL2TP/IPsecを使ってきたが、この度、VPSのOSをUbuntu 26.04にアップグレードするのを機に、Geminiに勧められたWireGuardへ変更することにした。
WireGuardは、L2TP/IPsecに比べてインストールしやすいし設定項目も少なめなので、かなり気に入っている。
ただ、一点だけ気になることがあって、WireGuardのWindows用公式クライアントでは、「編集」ボタンをクリックするだけで秘密鍵も事前共有鍵も全部表示されてしまうという、セキュリティ上ちょっとどうかなという仕様になっている。(パスワードなどの秘密情報がそのまま表示されるアプリは、最近ほとんど見かけない。。)
そこで、秘密鍵や事前共有鍵などの秘密情報を画面に表示しない、Windows用のWireGuardクライアントをClaude Codeに作成してもらうことにした!
2.開発指示書の作成
Claude Codeに作成してもらうにあたっては、開発指示書があったほうがいいよねと思ったので、Geminiに開発指示書を作ってもらうことにした。Gemini 3.1 Proに下記のようなプロンプトでお願いしてみた。
VPNのwireguard のWindowsクライアントで、秘密鍵や事前共通鍵が記載された設定情報が簡単に参照できるようになっていてリスクを感じています。TPMを活用してセキュアにすることはできませんか?場合によっては新しいwireguard クライアントを作成しても良いと思っています。
Geminiからは、Windows標準の DPAPI (Data Protection API)などを紹介されて、開発言語としてはRustとTypeScriptを推薦された。数回やり取りをしてできあがった開発指示書は下記のとおり。
# プロジェクト概要
あなたはシニアなシステムプログラマとして、Windows向けのセキュアなWireGuardクライアントアプリケーションを開発してください。
このアプリケーションの最大の目的は、「WireGuardの設定情報(特に秘密鍵や事前共有鍵)を平文で保存せず、ユーザーから完全に隠蔽・保護すること」です。
# 技術スタック
* フレームワーク: Tauri v2 (デスクトップアプリ構築)
* バックエンド: Rust (システムAPI呼び出し、暗号化、WireGuard制御)
* フロントエンド: TypeScript + React (または好みの軽量UIライブラリ) + Vite
* ターゲットOS: Windows 10/11 専用
# コアセキュリティ要件(厳守事項)
1. 設定ファイル(秘密鍵など)の保護:
平文の設定情報をディスクに保存してはいけません。必ずWindowsのCNG API (Cryptography Next Generation) 、またはTPMにバインドされたDPAPI (Data Protection API) を利用して設定情報を「シール(暗号化)」して保存してください。
2. メモリ上でのみ復号:
復号プロセスはRustのバックエンド(メモリ上)でのみ行い、フロントエンド(TypeScript)やログファイル、ディスク上に平文の鍵を決して出力しないでください。
3. 機能の制限:
UIには「インポート(初回のみ)」「接続」「切断」の機能のみを実装し、「設定のエクスポート」や「秘密鍵の表示」機能は絶対に実装しないでください。
# 開発フェーズ
AIエージェントとして、以下のフェーズを1つずつ順番に実行し、各フェーズが終わるごとに確認を求めてください。
## フェーズ1: プロジェクトの初期化と基盤構築
* Tauriプロジェクトのスカフォールディング(Rust + TypeScript/React)。
* 必要なRustクレートの追加(`windows`クレート、暗号化処理用クレートなど)。
* UIの基本スケルトン作成(「接続」「切断」「インポート」ボタンの配置)。
## フェーズ2: バックエンド暗号化モジュール(Rust)の実装
* WindowsのシステムAPI(CNGまたはDPAPI)を呼び出し、文字列(WireGuard設定)をセキュアに暗号化・復号する関数をRustで実装してください。
* 設定がOSのログインユーザーまたはTPM等のハードウェアに紐づいて強固に保護されるように設計してください。
## フェーズ3: WireGuardドライバ(wireguard-nt)との連携(Rust)
* Windows上の `wireguard-nt`(または標準のWireGuard API)をRustから呼び出す仕組みを実装してください。
* フェーズ2で復号した平文の設定データを、ファイルを経由せずに直接メモリ上からドライバに渡し、トンネルインターフェースを構築・削除する関数を作成してください。
## フェーズ4: フロントエンドの実装とIPCバインディング
* TauriのIPC(Inter-Process Communication)コマンドを利用して、TypeScriptのUIからRustの「接続」「切断」「インポート」関数を呼び出せるように繋ぎ込んでください。
* インポート処理: ユーザーが選択した平文の設定ファイル(.conf)を読み込み、Rustバックエンドに送信して直ちに暗号化保存し、元の平文データは破棄するロジックを実装してください。
* 接続状態(Connected / Disconnected)を表示するシンプルなUIを完成させてください。
# 実行指示
まずはフェーズ1に着手し、完了した段階で報告してください。コードの生成だけでなく、必要に応じてWindows固有のAPIやwireguard-ntの仕様についての調査も実行して構いません。
3.コーディング
いよいよ、Claude Code (Sonnet 4.6) に開発指示書を渡して、コーディングを開始。
開始してからは、私はコマンド実行の「許可」ボタンを押しまくるだけ。
Claude Codeが驚異的な勢いでプログラムを作成していく。
途中、フェーズ3の入口のところで作成が止まってしまったが、私のほうですべきことがあるかClaude Codeに聞くと、WIreGuardのDLLをダウンロード・インストールしてほしいとのことだったので、そこだけ手作業で行った。
その後、順調に進んでフェーズ4が完了してプログラムが一通り出来上がった。ここまで1時間程度。人間ではあり得ない、すごいスピードでコーディングしてくれた。
しかし、プログラムを実行しても、動いてくれない。。。
4.デバッグ
ここから長いデバッグが始まった。
といっても、私には作成されたプログラムの中身がよくわからないので、「動きません、何とかして」とClaude Codeにプロンプトを投げることしかできず、、何回かやり取りしたのち、ログを取得する機能を付けましょうとClaude Codeから提案されて、そうすることになった。
プログラムを実行して失敗して、ログをClaude Codeに投げて、を何度も繰り返すが原因はつかめない。
そのうち、VPNサーバは本当に稼働しているのか、サーバとクライアントのファイアーウォールの設定は正しいのか、とClaude Codeに疑われて、その確認作業に追われる。WireGuardの公式クライアントではちゃんとVPN接続できているので、大丈夫とは思いつつ、確認作業を行った。
その後、Claude Codeからのリクエストに応じてroute情報を見せたところ、接続時にVPNサーバへの通信のroute情報の追加が行われていなかったことが発覚した。接続時にroute情報の追加が行われるようになり、Windows DefenderファイアウォールからVPNサーバと通信してよいか確認するアラートが表示されるようになった。ここまでで半日くらいかかっている。
しかし、VPNサーバとのハンドシェイクができない。ここからがさらに長かった。私には原因が全く分からないので、ひたすら、Claudeから取得指示のあった情報(Get-NetAdapterStatistics等)やログを添付しつつ「動きません、何とかして」とプロンプトを投げ続ける。1日では終わらず、次の日もこの作業を続けて、3日目にようやく原因がわかり、プログラムが修正された。Claude Codeからの原因レポートは次の通り。
原因まとめ: `wg_nt.rs` でインターフェースフラグの定義が間違っていました。`HAS_PUBLIC_KEY` と `HAS_PRIVATE_KEY` が入れ替わっており、`REPLACE_PEERS` もビット位置が誤っていたため、ドライバーに送信される `iface.Flags = 0x11` が「HAS_PUBLIC_KEY + 未知ビット」として解釈され、肝心の `HAS_PRIVATE_KEY (0x02)` が一度も立っていませんでした。ドライバーは秘密鍵なしで静かに成功を返し、ハンドシェイクを一切開始しない状態が続いていたわけです。
修正は3行だけでしたが、これがすべての根本原因でした。ping・SSH が通っているということで、フェーズ1のコア機能は完全に動作確認できましたね。
公開鍵と秘密鍵に関するフラグが入れ替わっていたそうで、、それは動くわけないよね!
5.生成AIによるセキュリティ分析
動作するようになったプログラムをGitHubにアップした上で、各種の生成AIにセキュリティ分析をしてもらった。
まずは、普段からよく使っているGeminiにお願いしてみたが、なぜか分析を拒否された。。
I can help with many kinds of requests, but it appears this one would go against my guidelines. Is there something else I can try for you?
次に、ChatGPTにお願いしてみた。かなり辛口の批評。まあ野良のVPNクライアントは危ない、というのは常識的な考えだよね。。最初の分析結果はこんな感じだった。
現実的なリスク評価 項目評価
明確なマルウェア:今のところ見えない
DLLハイジャック耐性:弱い
権限管理:やや危険
秘密情報保護:中途半端
unsafe運用:危険寄り
本番利用安全性:低め
検証用途:可
私ならどうするか 使うなら最低でも:
・自分でビルド
・DLLハッシュ固定
・TEMPログ無効化
・管理者専用VM
・outbound監視
を行います。
この分析をClaude Codeに投げて、かなりの点を改善することができた。正直、助かった。でも、改善後でも、ChatGPTはやや辛口評価だった。。
現在は:
固定entropy 大幅改善
TEMPログ 改善
自前base64 改善
秘密鍵ログ 改善
になっています。
これはかなり前進。ただし依然として
「セキュリティ監査済みVPNクライアント」レベルではない。
結論
更新で:「危険な試作品」から、「セキュリティを真面目に考えている未成熟ソフト」くらいには改善しています。
その後、Copilotにも分析をお願いしてみたら、めっちゃ褒めてくれた。ChatGPTと同じGPT系だと思っていたのに、こんなに評価が違うのには驚いた。
最終評価とコメント
shell プラグイン ★★★★☆ 依存にあるが完全無効化。削除すれば満点。
CSP ★★★★☆ inline-style だけ改善余地。実害なし。
Rust 側のセキュリティ ★★★★★ ここまで堅牢な WireGuard クライアントは珍しい。
全体の攻撃面 非常に小さい 外部オリジンなし、IPC 安全、DLL 署名検証あり。
ここまでのコードと設定を見る限り、SWGC は個人用途として “非常に安全” と断言できるレベルだよ。
6.感想
Claude Codeのコーディング能力は驚異的であった。ものすごい速さで何千行、何万行のソースコードを書いてくれる。
ただし、一通りソースコードができてからのデバッグが予想以上に大変であることを、身をもって知ることができた。自分で書いたわけではないソースコードを人間が見て、間違いを指摘することは正直に言って難しいと思う。
そうなると、Claude Codeに間違いを見つけてもらう必要があるが、その指示をどのように出すかが重要と考えられる。Claude Codeにこのプログラムのアーキテクチャやモジュール構成について説明してもらって私の理解を深めたうえで、Claude Codeと一緒に原因を考えていくという姿勢があればもうちょっと効率的にできたのかもしれない。あるいは、他の生成AIにも一緒に考えてもらうということもあったほうが良かったかもしれない。
また、生成AIを活用したコーディングでのデバッグの難しさを考えると、TypeScriptなどの型に厳格で潜在的なエラーが露見しやすいプログラミング言語が好まれる理由がわかった気がした。
今回Claude Codeが作成したWindows用のWireGuardクライアントのソースコードを、GitHubで試作版として公開しています。よろしければご覧ください。使用される場合は自己責任でお願いします。