Real Client IP with @sentry/nextjs tunnel?

Hey all,

What’s the right way to pass the real client-side IP when using @sentry/nextjs@6.13.3's tunnel option?

I’m using the example Next.js tunnel implementation; however, the user IP reflected in Sentry UI is that of the backend server, not of the client.

I have also tried forwarding req.headers['x-forwarded-for'] || req.socket.remoteAddr as X-Forwarded-For to the /envelope endpoint. The resulting X-Forwarded-For header I’m sending contains the real client IP in the first position. However, that doesn’t seem to change its behaviour at all, Sentry UI still shows the IP of the backend server as the user IP.

Looks like I found a workaround. Adding forwarded_for: "<real-ip>" into the envelope header results in Sentry UI displaying the correct client IP.

I would appreciate it if any Sentry folks could offer a less hacky way to do this or confirm that this is indeed the intended way to do it.

Here’s roughly what my code looks like for that:

    const envelope = req.body;
    const [rawHeader, ...restPieces] = envelope.split('\n');

    const header = JSON.parse(rawHeader);

    // omitted: check DSN, host, project ID

    const body = [
      // HACK: Attempt to communicate the real client IP address to Sentry.
      //       The `forwarded_for` field was deduced from a test in Sentry's
      //       Relay (server) handling of the Envelope format,
      //       cf.
          typeof req.headers['x-forwarded-for'] === 'string'
            ? req.headers['x-forwarded-for']
            : req.socket.remoteAddress,

    const url = `https://${sentryHost}/api/${projectId}/envelope/`;
    const response = await fetch(url, {
      method: 'POST',

The existence of this field was deduced from a Relay test here: relay/ at 2e924639d7bcfa24db69ba2ed78a82e2c07478e1 · getsentry/relay · GitHub