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アドレス以外を破棄するにはどうすればよいですか?
正規表現は問題ないようです。私が見る唯一のことは、あなたがグループをそれ自体で置き換えることを要求するということです。
正規表現の先頭に^(.*)
を追加し、2番目の引数を\2
に置き換えると機能するはずです。
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2");
}
そうは言っても、XFFヘッダーを変更するのは良い考えではないと思います。中間プロキシから送信された削除情報を変更するのではなく、ヘッダーを追加するほうが標準的なはずです。