バイパスルーターのポートフォワーディング不具合の解決
はじめに
前回の記事 の方法で設定を完了した後、メインルーターでポートフォワーディングを設定し、かつポートを割り当てられた機器のゲートウェイがバイパスルーターになっている場合、そのポートフォワーディングは無効になります。これは Clash の分流による問題ではなく、バイパスルーターをゲートウェイに設定すると、メインルーターのポートフォワーディングがすべて無効になるためです。
原理(長文注意)
ゲートウェイの役割は NAT(ネットワークアドレス変換)であり、内部ネットワークのトラフィックを外部ネットワークへ転送するために使われます。内部ネットワークのトラフィックが外部へ出る際は必ずゲートウェイを経由しなければなりません。したがって、内部ネットワークの各機器には外部と通信するためのゲートウェイアドレスが必須です。
ゲートウェイの仕組みは簡単に言えば自動的なポートフォワーディングのようなものです。ゲートウェイは各アクティブな接続(5 つ組みで一意に識別)に対して、内部ポートと外部ポートのペアを管理しています。例えば、あなたの機器が Google サーバーと接続を確立した場合、ゲートウェイが管理するポートペアが (32384, 14122) だとすると、あなたから Google へ送る全てのトラフィックはゲートウェイの 32384 番ポートに送られ、ゲートウェイは 14122 番ポートを通じて Google サーバーへパケットを転送します。逆に Google サーバーからの返信もこの経路を通ります。もちろん、NAT は一層だけとは限らず、もしあなたの回線がグローバル IP を直接取得していなければ、家庭用ゲートウェイの上位にも NAT が存在し、最終的に Google と通信するゲートウェイはグローバル IP を持つ機器になります(インターネット通信が可能なのはグローバル IP を持つ機器のみです)。
バイパスルーターを設定すると、バイパスルーター自体がゲートウェイとして NAT を一回行います。つまり、あなたの機器と外部通信の間には二重の NAT が存在することになります:
あなたの機器 <——> バイパスルーター(NAT) <——> メインルーター(NAT) <——> 外部機器
ここでメインルーターにポートフォワーディングを設定していても、内部機器のゲートウェイがバイパスルーターの場合、外部からのアクセスは以下のように流れます:
外部機器 ----> メインルーターゲートウェイ ----> あなたの機器
一方、内部機器から外部への通信はこうなります:
あなたの機器 ----> バイパスルーター ----> メインルーター ----> 外部機器
実際には、外部機器が接続を開始した際、あなたの機器はメインルーターゲートウェイと接続を確立しますが、返信トラフィックはバイパスルーターゲートウェイへ送られます。バイパスルーターは接続に対応するポートペアを見つけられず、パケットを破棄してしまうため、ポートフォワーディングが機能しなくなります。
解決策(ここだけ見てください)
解決策はシンプルで、内部ネットワークに二重の NAT があるなら、ポートフォワーディングも二重に設定すれば良いだけです。
- メインルーターにポートフォワーディングを設定し、宛先をバイパスルーターに向ける
- バイパスルーターにポートフォワーディングを設定し、宛先を目的の機器に向ける
こうすることで、入ってくるトラフィックも戻るトラフィックも以下の経路を通り、接続が正常に確立されます:
あなたの機器 <——> バイパスルーター(NAT) <——> メインルーター(NAT) <——> 外部機器
メインルーターとバイパスルーターのポートフォワーディング設定方法はシステムによって異なります。iKuai や OpenWRT は GUI で設定可能なのでここでは割愛します。前回の記事でバイパスルーターに Debian を使いましたが、以下の方法は iptables を使うすべてのシステムに適用可能です。以下のコマンドを実行して iptables を設定してください。ここでは目的の機器を「内部」、ゲートウェイ機器を「外部」と呼びます。
iptables -t nat -I PREROUTING -p tcp -d <外部 IP> --dport <外部ポート> -j DNAT --to-destination <内部 IP>:<内部ポート>
iptables -t nat -I POSTROUTING -p tcp --dport <内部ポート> -d <外部 IP> -j SNAT --to-source <内部 IP>
これで iptables の設定が完了します。
なお、前回の記事の clean.sh 内の iptables -t nat -F
コマンドはすべてのユーザー定義ルールを消去するため、転送が無効になります。したがって、このコマンド実行後は上記の設定コマンドを再度実行する必要があります。