Как получить реальный IP-адрес клиента на сервере пирамиды за прокси-сервером nginx - PullRequest
5 голосов
/ 21 февраля 2012

У меня есть приложение Pyramid, которое в некоторых местах использует request.environ['REMOTE_ADDR'].

Приложение обслуживается Python Paste на порту 6543, и сервер nginx, прослушивающий порт 80, пересылает запросы на сервер Paste.

Конфигурация nginx основана на кулинарной книге Pyramid:

server {

    listen   80; ## listen for ipv4
    listen   [::]:80 default ipv6only=on; ## listen for ipv6

    server_name  localhost;

    access_log  /var/log/nginx/localhost.access.log;

    location / {

        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:6543;

    }

В приложении Pyramid переменная request.environ ['REMOTE_ADDR'] теперь всегда равна 127.0.0.1. Я вижу несколько стратегий для решения этой проблемы, но я не знаю, есть ли рекомендуемый способ сделать это.

Вот что я рассматриваю:

  • добавить подписчика NewRequest, который при необходимости заменяет request.environ ['REMOTE_ADDR']:

    if 'HTTP_X_REAL_IP' in event.request.environ: event.request.environ['REMOTE_ADDR'] = event.request.environ['HTTP_X_REAL_IP']

  • используйте промежуточное программное обеспечение wsgi для изменения request.environ перед попаданием на слой Pyramid.

  • что-то еще

Какую стратегию вы используете для развертывания приложений Pyramid? Что произойдет, если у меня будет два прокси nginx? (первый обслуживает локальную сеть, а второй - компьютер, напрямую подключенный к Интернету).

Ответы [ 4 ]

7 голосов
/ 21 февраля 2012

Если вы используете paste.deploy.config.PrefixMiddleware в своем конвейере WSGI через use = egg:PasteDeploy#prefix, он автоматически переведет X-Forwarded-For в REMOTE_ADDR. Он также отлично подходит для других свойств вашего обратного прокси-сервера, например, он переведет X-Forwarded-Proto в wsgi.url_scheme, чтобы гарантировать, что если пользователь заходит с https, то сгенерированные URL-адреса также будут https.

http://pythonpaste.org/deploy/class-paste.deploy.config.PrefixMiddleware.html

2 голосов
/ 17 января 2014

Я использую Gevent Server за nginx и request.client_addr, чтобы получить IP-адрес клиента.

1 голос
/ 03 декабря 2014

Если у вас нет трубопровода WSGI или вы не хотите использовать paste, добавьте обработчик события:

config.add_subscriber(reverseProxyProtocolCorrection,'pyramid.events.NewRequest')

Обработчик события может читать как:

def reverseProxyProtocolCorrection(event):
    event.request.scheme = 'https' if event.request.headers['X-Forwarded-Proto']=='https' else 'http'
    event.request.remote_addr=parseXForward(event.request.headers['X-Forwarded-For'],event.request.remote_addr)

и убедитесь, что ваш прокси установил заголовки

0 голосов
/ 21 февраля 2012

в nginx:

location / {
    proxy_pass http://yourapp;
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $remote_addr;
        }

в php я делаю:

        if($_SERVER["HTTP_X_FORWARDED_FOR"]){
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }else{
        $ip = $_SERVER["REMOTE_ADDR"];
      } 

возможно, в python похож, $ ip - ваш реальный ip

...