gaurishhs/elysia-ip

Incorrect IP Header Priority

Closed this issue · 4 comments

Description:
I'm experiencing an issue with the elysia-ip when specifying headers for IP retrieval. Despite setting cf-connecting-ip as the header to check, the middleware is still returning the IP from the x-forwarded-for header.

Node.js Version: v20.11.0
Elysia Version: v1.0.20
elysia-ip Version: v1.0.5
bun Version: v1.0.26

import { Elysia } from "elysia";
import { ip } from "elysia-ip";

const app = new Elysia()
  .use(ip({ headersOnly: true, checkHeaders: ["cf-connecting-ip"] })).get(
    "/test",
    ({ ip, request }) => {
      console.log("ip", ip);
      console.log("headers", JSON.stringify(request.headers, null, 2));
      return "777";
    },
  ).listen(3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
);

Run the following curl command to test

curl http://localhost:3000/test \
  -H 'cf-connecting-ip: 192.168.1.1' \
  -H 'x-forwarded-for: 192.168.2.2'

Observe that the console output shows the IP from x-forwarded-for instead of cf-connecting-ip.
Console Output:

ip 192.168.2.2
headers {
  "cf-connecting-ip": "192.168.1.1",
  "x-forwarded-for": "192.168.2.2"
}

Will release a fix for it

If you using array in checkHeaders it will be at least priority.
But if you using string like checkHeaders: "cf-connecting-ip".
It will first priority.

export const getIP = (
headers: Headers,
checkHeaders: IPHeaders[] = headersToCheck,
) => {
if (typeof checkHeaders === "string" && headers.get(checkHeaders)) {
logger("getIP", `Found ip from header ${checkHeaders}`)
return headers.get(checkHeaders)
}
// X-Forwarded-For is the de-facto standard header
if (headers.get("x-forwarded-for")) {
logger("getIP", "IP From Header x-forwarded-for")
return headers.get("x-forwarded-for")?.split(",")[0]
}
if (!checkHeaders) {
logger("getIP", "checkHeaders `false` return `null`")
return null
}
let clientIP: string | undefined | null = null
for (const header of checkHeaders) {
clientIP = headers.get(header)
if (clientIP) {
logger("getIP", `Found ip from header ${header}`)
break
}
}
if (!clientIP) {
logger("getIP", "Failed to get ip from header!")
return
}
return clientIP

I think a better idea would be to disable forced X-Forwaded-For header checking when using custom headers.

@vanisoul Thank you for reporting this what @armada45-pixel suggested will work and in array also, it will work.