Tinyproxy の Listen・Bind・BindSame:どちらのアドレスが勝つか
Listen はクライアントを受け付けるアドレスを選び、Bind は外向き接続の送信元を選びます。どちらも経路を設置しないため、経路は別に確認してください。
プロキシは応答し、リクエストは完了する。それでも宛先には LAN のアドレスが記録される。プロキシのログに異常は見当たらず、変更した行はドキュメントが変更するよう指示した行そのものだ。LAN アドレスとトンネルアドレスの両方を持つホストでは、どのアドレスがどこに現れるかを三つのディレクティブが決めるが、外向き側に関係するのは一つだけである。順序を間違えて読むと、理由もなくルーティングテーブルへ入り込むことになる。
症状:宛先には LAN のアドレスが見える
クライアントは LAN アドレスでプロキシに接続し、プロキシは宛先へ自分の接続を開く。この二つ目の接続はカーネルの規則で送信元アドレスを選び、既定では経路検索が選んだものになる。そのため、すべてのバイトがプロキシを通っていても、宛先にはホストの主アドレスが記録される。転送の面では何も壊れておらず、だからこそプロキシのログはこの件について何も語らない。
この不具合の鏡像はもっと見つけやすい。外向きの送信元をトンネルアドレスに固定すると、LAN のクライアントはリスナーにまったく届かなくなる。その版は自分から異常を告げるが、最初の版は正常に動くリクエストの陰に隠れる。どちらも、一つのディレクティブが二つの問いの両方に答えるかのように扱うことから生じる。
三つのディレクティブ、三つの異なるアドレス
Listen はプロキシのクライアントを受け付けるローカルアドレスを指定する。Bind はプロキシが外へ張る接続の送信元アドレスを与え、BindSame は直前に受け付けた接続のローカルアドレスを再利用するよう指示する。これは三つの別々の問いであり、一行の設定はそのうち一つにしか答えない。これらを混同することが、変更が効かないように見えるよくある理由である。
| What you observe | Check first |
|---|---|
| A client cannot connect at all | Listen: the local address the listener binds |
| The request works but the far side logs the LAN address | Bind: the outgoing source is not being applied |
| A configured Bind appears to have no effect | BindSame yes: the accepted local address overrides the Bind list |
| The lookup names the LAN interface | The route, not the proxy: the source cannot reach that destination |
インストールされた版に同梱される注釈付き設定を読むこと。既定値と受け付けられる構文はリリースごとに変わる。プロジェクトの設定例は各ディレクティブを互いに並べて文書化している。そのファイルとディスク上のファイルを比較し、別のディストリビューション向けに書かれたガイドとは比べないこと。
リスナーと外向きの送信元を別々に設定する
LAN アドレスが 192.168.50.10、トンネルアドレスが 10.90.0.3 のホストを考える。LAN のクライアントがプロキシに届き、そのリクエストがトンネルから出るべきなら、これは二つの独立した決定であり、両方を書き留める必要がある。下の断片はまさにそれだけを表している。
Listen 192.168.50.10
Bind 10.90.0.3
BindSame noこれは完全な設定ではないので、承認済みのポート、認証、クライアントのアクセス制御、宛先の制限は残しておく。両方のアドレスは Tinyproxy のネットワーク名前空間の中でこのホストに属している必要がある。プロセスが所有できない Bind の値は、起動時ではなく接続時に失敗するからだ。BindSame yes は別の方針を表し、受け付けた接続のローカルアドレスが外向きの送信元になる。現在のリリースではこの分岐が Bind の一覧より優先されるため、設定した送信元がエラーもなく消えるのである。
送信元が含意する経路を確認する
送信元アドレスを選んでも経路は生まれないので、その送信元とその宛先でカーネルが何をするかを尋ねる。トンネルのインターフェースを名指す検索が最小限の証拠であり、LAN のインターフェースを名指すなら、その送信元は書かれたとおりには動かない。検索は文脈依存で、その名前空間に有効なポリシー規則とテーブルを評価する。これは接続ではなく、下流の NAT がサービスに何を見せるかについても何も語らない。
ip -4 route get 203.0.113.25 from 10.90.0.3例ではドキュメント用アドレスを使い、試験を許可されたサービスに置き換える。プロキシがコンテナで動く場合はプロキシの名前空間の中で検索を実行する。ホストの規則はプロセスが見る規則ではないからだ。意図したトンネル経路がない場合は、プロキシホストに宛先固有の規則を足すのではなく、ネットワークの所有者に直してもらう。検索を通すためにホストの経路を消したり、サーバーが配る経路を無効にしたりしないこと。古いガイドがそうしていたとしても、その変更はホスト全体の承認済み VPN 挙動を動かして、プロキシの一経路を直すことになる。
宛先で送信元を確認する
送信元は、リクエストが出ていく場所ではなく、届く場所で読む。宛先のアプリケーションログ、あるいはその手前のエッジ機器が、実際に見たアドレスを記録する。プロキシが語れるのは意図だけだ。変更後に意図したリスナーを通して新しいリクエストを一度出し、キャッシュされた接続では新しい紐付けの証拠にならない。そのうえで記録されたアドレスを設定したアドレスと比べる。
ss -ltnp | grep tinyproxy
curl -x http://192.168.50.10:8888 https://example.com -o /dev/null -sScurl はトラフィックの生成器にすぎない。検証する価値があるのは遠い側が記録したアドレスであり、curl がたまたま接続した相手ではない。両者が食い違うなら、その差が送信元の選択から来るのか、途中の変換から来るのかを決める。前者と後者では直す場所が違う。アドレス変更とプロキシの再起動も一緒に計画すること。トンネルがもう持たないアドレスを結合すると、再接続のあと静かに失敗する。DNS と IPv6 の挙動も別に定義すること。上の IPv4 の断片はどちらについても何も証明しない。