web-dev-qa-db-ja.com

HAProxyの新しい「キャプチャ」機能を使用して、リモートアドレスをTCPフロントエンドに保存し、HTTPバックエンドの `X-Forwarded-For`ヘッダーとして使用できますか?

HAProxy 1.6と 巧妙なハック を使用して、ブラウザーがSNIに対応しているかどうかを検出するHAProxy tcpモードフロントエンドを取得し、それに基づいて、強力に暗号化されたSSL終了バックエンドまたは弱いもの。これにより、SSLラボでのA +グレーディングが保証され、IE6を除くすべてのブラウザーでSSLを使用できます。

これが私の設定です。いくつかのテンプレート変数が含まれていますが、それは一目瞭然のはずですが、私の質問に関連する領域にはありません。

frontend https_incoming
 bind 0.0.0.0:443
 mode tcp
 option tcplog
 tcp-request inspect-delay 5s
 tcp-request content accept if { req.ssl_hello_type 1 }
 use_backend https_strong if { req.ssl_sni -m end .transloadit.com }
 default_backend https_weak

backend https_strong
 mode tcp
 option tcplog
 server https_strong 127.0.0.1:1665

frontend https_strong
 bind 127.0.0.1:1665 ssl crt ${DM_ROOT_DIR}/envs/ssl/haproxy-dh2048.pem no-sslv3 no-tls-tickets ciphers ${strongCiphers}
 mode http
 option httplog
 option httpclose
 option forwardfor if-none except 127.0.0.1
 http-response add-header Strict-Transport-Security max-age=31536000
 reqadd X-Forwarded-Proto:\ https
 reqadd FRONT_END_HTTPS:\ on
 use_backend http_incoming

backend https_weak
 mode tcp
 option tcplog
 server https_weak 127.0.0.1:1667

frontend https_weak
 bind 127.0.0.1:1667 ssl crt ${DM_ROOT_DIR}/envs/ssl/haproxy.pem no-sslv3 ciphers ${weakCiphers}
 mode http
 option httplog
 option httpclose
 option forwardfor if-none except 127.0.0.1
 http-response add-header Strict-Transport-Security max-age=31536000
 reqadd X-Forwarded-Proto:\ https
 reqadd FRONT_END_HTTPS:\ on
 use_backend http_incoming

問題:https_incomingフロントエンドはクライアントIPを認識していますが、mode tcpにあるため、この情報をmode httpX-Forwarded-Forヘッダーに保存できません。 option forwardforはTCPモードでは無効です。

From serverfaultに関する別の質問 使用できることがすでにわかっています:

  • LVS
  • PROXYプロトコル

だから私が理解しているように、X-Forwarded-Forヘッダーはもう必要ありません。LVSの場合:パケットはスプーフィングされてソースがクライアントIPになり、PROXYの場合:パケットはカプセル化されて運ばれますクライアントIP。

これらはどちらも機能するようです。しかし、LVSは副作用をもたらす可能性のある心臓外科のようですが、PROXYには、プロキシ/アプリケーションの上流/下流に完全な互換性がない可能性があるという欠点があります。

私はもっ​​と軽量なものを本当に望んでいました、そしてそれが私が言及したように私がHAProxy 1.6の新しい "Capture"機能 を見つけたときです:

キャプチャスロットを宣言してデータを格納し、セッション中いつでも使用できます。

さらに、次の例を示します。

defaults 
 mode http

frontend f_myapp
 bind :9001
 declare capture request len 32 # id=0 to store Host header
 declare capture request len 64 # id=1 to store User-Agent header
 http-request capture req.hdr(Host) id 0
 http-request capture req.hdr(User-Agent) id 1
 default_backend b_myapp

backend b_myapp
 http-response set-header Your-Host %[capture.req.hdr(0)]
 http-response set-header Your-User-Agent %[capture.req.hdr(1)]
 server s1 10.0.0.3:4444 check

それは私には見え、情報はフロントエンドに保存され、後でバックエンドで使用されるので、おそらくクライアントIPをTCPモードで取得し、保存して、後でそれを使用できます。行、たぶんそう:

http-response set-header X-Forwarded-For %[capture.req.hdr(0)]

私は capture docs を見てきましたが、httpモードヘッダーでキャプチャの方が向いているようですが、- メーリングリストカンバセーション の使用も正常に示しています。 tcp-request capture

私はいくつかのことを試しましたが、その中で:

tcp-request capture req.hdr(RemoteAddr) id 0
# or
tcp-request content capture req.hdr(RemoteHost) id 0

しかし、あなたが見ることができるように、私は構文がどうあるべきか、そしてどのキーの下でこの情報が利用可能であるのか手がかりを持っていません、そして私はそれを (私は)関連するドキュメント で見つけることができません。

質問:TCP=モードでクライアントIPをキャプチャし、後でこの情報をHTTPモードのX-Forwarded-Forヘッダーに書き込むことができますか?可能であれば、どうしますか?この構文ですか?

6
kvz

私の質問に答えるために、トラフィックはここでHAProxyを「去る」ので、これは可能ではないようです:

       TCP                             HTTP
frontend->backend (->leaving->) frontend->backend

そのため、コンテキストが失われ、キャプチャを保持できません。代わりに、「PiBa-NL」がIRC= Freenodeの#haproxyで昨日提案したように:

[5:29pm] PiBa-NL: kvz, use proxy-protocol between back and front
[5:54pm] kvz: PiBa-NL: Thanks, does this mean my app also needs to understand 
         the proxy protocol, or will it be 'stripped' once it reaches the 
         backend. I don't think my node.js server could handle it without  
         significant changes to its stack
[6:07pm] kvz: Or let me rephrase: could I enable the proxy protocol on the first 
         frontend, then 'unwrap' it in the second frontend, taking the client ip 
         and putting it into the http header - so that my app would not have to 
         be proxy protocol compatible, and it would just be means to carry the 
         client ip from first frontend to the second?
[6:49pm] PiBa-NL: kvz, the last part you can still use the x-forwarded-for header
[6:50pm] PiBa-NL: but between haproxy backend and frontend you would use the 
         proxyprotocol to make the second frontent 'know' the original client ip
[6:50pm] PiBa-NL: server https_strong 127.0.0.1:1665 send-proxy
[6:50pm] PiBa-NL: bind 127.0.0.1:1665 ssl crt .... accept-proxy
[6:52pm] PiBa-NL: the second frontend can then still use the  
         'option forwardfor', and it should insert the wanted header
[6:53pm] PiBa-NL: so basically 'yes' 

つまり、PROXYプロトコルは、2つのフロントエンドを接着してCient IPをカプセル化するためにのみ使用されますが、2番目のフロントエンドはラップを解除し、X-Forwarded-Forを介してoption forwardforヘッダーに保存するため、バックエンドが送信できます。アプリサーバーへのプロキシプロトコルを使用しないリクエスト。つまり、上流/下流の互換性の問題を心配する必要はありません。

3
kvz

HAProxyはすでにX-Forwarded-Forヘッダーを追加しているはずです。これらのいずれかが非標準である場合は、プロトコルまたはポート、あるいはその両方を追加することができます。

私は通常、このような動作を、リクエストヘッダーをエコーするページでテストします。これにより、使用可能なヘッダーとその内容を簡単に確認できます。

X-Forward-Forがアドレスのリストを含むことは珍しいことではありません。これは、リクエストが複数のプロキシを通過したか、誰かがヘッダーをスプーフィングしていることを示しています。右端のアドレスは、要求を処理した最後のプロキシ(ha-proxy)によって追加されたアドレスになります。

一部のWebサーバーは、接続ではなくヘッダーからIPアドレスを記録するように構成できます。これは、アクセスログや、着信接続のIPアドレスに基づいてヘッダーを生成する場合に役立ちます。

2つの異なるスタックを使用せずに、IE 6を除くすべてのリストされたブラウザーをサポートしながら、A +レーティングを達成することは可能です。

  • Java 6の場合、少なくともDHE-RSA-AES128-SHAとAES128-SHAを無効にします。これは、おそらく転送秘密のないすべての暗号です。
  • WinXP/IE8およびJava6の場合は、DES-CBC3-SHAまたはEDH-DSS-DES-CBC3-SHAを有効にします。これらは転送秘密をサポートしないため、最も推奨されない暗号である必要があります。

WinXP/IE8とJava 6は安全なプロトコルを使用したForward Secrecyをサポートしていないので、テストはその失敗に対して不利になりません。他のすべてのブラウザーはサーバーの順序付けを強制する場合にForward Secrecyを使用します。(成功しない場合、Win Phoneは失敗します。)

A +の評価では、少なくとも180日間の期間でStrict-Transport-Securityを設定する必要があります。

0
BillThor