web-dev-qa-db-ja.com

Flask request.remote_addrがwebfactionで間違っており、実際のユーザーIPが表示されない

FlaskアプリをWebfactionにデプロイしたところ、そのことに気づきましたrequest.remote_addr 常に 127.0.0.1。もちろん、これはあまり役に立ちません。

Flask Webfactionで)でユーザーの実際のIPアドレスを取得するにはどうすればよいですか?

ありがとう!

21
Ignas Butėnas

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の投稿 を参照してください。

36
Ignas Butėnas

イグナスの答えを書き直す:

headers_list = request.headers.getlist("X-Forwarded-For")
user_ip = headers_list[0] if headers_list else request.remote_addr

スプーフィングの考慮事項について Eliの投稿 を必ずお読みください。

4
Shankar Cabus

Werkzeugミドルウェア

Flaskのドキュメントはかなり具体的です 推奨されるリバースプロキシサーバーのセットアップについて

HTTP [リバース]プロキシの背後にあるこれらの[WSGI]サーバーのいずれかを使用してアプリケーションをデプロイする場合、アプリケーションが[適切に]機能するためには、いくつかのヘッダーを書き換える必要があります。 WSGI環境で問題となる2つの値は、通常REMOTE_ADDRHTTP_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

Webfactionのドキュメント Accessing REMOTE_ADDR について:

... IPアドレスは、HTTP_X_FORWARDED_FORヘッダーのコンマ区切りリストの最初のIPアドレスとして使用できます。

クライアントのリクエストにすでにX-Forwarded-Forヘッダーが含まれている場合、何をするかは言われませんが、常識に従って、ヘッダーを置き換えると思います。したがって、Webfactionの場合、num_proxies0に設定する必要があります。

Nginx

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のままにします。

4
saaj

問題は、おそらくFlaskの前に何らかのプロキシがあることです。この場合、「実際の」IPアドレスはrequest.headers['X-Forwarded-For']

3
Rob Wouters

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]
2
itmard