Проверять ACL Varnish через X-Forwarded-For, когда за одним или несколькими (!) Обратными прокси-серверами

У меня Varnish работает за обратным прокси (работает на локальном хосте для разгрузки SSL). Прокси устанавливает заголовок X-Forwarded-For или добавляет себя к нему, если заголовок уже существует.

Когда я провожу проверку ACL, я, конечно, хочу проверять IP-адрес исходного клиента, а не IP-адрес моего прокси, поэтому я не могу использовать поле client.ip . С помощью vmod std я могу сделать следующее:

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) после I ' Я отключил прокси. Это должен быть 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 () и при этом point 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?

3
задан 23 February 2017 в 19:48
1 ответ

Ваше регулярное выражение в порядке. Единственное, что я вижу, это то, что вы запрашиваете замену самой группы.

Это должно сработать, если вы добавите ^ (. *) в начало вашего регулярного выражения и замените второй аргумент на \ 2

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

}

При этом я не думаю, что менять заголовок XFF - хорошая идея. Более стандартным должно быть добавление заголовка, а не изменение удаления информации, переданной промежуточными прокси.

1
ответ дан 3 December 2019 в 07:23

Теги

Похожие вопросы