
UDPストリームを (fake) TCPストリームに変換し、Layer 3 & Layer 4 (NAPT) ファイアウォール/NAT を通過できるようにします。
軽量で高速なUDPからTCPへの難読化ツール。
Rustは2023年以降、MIPSベースのプラットフォームに対してTier 3のサポートのみを提供しています。そのため、PhantunのMIPSビルドはnightly Rustツールチェーンを使用してビルドされ、ベストエフォートベースでのみ提供されます。
PhantunはUDPパケットをTCP接続に難読化するプロジェクトです。最小限の処理とカプセル化オーバーヘッドで最大のパフォーマンスを達成することを目指しています。
UDPがブロックまたは制限されているがTCPは許可されている環境でよく使用されます。
Phantunは単純にUDPパケットのストリームを難読化されたTCPストリームパケットに変換します。Phantunが使用するTCPスタックは、ほとんどのL3/L4ステートフル/ステートレスファイアウォール/NAT機器を通過するように設計されています。L7プロキシを通過することはできません。ただし、このアプローチの利点は、再送やフロー制御といった一般的なUDP over TCPのパフォーマンス低下要因が発生しないことです。ファイアウォール/NATの観点からはTCP接続のように見えますが、順序外れの配信などのUDPの特性は完全に保持されます。
Phantunという名前はPhantom TUNに由来し、ステートフルファイアウォール/NATをTCPパケットとして通過させるために必要最小限の処理を行うUDPトラフィック難読化ツールです。
Phantunは100%安全なRustで記述されています。マルチコアシステムで適切にスケールするよう広範囲に最適化されており、高速な接続であれば利用可能なすべてのCPUリソースを飽和させることも問題ありません。ベンチマーク結果についてはパフォーマンスのセクションを参照してください。

以下の例では、Phantunサーバーがポート4567(サーバーの--localオプション)でPhantunクライアントからの接続を待ち受け、UDPパケットを127.0.0.1:1234(サーバーの--remoteオプション)のUDPサーバーに転送すると仮定します。
また、Phantunクライアントが127.0.0.1:1234(クライアントの--localオプション)でUDPパケットを待ち受け、10.0.0.1:4567(クライアントの--remoteオプション)のPhantunサーバーに接続すると仮定します。
Phantunはクライアントとサーバーの両方にTUNインターフェースを作成します。クライアントでは、Phantunはデフォルトで自身にIPアドレス192.168.200.2とfcc8::2を割り当てます。サーバーでは、デフォルトで192.168.201.2とfcc9::2を割り当てます。そのため、カーネルでIPv4/IPv6転送を有効にし、物理NICアドレスとPhantunのTunインターフェースアドレス間のNATに対して適切なiptables/nftablesルールを設定する必要があります。
Phantunが作成するTunインターフェースの名前と割り当てられるアドレスをカスタマイズできます。変更方法については、実行可能ファイルを-hオプションで実行して確認してください。
このネットワークトポロジを理解する別の方法(トポロジの図については上の図を参照):
Phantunクライアントは、ルーターの背後にあるプライベートIPアドレス(192.168.200.2/fcc8::2)を持つマシンのようなものです。インターネットに到達するには、トラフィックがNICを離れる前にプライベートIPアドレスをSNATする必要があります。
Phantunサーバーは、ルーターの背後にあるプライベートIPアドレス(192.168.201.2/fcc9::2)を持つサーバーのようなものです。インターネットからアクセスするには、ルーターでリッスンポートをDNATし、宛先IPアドレスをサーバーが接続を待ち受けている場所に変更する必要があります。
これらの場合、Phantunを実行するマシン/iptablesは「ルーター」として機能し、Phantunが自身のプライベートIPアドレスを使用して外部と通信できるようにします。
Phantun v0.4.1以降、TCP側とUDP側の両方でIPv6が完全にサポートされています。IPv6アドレスを指定するには、[::1]:1234の形式をコマンドラインオプションで使用します。AAAAレコードの解決もサポートされています。IPv6の動作を制御する詳細なオプションについては、プログラムを-hで実行してください。
/etc/sysctl.confを編集し、net.ipv4.ip_forward=1を追加してsudo sysctl -p /etc/sysctl.confを実行します。
net.ipv6.conf.all.forwarding=1も設定する必要があります。
クライアントは、Phantunのアドレスを物理ネットワークで使用できるアドレスに変換するために、物理インターフェースでSNATを有効にするだけで済みます。これはマスカレードで簡単に行えます。
注意:eth0を実際の物理インターフェース名に変更してください
table inet nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
iifname tun0 oif eth0 masquerade
}
}
注意:上記のルールはテーブルファミリタイプとしてinetを使用しているため、IPv4とIPv6の両方の使用に対応しています。
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
サーバーは、TCPリッスンポートをPhantunのTUNインターフェースアドレスにDNATする必要があります。
注意:eth0を実際の物理インターフェース名に、4567をPhantunサーバーが使用する実際のTCPポート番号に変更してください
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iif eth0 tcp dport 4567 dnat ip to 192.168.201.2
iif eth0 tcp dport 4567 dnat ip6 to fcc9::2
}
}
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination 192.168.201.2
ip6tables -t nat -A PREROUTING -p tcp -i eth0 --dport 4567 -j DNAT --to-destination fcc9::2
ネットワーク向けアプリケーションをrootユーザーとして実行することは推奨されません。Phantunはcap_net_adminケーパビリティを使用して完全に非rootユーザーとして実行できます。
sudo setcap cap_net_admin=+pe phantun_server
sudo setcap cap_net_admin=+pe phantun_client
注意: 完全な詳細オプションを表示するには、Phantun実行可能ファイルを-hオプションで実行してください。
注意:4567はPhantunがリッスンするTCPポートで、上記で指定したDNATルールに対応している必要があります。127.0.0.1:1234は新しい接続に対して接続するUDPサーバーです。
RUST_LOG=info /usr/local/bin/phantun_server --local 4567 --remote 127.0.0.1:1234
または--remoteにホスト名を使用:
RUST_LOG=info /usr/local/bin/phantun_server --local 4567 --remote example.com:1234
注意:サーバーはデフォルトでTunインターフェースにIPv4とIPv6の両方のプライベートアドレスを割り当てます。IPv6を使用したくない場合は、上記のIPv6 DNATルールを作成しなければそれでよく、Tunインターフェース上のIPv6アドレスの存在はサーバーに副作用をもたらしません。
注意:127.0.0.1:1234はPhantunがリッスンするUDPアドレスとポートです。10.0.0.1:4567は接続先のPhantunサーバーです。
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote 10.0.0.1:4567
または--remoteにホスト名を使用:
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote example.com:4567
RUST_LOG=info /usr/local/bin/phantun_client --local 127.0.0.1:1234 --remote [fdxx::1234]:4567
AAAAレコードを持つドメイン名もサポートされています。
Phantunはトンネリングオーバーヘッドを最小限に抑えることを目指しています。通常のUDPパケットと比較したオーバーヘッドは以下の通りです(以下ではIPv4を例として使用):
標準UDPパケット: 20バイト IPヘッダー + 8バイト UDPヘッダー = 28バイト
難読化パケット: 20バイト IPヘッダー + 20バイト TCPヘッダー = 40バイト
Phantunはステートフルパケットインスペクションを通過するために、IPヘッダーとTCPヘッダー以外の追加ヘッダーを追加しないことに注意してください!
Phantunの追加オーバーヘッド:12バイト。言い換えれば、Phantunを使用する場合、UDPパケットの利用可能なペイロードは12バイト減少します。これはこの種の難読化で可能な最小のオーバーヘッドです。

Phantunを使用してWireGuard®のUDPパケットをトンネリングする方のために、WireGuardインターフェースに使用する正しいMTUを決定するためのガイドラインを以下に示します。
WireGuard MTU = リンクMTU - IPv4ヘッダー (20バイト) - TCPヘッダー (20バイト) - WireGuardオーバーヘッド (32バイト)
または
WireGuard MTU = リンクMTU - IPv6ヘッダー (40バイト) - TCPヘッダー (20バイト) - WireGuardオーバーヘッド (32バイト)
例えば、MTUが1500バイトのネットワークリンクの場合、WireGuardインターフェースのMTUは次のように設定する必要があります:
IPv4: 1500 (リンクMTU) - 20 - 20 - 32 = 1428バイト
IPv6: 1500 (リンクMTU) - 40 - 20 - 32 = 1408バイト
結果として得られるPhantun TCPデータパケットは1500バイトになり、インターフェースMTUの1500を超えません。
パケットサイズがリンクMTUを超えるとPhantunは正しく機能しません。なぜなら、PhantunはIPフラグメンテーションと再構成を実行しないからです。同様の理由で、Phantunは中間デバイスがパケットに対してフラグメンテーションを実行するのを防ぐために、IPヘッダーに常にDF(Don't Fragment)ビットを設定します。
また、WireGuardトンネルの両端で同じインターフェースMTUを使用することを強く推奨します。そうしないと予期しないパケットロスが発生する可能性があり、これらの問題は一般的にトラブルシューティングが非常に困難です。
TCPスタックはかなり安定していますが、一般的には両端でPhantunのサーバー/クライアントの同じマイナーバージョンを実行して、最大の互換性を確保することを期待しています。
自身のプロジェクト内でfake-tcpライブラリを使用したいユーザーは、以下のライブラリのドキュメントを参照してください:https://docs.rs/fake-tcp
パフォーマンスは、4 vCPU、5 Gb/s NICを備えた2台のAWS t4g.xlargeインスタンスでLAN経由でテストされました。nftablesを使用してiperf3のUDPストリームを2つのテストインスタンス間のPhantun/udp2rawトンネル経由でリダイレクトし、フラグメンテーションを避けるためにMTUを調整しました。
Phantun v0.3.2 と udp2raw_arm_asm_aes 20200818.0 が使用されました。これらは2022年4月時点での両プロジェクトの最新リリースでした。
テストコマンド:iperf3 -c <IP> -p <PORT> -R -u -l 1400 -b 1000m -t 30 -P 5
このパフォーマンス結果を達成するためにPhantunで使用されているいくつかの手法に関する解説:Writing Highly Efficient UDP Server in Rust
udp2raw は @wangyu- によるもう一つの人気プロジェクトで、Phantunと非常に似た機能を提供します。実際、私はPhantunの着想をudp2rawから得ました。Phantunを開発した最大の理由は、udp2raw(特にRaspberry Piなどのマルチコアシステム)を実行した際のパフォーマンス不足です。ただし、udp2rawと同等の機能を備えることを目標にはしておらず、最も一般的なユースケースのみをサポートします。特に、UDP over ICMPモードやUDP over UDPモードはサポートされておらず、アンチリプレイや暗号化のサポートもありません。これにより、TCPペイロード内に追加ヘッダーがないため、全体的なパフォーマンスが大幅に向上し、MTUオーバーヘッドが少なくなります。
以下に、選択の参考となる簡単な比較の概要を示します:
Copyright 2021-2025 Datong Sun ([email protected])
ライセンスは、Apache License, Version 2.0 <LICENSE-APACHE または https://www.apache.org/licenses/LICENSE-2.0>、またはMITライセンス <LICENSE-MIT または https://opensource.org/licenses/MIT> のいずれかを選択できます。プロジェクト内のファイルは、該当する条件に従わない限り、コピー、変更、または配布することはできません。
| モード | 送信速度 | 受信速度 | 全体的なCPU使用率 |
|---|
| 直接接続 (1ストリーム) | 3.00 Gbits/sec | 2.37 Gbits/sec | 25% (1コア100%) |
| Phantun (1ストリーム) | 1.30 Gbits/sec | 1.20 Gbits/sec | 60% (1コア100%、3コア50%) |
udp2raw (cipher-mode=none auth-mode=none disable-anti-replay) (1ストリーム) | 1.30 Gbits/sec | 715 Mbits/sec | 40% (1コア100%、1コア50%、2コアアイドリング) |
| 直接接続 (5ストリーム) | 5.00 Gbits/sec | 3.64 Gbits/sec | 25% (1コア100%) |
| Phantun (5ストリーム) | 5.00 Gbits/sec | 2.38 Gbits/sec | 95% (全コア使用) |
udp2raw (cipher-mode=none auth-mode=none disable-anti-replay) (5ストリーム) | 5.00 Gbits/sec | 770 Mbits/sec | 50% (2コア100%) |
| Phantun | udp2raw |
|---|
| UDP over FakeTCP難読化 | ✅ | ✅ |
| UDP over ICMP難読化 | ❌ | ✅ |
| UDP over UDP難読化 | ❌ | ✅ |
| マルチスレッド | ✅ | ❌ |
| スループット | より良い | 良い |
| Layer 3モード | TUNインターフェース | Rawソケット + BPF |
| トンネリングMTUオーバーヘッド | 12バイト | 44バイト |
| UDP接続ごとの個別TCP接続 | クライアント/サーバー | サーバーのみ |
| アンチリプレイ、暗号化 | ❌ | ✅ |
| IPv6 | ✅ | ✅ |