Использование Nginx real_ip, когда вы не знаете IP-адреса промежуточного прокси.

Модуль Nginx real_ip позволяет вам установить переменную $ remote_addr на основе значения, отправленные в определенных полях заголовка. Он имеет специальное представление о заголовке X-Forwarded-For и может использовать самое правое ненадежное значение в заголовке в качестве подключаемого IP-адреса.

Я хотел бы использовать модуль real_ip, чтобы установить $ remote_addr на подключаемый IP-адрес. У меня проблема в том, что я знаю, сколько переходов назад от конца X-Forwarded-For , чтобы посмотреть, но не IP-адреса прокси между ними. Насколько я понимаю, это означает, что я не могу использовать set_real_ip_from для указания IP-адреса прокси.

Я бы хотел настроить nginx так, чтобы он выбирал предпоследний адрес в списке как $ remote_addr . Кажется, что модуль real_ip работает только в том случае, если у вас есть инфраструктура, в которой вы знаете IP-адреса своих прокси.

Есть ли способ сделать это с помощью модуля real_ip? Я разработал решение на основе регулярных выражений, но я бы предпочел использовать модуль real_ip, если это возможно.

Я не думаю, что это обман nginx real_ip_header и X-Forwarded-For кажется неправильным или подобные вопросы.Переформулируем проблему:

  • Я знаю , сколько переходов от конца будет до IP-адреса подключения.
  • Я не знаю доверенных IP-адресов для промежуточных прокси между подключающимся IP и моим сервером, поэтому я не могу использовать set_real_ip_from .

Подробнее о специфике:

Я запускаю nginx внутри Google Cloud, за балансировщиком нагрузки HTTP Google Cloud. Google Cloud использует заголовок X-Forwarded-For , чтобы указать точку входа в сеть Google Cloud. Я знаю, что предпоследнее значение в списке X-Forwarded-For - это то, что мне нужно, но я не знаю, каким будет IP-адрес последнего значения (прокси). Даже если бы я мог перечислить все адресное пространство Google Cloud для прокси (не указано, что GCLB работает только внутри адресного пространства GCP), это открыло бы его для любых других пользователей, которые могут получить сервер внутри этого адресного пространства.

2
задан 9 January 2019 в 00:34
2 ответа

В итоге я использовал версию на основе регулярных выражений. Из моей конфигурации nginx :

http {
    # Regexes are:
    # (?<connecting_ip>\d+\.\d+\.\d+\.\d+), (?<proxy_ip>\d+\.\d+\.\d+\.\d+)$ # IPv4 only
    # (?<connecting_ip_x>[0-9a-f:.]+),\s*(?<proxy_ip>[0-9a-f:.]+)$ # IPv6 and IPv4, and more robust
    #
    # The last IP address is the one from the GCP front end load balancer
    # The second to last IP address in the list is the connecting IP address (i.e. user IP address)
    # We capture both of them. X-Forwarded-For is separated by commas, hopefully whitespace as well
    # but we don't want to trust that too much.
    #
    # Note that ~ at the start of the string in Nginx marks it as a regex. It's not part
    # of the regex.
    #
    # Test cases for regex101
    # 1.1.1.1, 2.2.2.2
    # 1.1.1.1, 2.2.2.2, 3.3.3.3
    # 1.1.1.1
    # ::ffff:130.211.1.102, 2.2.2.2
    # 2001:0db8:85a3:0000:0000:8a2e:0370:7334, 2.2.2.2
    # 2001:41d0:8:e8ad::1, 2600:1901:0:2ad2::
    # 1.1.1.1,2.2.2.2,3.3.3.3
    #
    # It would be better to use the real_ip module, if that is possible
    # https://serverfault.com/q/947835/334330 might get answered for this.


    # Get the IP address of the connecting IP. If we get a direct connection from
    # GCP's health checkers, there won't be an X-Forwarded-For header. We shouldn't
    # be getting any direct connections from other sources without XFF header.
    map $http_x_forwarded_for $connecting_ip {
        # Capture the proxy IP and connecting_ip_x, then assign the connecting_ip_x
        "~(?<connecting_ip_x>[0-9a-f:.]+),\s*(?<proxy_ip>[0-9a-f:.]+)$" $connecting_ip_x;
        default               $remote_addr;
    }
  #...
}

, а затем я использую $connecting_ip в своем определении сервера:

server {
  #...
  location / {
    proxy_set_header X-Real-IP $connecting_ip;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Host "";
    proxy_redirect off;
    proxy_next_upstream error;
  }
}
1
ответ дан 25 October 2021 в 09:59

Это невозможно сделать с помощью самого ngx_http_realip_module, учитывая, что, как указано в real_ip_recursive описание, только последний адрес в поле заголовка (т.е. ваш GFE, если установлено выкл) или последний ненадежный адрес (т.е.адрес клиента, если установлено значение on), будет сопоставлен с заменой $remote_addr, так что даже если вы получили адрес предыдущего прокси из $http_x_forwarded_for с помощью строковых манипуляций и установите для него $set_real_ip_from, модуль не изменит $remote_addr.

Поэтому, похоже, вам придется прибегнуть к ручному переопределению $remote_addr самостоятельно с помощью регулярного выражения, как вы упомянули, или использовать другой модуль.

С учетом сказанного, возможно, стоит отметить, что адрес GFE балансировщика нагрузки всегда должен соответствовать CIDR 35.191.0.0/16 или 130.211.0.0/22 CIDR.

0
ответ дан 19 November 2020 в 12:00

Теги

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