Will the header X-Real-IP always be renamed to cf-connecting-ip in fetch headers?

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * Respond to the request
 * @param {Request} request
 */
async function handleRequest(request) {
  return fetch('https://postman-echo.com/get',{
    headers: {
      'X-Real-IP': '127.0.0.2',
      'X-Real-IP2': '127.0.0.1'
    }
  })
}

The script above is a sample worker script to test this problem.
When I visited the “deployed” version of script on workers.dev, it always returns the following json output.
And it is clear that “X-Real-IP” is being renamed to “cf-connecting-ip”, which can be verified by changing the value of “X-Real-IP”.
Is there a way to disable this behavior? Or at least don’t delete “X-Real-IP” and just add “cf-connecting-ip”.

{
  "args": {},
  "headers": {
    "x-forwarded-proto": "https",
    "host": "postman-echo.com",
    "accept-encoding": "gzip",
    "cdn-loop": "cloudflare; subreqs=1",
    "cf-connecting-ip": "127.0.0.2",
    "cf-ew-via": "15",
    "cf-ray": "52272aa6f7846cfe-SJC",
    "cf-visitor": "{\"scheme\":\"https\"}",
    "cf-worker": "maple3142.workers.dev",
    "x-real-ip2": "127.0.0.1",
    "x-forwarded-port": "443"
  },
  "url": "https://postman-echo.com/get"
}

I set up a local express server to test the headers sent by CloudFlare workers:

const express = require('express')
const app = express()
app.use((req, res) => {
	res.send(req.headers)
})
app.listen(80)

And this is the result I get:

{
  "host": "HOSTNAME_TO_MY_PC",
  "connection": "Keep-Alive",
  "accept-encoding": "gzip",
  "x-forwarded-for": "127.0.0.2",
  "cf-ray": "5227a43677279304-SJC",
  "x-forwarded-proto": "http",
  "cf-visitor": "{\"scheme\":\"http\"}",
  "cf-ew-via": "15",
  "cdn-loop": "cloudflare; subreqs=1",
  "x-real-ip2": "127.0.0.1",
  "cf-worker": "maple3142.workers.dev",
  "cf-connecting-ip": "127.0.0.2"
}

It is clear that CloudFlare workers stripped the “X-Real-IP” headers.

CF has some protections to prevent Workers from sending requests to IPs with the wrong SNI, so I assume it also has some protections against faking the client’s IP. @KentonVarda

This is basically a bug. Historically Cloudflare’s stack has used X-Real-IP internally to identify the client IP, and then renames it to CF-Connecting-IP as one of the last steps before sending the request to origin. The behavior you observe with workers is an artifact of that, since Workers run much earlier in the pipeline. We have it on our list to fix this someday but it’s kind of tricky to do without breaking existing users, etc.

Long story short, there is currently no way to send a header to your origin called X-Real-IP. Sorry.

2 Likes