TUN モードは Android の VpnService で仮想ネットワークインターフェースを作り、端末の通信を丸ごと v2rayNG 内蔵の Xray コアに取り込みます。本記事は四つの段階で進みます。まず既定のローカルプロキシとの違いを比べ、次にデータの流れを分解し、続いて有効化と権限許可の順序を示し、最後に三つの再現可能なチェックで引き受け範囲を確認し、バックグラウンドでの維持と DNS 解決でよくある落とし穴を挙げます。
TUN モードと既定のローカルプロキシの違い
v2rayNG の既定の接続方法は、端末内に二つのインバウンドを開くだけです。SOCKS は 127.0.0.1:10808、HTTP は 127.0.0.1:10809。プロキシ設定を読むアプリ(ブラウザや一部のダウンロードツール)だけがこの二つのポートにリクエストを送り、それ以外のアプリはそのまま直接接続します。Android にも全アプリ共通のグローバルプロキシスイッチはなく、Wi-Fi の詳細設定にあるプロキシはその設定に従うアプリにしか効きません。
TUN モードは別の経路をたどります。v2rayNG は Android の VpnService を通じて仮想ネットワークインターフェースを要求し、システムが端末から出る IP パケットをこのインターフェースに書き込みます。アプリ側にプロキシアドレスを入力する必要はありません。インターフェース内のパケットは内蔵の転送コンポーネント tun2socks に渡され、TCP 接続と UDP セッションに戻されたあと、SOCKS5 として Xray コアに渡って振り分けられます。
| 比較項目 | 既定のローカルプロキシ | TUN モード |
|---|---|---|
| 引き受け対象 | 自らプロキシを設定するアプリ | 端末のすべての IP 通信(アプリ単位で絞り込み可能) |
| アプリ側の設定 | 127.0.0.1:10808 の入力が必要 | 不要 |
| DNS の扱い | アプリが独自に解決 | 通信とともにコアへ入り、ドメイン解決ポリシーに従って処理 |
| 権限 | なし | システムの VPN 許可が必要 |
| 消費電力 | 低い | やや高い(ユーザー空間の転送が一回増える) |
| 典型的な用途 | ブラウザとプロキシ対応ツール | プロキシ設定を持たないアプリ、全体を引き受けたい場合 |
データの流れ:アプリからアウトバウンドまで
TUN モードでは、一回のリクエストが五つの段階を通過し、どの段階も個別に切り分けられます。
最初の二段階はシステムと転送コンポーネントが担います。VpnService がインターフェースを作ると、既定ルート 0.0.0.0/0 がこのインターフェースを指し、アプリが発した接続は丸ごと TUN に書き込まれます。tun2socks はインターフェースから生の IP パケットを読み出し、TCP 接続と UDP セッションに戻してから、SOCKS5(UDP ASSOCIATE を含む)として 127.0.0.1:10808 に渡します。
残りの三段階は Xray コアの中で行われます。リクエストは socks インバウンドに入るとまず routing ルールで照合され、outbound プロキシに送るか freedom で直接接続するかが決まります。ドメインをいつ IP に解決するかは「設定」の「ドメイン解決ポリシー」で制御します。IPIfNonMatch を選ぶとまずドメインでルールを照合し、一致しない場合にだけ解決を始めるので、無駄な DNS クエリを一回省けます。AsIs なら完全にドメインで照合し、IPOnDemand は IP ルールに当たったときだけ解決します。
{
"inbounds": [
{ "tag": "socks", "listen": "127.0.0.1", "port": 10808, "protocol": "socks", "settings": { "udp": true } },
{ "tag": "http", "listen": "127.0.0.1", "port": 10809, "protocol": "http" }
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{ "type": "field", "outboundTag": "direct", "ip": ["geoip:private"] },
{ "type": "field", "outboundTag": "direct", "domain": ["geosite:cn"] }
]
}
}
ここで抜き出したのはインバウンドとルーティングの二段階で、outbounds と具体的なノードは読み込んだサブスクリプションが生成します。TUN モードが新しいプロトコルを追加しているわけではないことが分かります。インターフェースから出た通信は最終的に 10808 の SOCKS インバウンドを通り、ハンドシェイクと暗号化方式はノード側が決めます。VMess、VLESS、Trojan、SS のいずれも同じです。
TUN モードを有効にする手順
以下の順序は v2rayNG 1.9.x の画面構成に対応しています。バージョンによってメニューの文言が多少異なりますが、手順自体は変わりません。
- まずサブスクリプションを読み込み、ノードが使えることを確認します。ノード行の右側メニューで「実際の接続遅延をテスト」を実行し、遅延が -1 と表示されるノードはハンドシェイクに失敗しています。まず通るノードに切り替えて、ノード側の問題を TUN の問題と誤認しないようにします。
- サイドバー →「設定」を開き、接続方式が VPN(TUN)モードであることを確認します。v2rayNG は VpnService で仮想ネットワークインターフェースを作ります。バージョンによってはここが「VPN モード」スイッチになっている場合もあれば、独立したスイッチがなく接続をタップすると直接 VpnService を使う場合もありますが、以降の手順には影響しません。
- サイドバー →「ルーティング設定」→「定義済みルール」で「LAN と中国本土をバイパス」を選びます。LAN 内の機器と中国本土のサイトは direct を通り、プロキシが必要な通信だけがノードに入ります。
- 「設定」→「ドメイン解決ポリシー」で IPIfNonMatch を選びます。この項目はドメインがルール照合のどの段階で解決されるかを決めるもので、後で DNS を確認するときに使います。
- アプリ単位で制御したい場合は「設定」→「アプリ別プロキシ」を開き、スイッチを入れて「選択したアプリのみプロキシ」または「選択したアプリをバイパス」を選び、アプリ一覧で対象のアプリにチェックを入れます。
- メイン画面に戻って接続をタップします。初回はシステムの「接続リクエスト」ダイアログが出るので「許可」をタップします。その後、ステータスバーに VPN の鍵アイコン、通知バーに v2rayNG の実行通知が表示され、引き受けが始まります。
アプリ別プロキシと TUN は同じ層の仕組み
アプリ別プロキシは二本目の経路ではありません。TUN と同じ VpnService を使っており、許可リストと除外リストはシステムが VPN 層でフィルタリングします。除外されたアプリの通信は仮想ネットワークインターフェースに入らず、当然 Xray にも入りません。したがって「TUN を有効にしてからアプリ別プロキシを有効にする」ことで二重プロキシにはならず、引き受け範囲が狭くなるだけです。
権限とバックグラウンドでの維持
許可はシステム層の話ですが、維持できるかどうかはメーカーのバックグラウンドポリシー次第です。中国メーカーの ROM は画面オフから数分で VPN サービスを回収することが多く、ステータスバーの鍵アイコンが消え、通信量の統計が増えなくなり、アプリを開き直すと接続状態が未接続に戻っています。
- バッテリー:システムの「設定」→「アプリ」→「v2rayNG」→「バッテリー」で「制限なし」を選ぶか、バッテリー最適化をオフにします。
- 自動起動:「自動起動管理」で v2rayNG の自動起動を許可し、最近使ったタスク一覧でアプリをロックして、一括クリーンアップで消されないようにします。
- バックグラウンドでのポップアップ表示:v2rayNG が「接続リクエスト」を出すときにシステムに遮られないようにします。この権限を許可しておくと、認可に失敗する場面を減らせます。
- 常時接続 VPN:Android 7.0 以降では「設定」→「ネットワークとインターネット」→「VPN」に「常時接続 VPN」があり、v2rayNG を常駐させて切断時にシステム側から起動し直せます。
- VPN なしの接続をブロック:同じ画面にあるこの項目を有効にすると、VPN が切れたときにすべての通信が遮断されます。切り分けの段階ではオフにしておいてください。オンにしていると、通信できない原因の見当がつかなくなります。
まとめ:まずバックグラウンド設定、次にルールを確認
同じ設定でも端末によって挙動が違う場合、その多くはコアではなくバックグラウンド維持ポリシーが原因です。バッテリー最適化の解除、自動起動、バックグラウンドロックの三点を設定して一日様子を見てから、DNS とルーティングルールの確認に戻ってください。順序を逆にすると多くの時間を無駄にします。
引き受け範囲の確認
接続状態は VpnService のリンクが成功したことしか示しておらず、通信が本当にコアに入っているかは分かりません。三つの再現可能なチェックで引き受け範囲を確認します。
- 出口アドレスの比較:まずブラウザで出口 IP を表示するページを開き、直接接続時の結果を記録します。TUN に接続してから同じページを開くと、IP はノードのある地域のアドレスに変わり、プロバイダの欄も変わります。
- アプリ別プロキシによる反証:「アプリ別プロキシ」で特定のアプリをバイパスに設定し、そのアプリを開き直すとローカル IP が表示されるはずです。チェックを外して再度開き直すとノードの IP が表示されるはずです。二回の結果が異なれば、TUN のアプリ単位フィルタが効いている証拠です。
- 通信量の統計:「設定」→「通信量統計を有効にする」を開き、接続後に統計ページで上り下りが閲覧に応じて増えるかを見ます。数値が動かなければ通信がコアに入っていません。
よくある質問と切り分け
v2rayNG を切断したのにステータスバーの鍵アイコンが残る?
鍵アイコンはシステムの VPN フレームワークが描画します。まず v2rayNG のメイン画面で一度切断すると、アイコンは VpnService とともに消えます。それでも残る場合は、システムの「設定」→「ネットワークとインターネット」→「VPN」で他に接続中の設定がないか確認し、一つずつ切断してください。
TUN を有効にしても特定のアプリがローカル IP のまま?
まず「設定」→「アプリ別プロキシ」を確認します。モードが「選択したアプリをバイパス」なら、一覧でチェックが入っているアプリがプロキシを通りません。モードが「選択したアプリのみプロキシ」なら、チェックのないアプリがプロキシを通りません。両方のモードを確認したうえで、そのアプリを開き直して再テストしてください。
ブラウザの拡張機能に 127.0.0.1:10808 を入れたまま。変更すべき?
消しておくことをおすすめします。残していると、リクエストはまず拡張機能によってローカルのインバウンドに送られ、TUN のアプリ単位フィルタを迂回します。アプリ別プロキシでブラウザを除外しているのに拡張機能の層ではプロキシが効いている、という状態になり、切り分けの結論が矛盾します。
接続時にシステムの「接続リクエスト」が出て、キャンセルしたらまた出る?
出ます。次に接続をタップすると改めて許可を求められ、一度キャンセルしたからといって永久に拒否されるわけではありません。ダイアログがまったく出ない場合は、システムの VPN 一覧から v2rayNG の項目を削除してからもう一度接続すると、認可の流れが最初からやり直されます。
TUN モードはローカルプロキシより電池を食う?
少し多くなります。増える分のオーバーヘッドは tun2socks のユーザー空間転送とメモリコピー一回分で、長時間バックグラウンドに置くほど目立ちます。ブラウザでしか使わないなら TUN をオフにするか、アプリ別プロキシで必要なアプリだけに範囲を絞ってください。
切り分けの順序は固定しておくのがおすすめです。まずバックグラウンドで生きているか、次に対象の通信をルーティングルールが直接接続にしていないか、最後に DNS をどこで解決しているかを見ます。三段階すべて確認してもつながらない場合に、ノード自体に戻って実際の接続遅延を一度テストします。