2 ポイント 投稿者 GN⁺ 2024-04-03 | 1件のコメント | WhatsAppで共有
  • Wireproxy は、WireGuard ピアに接続したうえでローカルマシン上に SOCKS5/HTTP プロキシまたはトンネルとして公開される、完全なユーザー空間の WireGuard クライアント
  • 新しいネットワークインターフェイスを設定せずに特定サイトのトラフィックだけを WireGuard ピアへ送りたい場合や、WireGuard 設定変更に root 権限を使いたくない場合を想定している
  • 機能には TCP 静的ルーティング、SOCKS5/HTTP プロキシ、TLS SNI ベースの透過プロキシが含まれ、HTTP プロキシは現時点では CONNECT のみをサポート
  • 設定は wg-quick[Interface][Peer] の意味に従い、既存の WireGuard 設定ファイルを WGConfig で取り込んだり、複数ピアを AllowedIPs でルーティングしたりできる
  • 運用向けに --info/-i ベースの health endpoint を提供し、/metrics/readyz で WireGuard の状態と CheckAlive ベースの準備状態を確認できる

Wireproxy がすること

  • wireproxy は WireGuard ピアに接続し、ローカルマシンに SOCKS5/HTTP プロキシまたはトンネルを公開するユーザー空間アプリケーション
  • 特定サイトだけを WireGuard ピア経由で接続したいが、新しいネットワークインターフェイスは作りたくない場合に利用できる
  • ネットワークインターフェイスから完全に分離して動作し、設定のために root 権限は不要
  • Amnezia VPN と似た用途が必要なユーザーは、wireproxy-awg フォークを利用できる

対応機能とまだない機能

  • 対応機能
    • クライアントおよびサーバー向けの TCP 静的ルーティング
    • SOCKS5/HTTP プロキシ
      • HTTP は現時点では CONNECT のみをサポート
    • Server Name Indication を使用する 透過 TLS プロキシ
  • TODO として残っている機能
    • SOCKS5 の UDP 対応
    • UDP 静的ルーティング

実行とインストール

  • 基本の実行形式は ./wireproxy [-c path to config]
  • 主なオプション
    • -c, --config: 設定ファイルのパスを指定
      • デフォルトパスは /etc/wireproxy/wireproxy.conf, $HOME/.config/wireproxy.conf
    • -s, --silent: silent mode
    • -d, --daemon: バックグラウンド実行
    • -i, --info: health status 公開用のアドレスとポートを指定
    • -v, --version: バージョンを出力
    • -n, --configtest: 設定ファイルの妥当性のみを確認
  • ビルドはリポジトリをクローンした後、make で行う
  • インストール例では go install github.com/windtf/wireproxy/cmd/wireproxy@v1.1.2 または @latest を使用する

設定モデル

  • [Interface][Peer] の設定は wg-quick 設定と同じ意味に従う
  • Address は IPv4 の場合 /32、IPv6 の場合 /128 サブネットを使用する必要がある
  • PrivateKey は環境変数参照も可能
  • 既存の WireGuard 設定がある場合は WGConfig = <path to the wireguard config> で取り込める

トンネルとプロキシ設定

  • TCPClientTunnel
    • ローカルマシンで受信した TCP トラフィックを、WireGuard 経由で指定先へ転送する
    • 例のフローは <LAN 앱> → localhost:25565 → WireGuard → play.cubecraft.net:25565
  • TCPServerTunnel
    • WireGuard ネットワークで受信した TCP トラフィックを、ローカルネットワーク上の指定先へ転送する
    • 例のフローは <WireGuard 네트워크 앱> → WireGuard → 172.16.31.2:3422 → localhost:25545
  • STDIOTunnel
    • wireproxy プロセスの標準入力と標準出力を、WireGuard 経由の TCP 宛先に接続する
    • opensshProxyCommand パラメータとして使うのに便利
  • Socks5
    • ローカル LAN に SOCKS5 プロキシを作成し、すべてのトラフィックを WireGuard にルーティングする
    • ユーザー名とパスワードを指定すると、プロキシ認証を有効化する
  • http
    • ローカル LAN に HTTP プロキシを作成し、すべてのトラフィックを WireGuard にルーティングする
    • ユーザー名とパスワードを指定すると認証を有効化する
    • CertFileKeyFile を指定すると HTTPS を有効化する
  • SNI
    • ローカル LAN に透過 TLS プロキシを作成し、SNI をルーティング先として使用して WireGuard 経由でトラフィックを送る

複数ピアとルーティング

  • 複数の WireGuard ピアを使用できる
  • 複数ピアを使う場合は、wireproxy がどのピアへ転送すべきか分かるように AllowedIPs を指定する必要がある
  • 設定例では、異なる AllowedIPs を持つ複数の [Peer] と複数の TCPServerTunnel を併用する
  • UDPProxyTunnel の例も含まれる
    • BindAddress でローカルのバインドアドレスを指定する
    • Target で対象アドレスを指定する
    • InactivityTimeout0 ならタイムアウトしない
  • [Resolve] は DNS 解決戦略を設定する
    • ipv4: A レコードを優先する
    • ipv6: AAAA レコードを優先する
    • auto: デフォルト値で、WireGuard インターフェイスが IPv4 アドレスだけを持つ場合は ipv4 と同じ、それ以外は ipv6 と同じ
  • Endpoint がない [Peer] 設定により、ピアが wireproxy に接続することを許可できる

Health endpoint

  • --info/-i は、たとえば localhost:9080 のようなアドレスとポートを受け取り、health status metric を提供する HTTP サーバーを公開する
  • 現在 2 つの endpoint が実装されている
    • /metrics: WireGuard デーモン情報を公開し、wg show と同じ情報を提供する
    • /readyz: CheckAlive に指定された IP から最後に pong を受信した時刻を JSON で返す
  • CheckAlive が設定されている場合、指定アドレスへ CheckAliveInterval 秒ごとに WireGuard 経由で ping を送信する
    • デフォルトの CheckAliveInterval は 5 秒
    • 最後の CheckAliveInterval 秒に遅延猶予 2 秒を加えた時間内に pong を受け取れない場合は 503 を返す
    • 条件を満たす場合は 200 を返す
  • CheckAlive が設定されていない場合、/readyz は空の JSON オブジェクトと 200 を返す
  • ICMP ping パケットがルーティングされるピアは、各ピアの AllowedIPs 設定によって変わる

1件のコメント

 
GN⁺ 2024-04-03
Hacker News のコメント
  • 小さなツールだが素晴らしい。Firefox の multi-account containers で特定のタブだけを選び、WireGuard はサポートしているがアプリケーション層プロキシや SSH はないホームルーターへプロキシするのに使っている

    • multi-account containers が コンテナごとのプロキシ設定 をサポートしていることを初めて知った
      これを設定するには https://addons.mozilla.org/en-GB/firefox/addon/container-pro... のような別の拡張機能が必要だと思っていたが、そうではなく、今ではそんな勘違いもダウンボートの理由になるようだ
    • こうした構成をどう設定するのか説明した良い資料があれば知りたい
  • WireGuard でやろうとしていた作業には https://github.com/dariost/soks のほうが合っていた。ほぼ同じことをするが、既存の WireGuard インターフェース を再利用する
    使い方はこの記事に詳しく書いた: https://www.nicoco.fr/blog/2023/09/10/wireguard/

    • これはかなり違う。wireproxy はユーザー空間で TCP と WireGuard の実装 を含んでいるように見える一方、soks は TCP しか扱えない IP ルーターに近い
      ルーティングテーブルを制御手段として使う代わりに、SOCKS5 プロキシを使うかどうかを決める方式のようだ
    • なぜそちらのほうが合っていたのか気になる
      以前は Raspberry Pi の Docker コンテナで似たようなことをしていたが、どの OS でも動かせて、ホストのルーティングテーブルをうっかり壊さない保証があるので、ユーザー空間の解決策のほうがずっと良い選択に見える
  • onetun もある: https://github.com/aramperes/onetun

  • 完全な ユーザー空間サーバー実装 もあるのだろうか。tun/tap デバイスなしでやるには、ユーザー空間の IP スタックのようなものが必要そうだが、確信はない

  • 別の IP が必要なときに使っていた SSH トンネル を置き換えるのに良さそう
    関連ツールとして pproxy もあり、多くの機能の一つとして異なるトンネルプロトコル同士を「変換」でき、ルーティング機能もある。SSH SOCKS5 を HTTP プロキシに変えるのに使った: https://github.com/moreati/pproxy

  • 「こういうのは Go ならかなり簡単に作れそうだな」と思ったら、やはり Go で書かれて いた

  • 複数の マルチプロトコルプロキシクライアント がこの機能をサポートしている。代表的なオープンソースの例として sing-boxclash-meta およびその他の clash ベースのクライアント、xray がある
    クローズドソースのクライアントでは Surge Mac/iOS がある

    • その通り。こうしたマルチプロトコルプロキシは、おそらく 中国のファイアウォール回避 のために作られたのだろうが、興味深い小さなエコシステムだ
      あまり知られていないトラフィックルーティングの可能性が多く、Android 実装もある。以前、テザリングをサポートしない SIM と root 化していない Android でテザリングを有効にしようとして使ったことがある
      ただ、インターネットのあちこちから持ってきたコードが多く含まれていて、開発者コミュニティもいろいろな理由でかなり独特なので、どれほど信頼できるのかはいつも気になっている
    • クローズドソース側では Cloudflare WARP もプロキシモードで動作できる。WARP 設定を通常の WireGuard 設定に変換すれば、無料アカウントでもこうして使える
    • 中国で安定して動作するのは clash + v2ray がほぼ唯一のように見える。大半の大手 VPN 事業者は中国で使えると言うが、実際には使えない
      動作の仕組みを深く掘り下げたわけではないが、どのドメインを VPN 経由でプロキシするかをルールグループで決めるという考え方は気に入っている
  • 性能が気になる。記憶では「バニラ」 SOCKS は設定がとても簡単で、つまり SSH を適切なオプションで実行し、アプリケーションにそれを使うよう伝えるだけでよかったが、かなり遅かった
    このツールは通常の SOCKS/SSH サーバーがない場合向けのようだが、そちらに対しても利点があるのか気になる

    • 「バニラ」 SOCKS とはどういう意味なのか気になる。どの別の SOCKS 実装との対比なのかわからない
      私の場合、SSH 上の SOCKS はいつも性能がかなり良く、OpenSSH の TUN モードのように TCP の上に TCP を重ねる方式とは違っていた
    • 比較してみると良さそう。今は WireGuard に接続したあと SSH で SOCKS プロキシ を作っていて、驚くほどよく動いている
      それでもこの解決策にはとても興味がある
  • Thunderbird のすべてのメール接続を Tailscale exit node 経由でプロキシしつつ、全トラフィックを exit node に送るわけではないツールがあればいいなと、ちょうど考えていたところだった

    • tailscale CLI を SOCKS プロキシとして使える: https://tailscale.com/kb/1113/aws-lambda
      これをコンテナイメージに入れて tailscale が待ち受ける SOCKS ポートを公開すれば、そのままプロキシになる
    • exit node が動いているマシンに 3proxysquid proxy をインストールしてもよい。tailnet 内のすべてのマシンからそれが見える
  • Mullvad VPN 専用にこういうものが必要なら https://github.com/imiric/mullvad-proxy を使ってみて良かった
    自分のプロジェクトではなく、更新のためにフォークしただけ。良い点は Mullvad CLI ツールを内蔵していてサーバー切り替えがとても簡単なことと、すべてがホストマシンから隔離されていること。また、「ただの」 nginx といくつかのスクリプトなので SOCKS5 サポートも問題なさそうだ