HTTP・SOCKS・透過プロキシ・UDP
SOCKS・透過プロキシ・UDP-over-TCPなどを中心に、ネットワークの変更に使えるプロキシ関連の各種技術を雑にまとめた。
近年はGo製のものが多い。また検閲に対抗するためか、中国系(中国語でissueが投稿されているなど)のものが多い。gost, go-proxy, hysteria, txthinking/socks5, things-go/socks5などはいずれもその2つに当てはまる。たまにロシア系もある。
大規模・多機能系
以下のものは機能が多くて分類できないのでソフトウェアごとに紹介する。
gost
GO Simple Tunnelの略らしい。安定版のv2系(https://github.com/ginuerzh/gost, https://v2.gost.run/)と開発中のv3系(https://github.com/go-gost, https://gost.run/)で大きく仕様が異なる。v3は開発中と言いつつv2系のページを見るとかなりv3推しに見える。
starはバージョン2が16k、バージョン3が5kほど。
イメージとしては、TCPによるシンプルなトンネルプロトコル(これがgost)(暗号化無し)と他の大量のプロトコルの間の相互変換を実装しているような感じと思われる。
非常に多機能で、このページで紹介している多くソフトウェアの基本機能をカバーしていると言ってもいいくらい。UDP-over-TCP系は基本これ1つで十分。機能の豊富さに比して明らかにドキュメントが不足しており、エラーメッセージも親切ではない(起動時ではなく実際にパケットが来てからエラーが出るような感じ)。
connectorとしてはsocks5も用意されているが、相手がgostでない限りUDP Associateは動かない模様。具体的には
gost -L "auto://:8480?udp=true&relay=udp" -F socks5://192.168.1.13:3129
などとしても、 05f3 0001 0000 0000 0000みたいなよくわからんリクエストが送られてしまう。このf3のところは下記の独自拡張っぽい。
go-proxy
https://github.com/snail007/goproxy
これも見た感じgostと同じくらいか一部では上回るくらい多機能に見えるが、この雰囲気にしては珍しく有料版があり、無料版だと一部機能が制限されているようなので、あまり使ったことはない。
GFW回避
中国政府の検閲システムであるグレート・ファイアウォール(GFW)に対抗することを主な目的とするもの。
shadowsocks
SOCKSに暗号化を施した独自プロトコルで、いくつかの実装がある。https://github.com/shadowsocks/shadowsocks-rustなどが主流とみられる。
VPN以外のGFW回避ソフトウェアだとおそらくもっともメジャー。
サーバーとクライアントに分かれていて、クライアント側では透過プロキシにも対応している。
Hysteria
通信路がHTTP/3に偽装した形で暗号化される。shadowsocksの次世代に位置付けられるソフトウェアのように見える。
SOCKS5サーバー部分にはtxthinking/socks5を使っている。
SNI Proxy
HTTP・HTTPSのリバースプロキシで、host(HTTPの場合)あるいはsni(HTTPSの場合)に基づいてアクセスを振り分けるものをSNI Proxyと呼ぶことがあるらしい。NginxやHAProxyのような汎用のプロキシサーバーでも使える機能だが、これを専門とするソフトウェアもある。
- こんな使い方もある(自分の記事)→ 【Android】NextDNSをアプリごとに有効無効切り替え+Tailscale経由の自宅鯖を使ってControl D風のトラフィック転送 - turgenev’s blog
dlundquist/sniproxy
https://github.com/dlundquist/sniproxy starは2.6kほど。2024年に更新あり。非推奨である理由(HTTP/2とかQUICでうまくいかないとか)も書いてある。
tcpproxy
https://github.com/inetaf/tcpproxy starは1.3kほど。ライブラリ用途がメインか。
ameshkov/sniproxy
https://github.com/ameshkov/sniproxy starは70ほど。上流のSOCKS5, HTTPプロキシへの転送機能がある。
puxxustc/sniproxy
https://github.com/puxxustc/sniproxy starもほぼなく更新も9年前。
SOCKSプロキシサーバー
Dante
企業(Inferno Nettverk A/S)によるオープンソースなSOCKS5実装で、有償サポートまであるらしい。見るからに古臭いHPで、メンテされているかどうか不安になるが、つい最近2024年末にもアップデートがあり、次期バージョンの計画についても記載されている。
Cで書かれていて、おそらく最も正確なSOCKS5実装だろう。コメントも親切で、リファレンス実装のような雰囲気がある。他の透過プロキシクライアントなどをテストする際はDanteでテストして動けば安心感がある。
OpenSSH
現実的に最もよく使われているSOCKSサーバーは間違いなくOpenSSHだろう。しかし、UDP-over-TCPの問題があるため、UDPはサポートされていない。
ssh -Dでforward方向のプロキシを建てるのが有名だが、OpenSSH 7.6からは-Rでreverse方向にも建てられるようになった。クライアント側が7.6以上であればよい。
- 参考: OpenSSH 7.6 (
ssh(1): add support for reverse dynamic forwarding
)
socks-with-udp-over-ssh
https://github.com/ge9/socks-with-udp-over-ssh
TCP接続(あるいは任意のバイトストリーム)の上にUDP付きのSOCKS5を通すために自分が実装したツール。サーバー側とクライアント側に分かれている。しかし実装した後にgostで同じことができることに気付いた。
経緯・使い方などはroot権限のないssh上にUDPを通す方法について(ポートフォワード、SOCKS5プロキシなど) - turgenev’s blogに書いてある。
3proxy
3proxy tiny free proxy server for Windows, Linux, Unix: SOCKS, HTTP, FTP proxy
https://github.com/3proxy/3proxy
ロシア系。エラーメッセージなどがかなり不親切だが、ちゃんと動くソフト。
fast-socks5
https://github.com/dizda/fast-socks5 Rust製では最も有名か。starは500ほど。使ったことなし
txthinking/socks5
https://github.com/txthinking/socks5
starは700前後。hysteriaやtrojan-goなどいくつかの大きなプロジェクトで使われており、go製のSOCKS5関連ライブラリでは一番メジャーか。
クライアントもある。
自分のfork(https://github.com/ge9/socks5)ではFull Cone NATを追加した
armon/go-socks5
https://github.com/armon/go-socks5
starは2kだが、最終更新2016年でUDP Associateも無し。Wireproxyで以前使われていたが使われなくなった(https://github.com/whyvl/wireproxy/issues/15)。
ここからフォークされたものが複数ある。
things-go/go-socks5
https://github.com/things-go/go-socks5
armon/go-socks5からのフォーク(GitHub上ではfork扱いではない)。starは400個ほど。UDP Associateはサポートしているがバグあり(自分のPRが採用されるかどうかで揉めてるhttps://github.com/things-go/go-socks5/pull/63)。
Wireproxyで使われている。
自分のフォーク https://github.com/ge9/go-socks5 ではFull Cone NATを追加した
haxii/socks5
https://github.com/haxii/socks5
armon/go-socks5からのfork。UDP Associate対応。starは50個前後。最終更新2019年。
wzshiming/socks5
https://github.com/wzshiming/socks5
クライアントもある。
starは90個ほど。最終更新2024年。
とりあえずredsocksと組み合わせでUDP透過プロキシ動作確認済。
Wireproxyで使用が検討された(https://github.com/whyvl/wireproxy/issues/15)が結局使用されず。
haochen233/socks5
https://github.com/haochen233/socks5
クライアントもある。
UDP Associateはサポートしているが、starは49とさらに少なく、最終更新も2021年。
同じくWireproxyで使用が検討された(https://github.com/whyvl/wireproxy/issues/15)が結局使用されず。
tun系
tun2proxy
https://github.com/tun2proxy/tun2proxy
透過SOCKSプロキシクライアント
バックにSOCKS(SOCKS5)プロキシを用いてTCP・UDPのレイヤで透過プロキシを行うもの。基本的には管理者権限(最低でもCAP_NET_ADMIN)が必要。
redsocks
semigodking/redsocks (fork元のdarkk/redsocksはメンテされておらず、TCPのTPROXYに非対応)
*nix対応。BSD系で動かすことができたという話はFreeBSD/OpenBSD/NetBSDで透過プロキシのredsocksを動かしてみる - turgenev’s blogに書いた。
ProxiFyre
https://github.com/wiresock/proxifyre Windows用の透過SOCKSクライアント。管理者権限必要。TCP/UDP両方対応。インストールも簡単で、よくできている。
hev-socks5-tproxy
https://github.com/heiher/hev-socks5-tproxy Linux向け。redsocksより若干知名度は下がるものの、きちんとメンテされている。
Proxifier
https://www.proxifier.com/ 見た感じ機能は十分そうだが、有料なので試していない。
ライブラリ関数ハック系
ライブラリ関数レベルでの置き換えになるため厳密性・安定性に欠ける(異常終了する場合もある)ものの、root権限がない場合に有効な手法。
Linux(LD_PRELOAD)
libc依存でないプログラム(Go製のものなど)には効かない。
socksify
後述のDanteの一部。UDP/TCP両対応。唯一のUDP対応のものである。
route {
from: 0.0.0.0/0 to: 0.0.0.0/0 via: 192.168.1.1 port = 1080
}
こんな感じの/etc/socks.conf
を作るか、SOCKS5_SERVER=192.168.1.1:1080 socksify curl http://ipv4.icanhazip.com
とかでもよい。
Macでも動くはずだが、筆者が唯一試したMac環境ではcurlに対してさえうまく動作しなかった(socksifyを使わないのと全く同様に動作するだけだった)(DYLD_FORCE_FLAT_NAMESPACE=1
は指定している)。
proxychains-ng(proxychains)
ngはnew generationの略で、proxychainsの後継である。ただしコマンド名はproxychains4である。
多段プロキシを構成するためのソフトウェア。
UDP非対応(https://github.com/rofl0r/proxychains-ng/issues/336)。ただしDNSに対応したproxy_dnsというオプションがあり、これを有効にするとDNS以外のUDP通信が正常に機能しなくなる副作用がある(https://github.com/rofl0r/proxychains-ng/issues/103)。
torsocks(tsocks)
多分、メンテされていないtsocksがTorに取り込まれてtorsocksになったような感じ。tsocksは非常に古く、多分2010年以降には更新されていないが、知名度は高く、今でも多分そこそこ使われてそう。
torsocksはアクティブなはず。ただし、Torでない普通のSOCKS5を指定しても動かないようである(やり方が悪いかも)。
tsocksはUDPには対応していない。torsocksもそうだが、まずそもそもTor自体がUDPに対応していない。
Windows(DLL Hijacking)
どのDLLを置き換えたらいいか自明ではなさそうなので、LD_PRELOADと違って対象とするソフトウェアごとに実装が必要そう。そもそも不可能なソフトウェアもLD_PRELOADの場合より多そう。よく見かけるのはDiscordを対象にしたもので、ロシア系のものが多い。筆者は使ったことがない。
discord-drover
https://github.com/hdrover/discord-drover
discord-voice-proxy
https://github.com/runetfreedom/discord-voice-proxy
HTTPプロキシ
Squid, Privoxyなどが有名。
Squidには透過プロキシ機能があるが、redsocksなどとは動作の細かい部分が異なる。squidで透過プロキシ(intercept, tproxy)を動かす - turgenev’s blogに書いた。
SOCKS関連の話題
SOCKS5によるドメイン解決
SOCKS5(SOCKS4aも?)では、クライアントがCONNECTなどの要求をする際、接続先をIPアドレスではなくホスト名(ドメイン名)で指定することができる仕様になっている。これによりクライアント側ではなくSOCKS5サーバー側でドメイン解決が行われる。
Proxifyreやredsocksを普通に使う場合、TCP/UDPレイヤでのプロキシとなるので、この機能が使われることはない(squidで透過プロキシ(intercept, tproxy)を動かす - turgenev’s blog)。一方、Webブラウザなどでは、この機能が使われる場合がある(参照: https://github.com/FelisCatus/SwitchyOmega/issues/2304、How does SOCK 5 proxy-ing of DNS work in browsers?)。
ブラウザのSOCKS5プロキシのWebRTC対応
基本的に現在主流のブラウザ(Firefox, Chrome)のSOCKS5プロキシ機能(拡張機能で設定する場合を含む)はUDPには対応していないため、Discordの通話などWebRTC関係の機能を使うと生IPが漏洩する(またはそれを防ごうとすると単にその機能が使えない)。これは原理的に実装が不可能なわけではなく、単に需要が少ないから実装されていないだけである。
- Chromeではどれが最新か不明(最近の物は少ない)。このへんとか?Chromium
- torのバグ報告 https://gitlab.torproject.org/tpo/applications/mullvad-browser/-/issues/151
- firefoxの https://bugzilla.mozilla.org/show_bug.cgi?id=1808692
従って、ブラウザのWebRTCをプロキシさせたい場合はVPNや透過プロキシなどroot/管理者権限が必要な手法を使うことになる。ただしLinux+Firefoxの場合はsocksifyが使えるのでrootが無くても可能。
UDP AssociateリクエストのDST.ADDRとDST.PORT
クライアントがサーバー側にUDP Associateリクエストをするとき、この2フィールドには通信したい宛先ではなく(←というかそもそもそれが複数ある場合もある)、クライアント側がUDP Associateに使用する予定のポートを入れる。指定しない場合(例えばNATがある場合、これを予測するのは難しくなる)は、全ビットを0に設定する必要がある。
これによってサーバー側は、UDPパケットが送られてきたタイミングでそれが事前に通知されたものと一致するかどうか確認できるというわけである。
この部分に誤ってクライアント側が通信したい宛先ポートを入れるよう実装していたSOCKS5クライアントがいくつかある。
- semigodking/redsocks…自分のhttps://github.com/semigodking/redsocks/issues/210で修正済み。
- gost…https://github.com/ginuerzh/gost/issues/96で修正済み。
- txthinking/socks5…https://github.com/txthinking/socks5/issues/15で修正済み。
- things-go/go-socks5…これはサーバー側。https://github.com/things-go/go-socks5/issues/29の通り、クライアントが必ずアドレス・ポートを通知してくれる(ゼロ埋めしない)と仮定していたが、修正された。
VPN(tun)
tun2proxy
https://github.com/tun2proxy/tun2proxy
Rust製。starは700ほど。SOCKSとHTTPをtunにしてくれる。
hev-socks5-tunnel
https://github.com/heiher/hev-socks5-tunnel
hev-socks5-tproxyの作者による。Androidアプリのhttps://github.com/heiher/sockstunもここから。
プロキシプロトコル間の変換
socks-to-http-proxy
https://github.com/KaranGauswami/socks-to-http-proxy
名前の通り、socksをhttpにしてくれる。starは250ほど。
privoxy
基本的にはHTTPプロキシソフトウェア。socksプロキシをhttpプロキシとして使えるようにする機能はあるが、より大がかり(一般ユーザーでの実行がしづらい)
UDP・Wireguard関連
UDPでサーバー→クライアントにデータ送信
https://github.com/prof7bit/udp-reverse-tunnel
これを使うと、サーバー側だけでポートが開けられるとしても事実上クライアント側で開けられるのと同等になるのでreverseをするのが楽になる
- https://superuser.com/questions/1737943/how-to-create-a-reverse-udp-tunnel
- どっちも開放できない場合、UDPホールパンチングで何とかするしかない
wgslirpy
https://github.com/vi/wgslirpy
Slirp(ユーザーランドで動くPPPサーバーのようなもの)のような形で実装されたWireguardサーバー。rootなしでWireguardサーバーとして動作する。
wireproxy
https://github.com/whyvl/wireproxy
wgslirpyの逆のような(?)ツール。Wireguardクライアントであるが、SOCKSサーバーとして動作する。
依存ライブラリのUDP Associate対応が不完全(自分がプルリクを送っている)だが、クライアントによってはうまくUDP Associateが動く(https://github.com/whyvl/wireproxy/issues/30)。
自分でカスタマイズしてCone NATを加えたthings-go/go-socks5を使えば(
go.mod
でreplace github.com/things-go/go-socks5 => ../../go-socks5
などとする)、以下のようなコードをroutine.goのsocks5.Optionのところに追加することでCone NATにできる。socks5.WithDialUDP(func(laddr, raddr *net.UDPAddr) (net.PacketConn, error) { return vt.Tnet.DialUDP(laddr, raddr) }),
Wireguard通信の確立: 各パターンでのやり方
各状況に応じて、2端末間でUDPの暗号化された通信路を確立するための方法を書いた。
- forwardは「クライアント→サーバー」、reverseは「サーバー→クライアント」という意味。「サーバー」は、「ポートが開放できる方」という意味合い。
どっちもrootあり
普通にWireguardを使う
サーバーのみrootあり
forward
サーバーはWireguard、クライアントは普通にWireproxyでいける
reverse
udp-reverse-tunnelで頑張って逆にする(あるいはホールパンチング)。
その上で、wgslirpyを使うか、Hysteriaを使うか
クライアントのみrootあり
↑さっきと逆
forward
wgslirpyを使うか、Hysteriaを使うか
reverse
udp-reverse-tunnelで頑張ったうえで普通にWireguardとWireproxy
どっちもrootなし
この場合そもそもWireguardを使うメリットはあまりないかも。というのとrootがないならポート開放も無理そう
forward
Hysteriaでいけそう。
reverse
udp-reverse-tunnelしてHysteria?かな