TCP通信(非HTTP)のアクセス元IPの伝播には、Proxy Protocolが必要です。
コンテナイメージ
Proxy ProtocolのCODECツールとして、
go-mmproxyが手軽です。
バイナリと以下のスタートアップスクリプトを同梱したコンテナイメージを作成しておきます。
#!/bin/bash
ip rule add from 127.0.0.1/8 iif lo table 123
ip route add local 0.0.0.0/0 dev lo table 123
go-mmproxy -l 0.0.0.0:25577 -4 127.0.0.1:<target_port> -allowed-subnets </path/to/subnet.txt>
<target_port>
は実アプリのポートで、たとえばsshdのウェルノウンポートは22番です。
<subnet.txt>
はアクセス許可するIP範囲を記載したテキストで、制限なしの設定例は以下のような一行です。
0.0.0.0/0
サイドカーのマニフェスト
sshdのサイドカー構成のコンテナスペックの抜粋は以下のようになります。
spec:
containers:
- name: mmproxy
# image: required
ports:
- containerPort: 25577
name: mmproxy
securityContext:
capabilities:
add: ["NET_ADMIN"]
- name: sshd
# image: required
ports:
- containerPort: 22
name: sshd
NET_ADMIN
特権はスタートアップスクリプトのip
コマンドに必要です。
TCPサービスからの戻りのパケットをキャプチャして書き換えます。
実サービスのコンテナポート(上の例の22)は公開しなくても動作するでしょう。
外部との通信は25577番に集約します。
ヘルスチェックに注意
Proxy Protocolを使用する場合、フロントにプロキシがある想定ですが、ヘルスチェックには注意が必要です。
go-mmproxyは互換性のないパケットを受信すると通信をドロップします。Google Cloudの構成では、ヘルスチェックは通過するものの、実通信の90%程度が失敗する挙動になりました。
ヘルスチェック対象をgo-mmproxyではなく実サービスに代えることで通信が安定しました。上の例ではヘルスチェック用に22番を定義しています。 TCPプロキシはログ出力も乏しく、非常に分かりにくい挙動となるため注意が必要です。
⁋ 2021/12/10↻ 2024/12/18
中馬崇尋
Chuma Takahiro
Chuma Takahiro