nginxプロキシの背後にあるピラミッドサーバーでクライアントの実際のIPを取得する方法
-
28-10-2019 - |
質問
使用するピラミッドアプリケーションがあります request.environ['REMOTE_ADDR']
いくつかの場所で。
アプリケーションは、ポート6543のPython Pasteによって提供され、ポート80でリスニングされるNginxサーバーは、Pasteサーバーへのリクエストを転送しています。
Nginx構成は、Pyramid Cookbookに触発されています。
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アプリケーションでは、変数要求.Environ ['Remote_Addr']は常に127.0.0.1に等しくなりました。この問題を解決するためのいくつかの戦略が見られますが、それを行うための推奨方法があるかどうかはわかりません。
これが私が検討していることです:
必要に応じて、request.environ ['remote_addr']を置き換えるnewRequestサブスクライバーを追加します。
if 'HTTP_X_REAL_IP' in event.request.environ: event.request.environ['REMOTE_ADDR'] = event.request.environ['HTTP_X_REAL_IP']
WSGIミドルウェアを使用して、ピラミッド層を押す前にrequest.environを変更します。
何か他のもの
ピラミッドアプリケーションの展開にどの戦略を使用していますか? 2つのnginxプロキシがある場合はどうなりますか? (最初のLANを提供し、2番目の1つはインターネットに直接接続されたマシンを提供します)。
解決
使用する場合 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
他のヒント
Nginxの背後にあるGeventサーバーを使用し、使用します request.client_addr
クライアントのIPアドレスを取得します。
WSGI Piplineを持っていない場合、または使用したくない場合 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)
そして、あなたのプロキシがヘッダーを設定することを確認してください
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です