web-dev-qa-db-ja.com

X-Forwardedを介してVarnishACLを確認します-1つ以上(!)のリバースプロキシの背後にある場合

Varnishをリバースプロキシの背後で実行しています(SSLオフロード用にlocalhostで実行しています)。プロキシはX-Forwarded-Forヘッダーを設定するか、ヘッダーがすでに存在する場合は自身を追加します。

もちろん、ACLチェックを行うときは、プロキシのIPではなく、元のクライアントのIPに対してチェックしたいので、_client.ip_フィールドを使用できません。 std vmodを使用すると、次のことができます。

_vcl 4.0;
import std;
sub vcl_recv {
    if (std.ip(regsub(req.http.X-Forwarded-For, ", 127.0.0.1$", ""), "0.0.0.0") ~ my_acl) {
        ...do stuff...
    }
}
_

言い換えれば、_std.ip_を実行してACLと比較する前に、ヘッダーからプロキシのIP(127.0.0.1)をトリミングします。これは正常に機能しますが...

X-Forwarded-Forヘッダーがプロキシに到達する前にすでに設定されている場合、これは失敗します。その場合、XFFヘッダーには3つ以上のIPアドレスが含まれます。最後の1つをトリミングすると、まだ1つ以上が残り、_std.ip_がこれをチョークし、要求を数秒遅らせ、もちろんACLのチェックに失敗します。

プロキシをオフにした後、XFFヘッダーにIP(IPv4またはIPv6)が1つだけ含まれていることを確認する必要があります。これはクライアントのIPである必要があります。

例えば:

_X-Forwarded-For: 10.10.1.1, 10.10.2.2, 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1
_

になるはずです

_X-Forwarded-For: 2001:a031:100a:dead:beef:1234:1234:1234, 127.0.0.1
_

外部から入ってくるXFFヘッダーは信頼できないので、プロキシが見たclient-ip以外はすべて破棄したいと思います。私のプロキシはXFFヘッダーの変更をサポートしていないため、Varnishで変更する必要があります。

ヘッダーとやり取りできるVarnishのフローの最初のポイントはvcl_recv()にあり、その時点でVarnishはリストの最後に_client.ip_をすでに追加しています。

正規表現を使用して、最後の2つのアイテム(IPv4またはIPv6)を番号付きのキャプチャグループ($ 1)にキャプチャし、ヘッダーをキャプチャグループに置き換えることを望んでいました。このような:

_vcl 4.0;
import std;
sub vcl_recv {
    set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "([a-f0-9:.]+, [a-f0-9:.]+)$", "\1");
}
_

3番目の引数(正規表現と一致する文字を置き換える文字列)は機能しません。結果のヘッダーは以前とまったく同じですが、正規表現は最後の2つのIPアドレスのみをキャプチャします。

XFFヘッダーから最後の2つのIPアドレス以外を破棄するにはどうすればよいですか?

3
Martijn Heemels

正規表現は問題ないようです。私が見る唯一のことは、あなたがグループをそれ自体で置き換えることを要求するということです。

正規表現の先頭に^(.*)を追加し、2番目の引数を\2に置き換えると機能するはずです。

set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2");

}

そうは言っても、XFFヘッダーを変更するのは良い考えではないと思います。中間プロキシから送信された削除情報を変更するのではなく、ヘッダーを追加するほうが標準的なはずです。

1