同様にこれCloudflareのブログ記事によると、私は透過ソケット(IP_TRANSPARENT
ソケットオプション)。これを実行することで、すべてのポートに効果的にバインドするリバース TCP プロキシを実装します。
ソケットIP_TRANSPARENT
オプションはネイティブサポートされていないNginxがリスニングのために使用しているため、ソケットを作成しようとしていますSystemd ソケットユニットそして、それをNginxプロセスに渡します。NGINX
環境変数。
ソケットユニットは次のとおりです (重要でない行は削除されています)。
[Socket]
ListenStream=127.0.0.1:1234
Transparent=true
[Install]
WantedBy=sockets.target
私の Nginx サービス ユニットは次のとおりです (重要でない行は削除されています)。
[Service]
# Configure Nginx to use the socket inherited from Systemd
Environment=NGINX=3;
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
そして、私のものnginx.conf
は以下のとおりです (重要でない行は削除されており、upstream
プロキシするアップストリーム ホストのホスト名です)。
stream {
server {
proxy_pass upstream:443
listen 127.0.0.1:1234;
}
}
NginxはGCPコンピューティングインスタンス上で実行されており、内部パススルーロードバランサIP アドレスが 10.11.12.13 なので、トラフィックを透過ソケットにリダイレクトするための次の iptables ルールを追加しました。
iptables -t mangle -I PREROUTING -d 10.11.12.13/32 -p tcp -j TPROXY --on-port=1234 --on-ip=127.0.0.1
説明どおりここ、GCP がロードバランサのローカルルートをインストールするので、自分でインストールする必要はありません。つまり、次のコマンドは以下を返しますRTNETLINK answers: File exists
。
ip route add local 10.11.12.13/32 dev lo src 127.0.0.1
ただし、次の curl コマンドはハングします。
curl https://10.11.12.13
curl の観点からは TCP 接続は正しく確立されていますが、Nginx ワーカー プロセスをトレースすると、accept4
システム コールでハングしているように見えます。
tcpdump
Nginx が実行されているインスタンスから実行すると、次のように表示されます。
15.59.51.564902 IP [REDACTED].50028 > 10.11.12.13.443: Flags [S], seq 3519046460, win 65535, options [mss 1320,nop,wscale 6,nop,nop,TS val 3905128064 ecr 0,sackOK,eol], length 0
15.59.51.564973 IP 10.11.12.13.443 > [REDACTED].50028: Flags [S.], seq 2512605282, ack 3519046461, win 28400, options [mss 1420,nop,nop,sackOK,nop,wscale 7], length 0
15.59.51.601898 IP [REDACTED].50028 > 10.11.12.13.443: Flags [.], ack 1, win 4096, length 0
15.59.51.601898 IP [REDACTED].50028 > 10.11.12.13.443: Flags [P.], seq 1:370, ack 1, win 4096, length 369
15.59.51.601898 IP 10.11.12.13.443 > [REDACTED].50028: Flags [.], ack 370, win 231, length 0
私の理解では、これはクライアントがデータを送信し、サーバーがそれを確認しているが、その後クライアントはそれ以上データを送信していないことを意味します。これはおそらく、サーバーからの応答を期待しているが、受信していないためだと思われます。このため、Nginx はクライアントから送信されたデータを単に無視しているのではないかと思います。
問題を理解するのに十分な背景情報を提供できたと思います。ここからどうしたらいいのか、あるいは私がしようとしていることに根本的な問題があるのかどうか、よくわかりません。どなたか助けていただければ幸いです。
答え1
解決策を見つけたこここれは、Nginx サービス ユニットに次のオプションを設定することでした。
[Service]
NonBlocking=true
おそらく Nginx は、リスニング ソケットの作成時にこのオプションが設定されていると想定しているため、Systemd がこのオプションを設定せずにソケットを渡した場合、データを読み取ることができません。