FlaskアプリをWebfactionにデプロイしたところ、そのことに気づきましたrequest.remote_addr
常に 127.0.0.1
。もちろん、これはあまり役に立ちません。
Flask Webfactionで)でユーザーの実際のIPアドレスを取得するにはどうすればよいですか?
ありがとう!
Flaskの前にプロキシがある場合、次のようなものがFlaskの実際のIPを取得します。
if request.headers.getlist("X-Forwarded-For"):
ip = request.headers.getlist("X-Forwarded-For")[0]
else:
ip = request.remote_addr
更新:Eliがコメントで述べた非常に良い点。単にこれを使用するだけでは、セキュリティ上の問題が発生する可能性があります。詳細については Eliの投稿 を参照してください。
イグナスの答えを書き直す:
headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr
スプーフィングの考慮事項について Eliの投稿 を必ずお読みください。
Flaskのドキュメントはかなり具体的です 推奨されるリバースプロキシサーバーのセットアップについて :
HTTP [リバース]プロキシの背後にあるこれらの[WSGI]サーバーのいずれかを使用してアプリケーションをデプロイする場合、アプリケーションが[適切に]機能するためには、いくつかのヘッダーを書き換える必要があります。 WSGI環境で問題となる2つの値は、通常
REMOTE_ADDR
とHTTP_Host
...です。Werkzeugは、いくつかの一般的なセットアップを解決する修正プログラムを出荷しますが、特定のセットアップ用に独自のWSGIミドルウェアを作成することもできます。
また、セキュリティの考慮事項について:
このようなミドルウェアは、悪意のあるクライアントによって偽造される可能性のある受信ヘッダーを盲目的に信頼するため、非プロキシ設定で使用することはセキュリティ上の問題であることを覚えておいてください。
request.remote_addr
がクライアントのIPアドレスを返すようにする推奨されるコード(ミドルウェアをインストールします)は次のとおりです。
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=1)
num_proxies
に注意してください。デフォルトでは1
です。アプリの前にあるプロキシサーバーの数です。
実際のコードは次のとおりです(執筆時点で最新のwerkzeug==0.14.1
)。
def get_remote_addr(self, forwarded_for):
if len(forwarded_for) >= self.num_proxies:
return forwarded_for[-self.num_proxies]
Webfactionのドキュメント Accessing REMOTE_ADDR
について:
... IPアドレスは、
HTTP_X_FORWARDED_FOR
ヘッダーのコンマ区切りリストの最初のIPアドレスとして使用できます。
クライアントのリクエストにすでにX-Forwarded-For
ヘッダーが含まれている場合、何をするかは言われませんが、常識に従って、ヘッダーを置き換えると思います。したがって、Webfactionの場合、num_proxies
は0
に設定する必要があります。
Nginxはそれについてより明確です $proxy_add_x_forwarded_for
:
「X-Forwarded-For」クライアント要求ヘッダーフィールドに
$remote_addr
変数が追加され、カンマで区切られます。 「X-Forwarded-For」フィールドがクライアント要求ヘッダーに存在しない場合、$proxy_add_x_forwarded_for
変数は$remote_addr
変数と等しくなります。
アプリの前のNginxの場合、num_proxies
はデフォルトの1
のままにします。
問題は、おそらくFlaskの前に何らかのプロキシがあることです。この場合、「実際の」IPアドレスはrequest.headers['X-Forwarded-For']
。
request.access_route
を使用して、ipのリストにアクセスできます。
if len(request.access_route) > 1:
return request.access_route[-1]
else:
return request.access_route[0]
更新:
あなたはこれを書くことができます:
return request.access_route[-1]