Repository: getsentry/sentry-python

Issue:
Flask integration wrong User IP behind proxy
When sentry report bugs I get wrong users IP. 

I'm using UWSGI and NGINX stack. I forward X-REAL-IP from NGINX to UWSGI. Also flask.request.remote_addr shows correct user IP address but sentry-sdk version 0.7.10 shows my server IP address as user IP.

Would you please assist?


Discussion:
Hello, your problem should be solved if you set `X-Forwarded-For` to the same value as well, but this is a bug in the SDK. We should trust the value given by Flask.
May I ask how you read X-Real-IP into Flask? I assume you use a WSGI middleware for this?
```python
    sentry_sdk.init(dsn=config.SENTRY_DSN_URL, integrations=[FlaskIntegration(),
                                                             CeleryIntegration(),
                                                             sentry_logging])
    app.wsgi_app = SentryWsgiMiddleware(app.wsgi_app)
```
May I use like this ?

@NullYing this seems fine, but I don't understand how it's related to this issue.
https://github.com/getsentry/sentry-python/blob/263a0bd92bdf85c6b23c889c8cd5a28adfd81ea2/sentry_sdk/integrations/wsgi.py#L129

```python
    try:
        return environ["HTTP_X_FORWARDED_FOR"].split(",")[0].strip()
    except (KeyError, IndexError):
        return environ.get("REMOTE_ADDR")
```

I found get_client_ip in wsgi.py
but not flask

@NullYing See here: https://github.com/getsentry/sentry-python/blob/263a0bd92bdf85c6b23c889c8cd5a28adfd81ea2/sentry_sdk/integrations/flask.py#L65

So the integration already does `app.wsgi_app = ...`, but the middlewares run in the wrong order (`ProxyMiddleware` runs after `SentryMiddleware`, so Sentry sees the wrong IP)
I will fix this bug shortly, @NullYing just gave me an idea on how to solve this elegantly

Resolving patch:
diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py
--- a/sentry_sdk/integrations/wsgi.py
+++ b/sentry_sdk/integrations/wsgi.py
@@ -96,9 +96,10 @@ def _get_environ(environ):
     """
     Returns our whitelisted environment variables.
     """
-    keys = ("SERVER_NAME", "SERVER_PORT")
+    keys = ["SERVER_NAME", "SERVER_PORT"]
     if _should_send_default_pii():
-        keys += ("REMOTE_ADDR",)  # type: ignore
+        # Add all three headers here to make debugging of proxy setup easier.
+        keys += ["REMOTE_ADDR", "HTTP_X_FORWARDED_FOR", "HTTP_X_REAL_IP"]
 
     for key in keys:
         if key in environ:
@@ -129,16 +130,21 @@ def _get_headers(environ):
 def get_client_ip(environ):
     # type: (Dict[str, str]) -> Optional[Any]
     """
-    Naively yank the first IP address in an X-Forwarded-For header
-    and assume this is correct.
-
-    Note: Don't use this in security sensitive situations since this
-    value may be forged from a client.
+    Infer the user IP address from various headers. This cannot be used in
+    security sensitive situations since the value may be forged from a client,
+    but it's good enough for the event payload.
     """
     try:
         return environ["HTTP_X_FORWARDED_FOR"].split(",")[0].strip()
     except (KeyError, IndexError):
-        return environ.get("REMOTE_ADDR")
+        pass
+
+    try:
+        return environ["HTTP_X_REAL_IP"]
+    except KeyError:
+        pass
+
+    return environ.get("REMOTE_ADDR")
 
 
 def _capture_exception(hub):


Test patch: