У меня Varnish работает за обратным прокси (работает на локальном хосте для разгрузки SSL). Прокси устанавливает заголовок 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...
}
}
Другими словами, я удаляю IP-адрес прокси (127.0.0.1) из заголовка, прежде чем запускать его через std.ip
и сравнивая его с моим ACL. Это нормально работает, кроме ...
Это не удается, если заголовок X-Forwarded-For уже установлен до того, как он достигнет моего прокси. В этом случае заголовок XFF содержит три или более IP-адресов. Обрезка последнего по-прежнему оставляет более одного и std.ip
задыхается от этого, задерживая запрос на несколько секунд и, конечно, не проверяя ACL.
Мне нужно убедиться, что заголовок XFF содержит только один IP (IPv4 или IPv6) после того, как я отключил прокси. Это должен быть 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, которые приходят извне, я бы хотел отказаться от всего, кроме ip-адреса клиента, который видел мой прокси. Мой прокси не поддерживает изменение заголовка XFF, поэтому мне нужно сделать это в Varnish.
Первая точка в потоке Varnish, когда я могу взаимодействовать с заголовками, находится в vcl_recv()
и к этому моменту Varnish уже добавил client.ip
в конец списка.
Я надеялся использовать регулярное выражение для захвата двух последних элементов (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");
}
Третий аргумент (строка, заменяющая символы, соответствующие регулярному выражению) не работает. Результирующий заголовок точно такой же, как и раньше, хотя регулярное выражение захватывает только два последних IP-адреса.
Как я могу выбросить что-либо, кроме двух последних IP-адресов из заголовка XFF?
Ваше регулярное выражение кажется прекрасным. Единственное, что я вижу, это то, что вы просите заменить группу самой.
Он должен работать, если вы добавите ^(.*)
в начале вашего регулярного выражения и замените второй аргумент на \2
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^(.*)([a-f0-9:.]+, [a-f0-9:.]+)$", "\2");
}
При этом я не думаю, что менять заголовок XFF - хорошая идея. Более стандартным должно быть добавление заголовка, а не изменение удаления информации, переданной промежуточными прокси.