Giter VIP home page Giter VIP logo

request-ip's Introduction

request-ip

A tiny Node.js module for retrieving a request's IP address.

CI Coverage Status npm version

Installation

Yarn

yarn add request-ip

npm

npm install request-ip --save

Getting Started

const requestIp = require('request-ip');

// inside middleware handler
const ipMiddleware = function(req, res, next) {
    const clientIp = requestIp.getClientIp(req); 
    next();
};

// on localhost you'll see 127.0.0.1 if you're using IPv4 
// or ::1, ::ffff:127.0.0.1 if you're using IPv6

As Connect Middleware

const requestIp = require('request-ip');
app.use(requestIp.mw())

app.use(function(req, res) {
    const ip = req.clientIp;
    res.end(ip);
});

To see a full working code for the middleware, check out the examples folder.

The connect-middleware also supports retrieving the ip address under a custom attribute name, which also works as a container for any future settings.

How It Works

It looks for specific headers in the request and falls back to some defaults if they do not exist.

The user ip is determined by the following order:

  1. X-Client-IP
  2. X-Forwarded-For (Header may return multiple IP addresses in the format: "client IP, proxy 1 IP, proxy 2 IP", so we take the first one.)
  3. CF-Connecting-IP (Cloudflare)
  4. Fastly-Client-Ip (Fastly CDN and Firebase hosting header when forwared to a cloud function)
  5. True-Client-Ip (Akamai and Cloudflare)
  6. X-Real-IP (Nginx proxy/FastCGI)
  7. X-Cluster-Client-IP (Rackspace LB, Riverbed Stingray)
  8. X-Forwarded, Forwarded-For and Forwarded (Variations of #2)
  9. appengine-user-ip (Google App Engine)
  10. req.connection.remoteAddress
  11. req.socket.remoteAddress
  12. req.connection.socket.remoteAddress
  13. req.info.remoteAddress
  14. Cf-Pseudo-IPv4 (Cloudflare fallback)
  15. request.raw (Fastify)

If an IP address cannot be found, it will return null.

Samples Use Cases

  • Getting a user's IP for geolocation.

Running the Tests

Make sure you have the necessary dev dependencies needed to run the tests:

npm install

Run the integration tests

npm test

Building

Compiles the current ES6 code to ES5 using Babel.

npm build

Release Notes

See the wonderful changelog

To generate a new changelog, install github-changelog-generator then run npm run changelog. This will require being on Ruby >= 3

Contributors

Thank you to all the contributors!

License

The MIT License (MIT) - 2022

request-ip's People

Contributors

9renpoto avatar andfaulkner avatar aseyfpour avatar austince avatar bitdeli-chef avatar echosonusharma avatar floris-hatsa avatar fluxsauce avatar isayme avatar luisrudge avatar morello-cl avatar nukosuke avatar osherx avatar pbojinov avatar perrin4869 avatar pi0 avatar pmarques avatar rafaelthemendes avatar raunc avatar richardweaver avatar rokob avatar vbryan avatar vishalvijay avatar www-chique avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

request-ip's Issues

Not getting the right ip first time

Hi there

Something wired is happening and I can't get it what.
The case:
I'm making a request to a nodejs http-proxy server and when the first request is made from the client, I'm getting ::1 as ip.
When I'm making the second request I get ::ffff:127.0.0.1.
When I'm making a request without a proxy, I'm getting all the time ::ffff:127.0.0.1
Is there something that i should know?

Thanks

Client IP not getting captured

I am using the below code within my node js application and when i try to run it locally the code inside app.use is not getting triggered and ip variable is blank

var connect = require('connect');
var http = require('http');
app.use(requestIp.mw())
var ip
app.use(function(req, res) {
    // by default, the ip address will be set on the `clientIp` attribute
     ip = req.clientIp;
     res.end(ip + '\n');
    console.log('ip is %s',ip)
   
});

Mac address instead of IP

Getting the Mac address in most of the cases, is this normal ?

for example : *****:fb90:d07f:fee4:0:b:fbfe:1b01

needs semver

Will you just bump this to 1.0.0 please?

It appears that the API is production ready and I would like the security of knowing that until 2.0.0 I don't need to worry that the single API is going to break or disappear.

Thanks.

Usage guide should mention stripping unexpected headers

request-ip goes down a list of different methods of providing an IP address, and picks the first one that works. If the user of this library doesn't filter out unknown/unexpected headers, this is quite a dangerous way of determining the IP address. If X-Client-IP wasn't filtered by the user's web server, then an attacker could set the X-Client-IP header themselves and request-ip would happily accept it as the 'real' IP.

A more secure design would be for the user to configure request-ip with the headers and request keys they expect to get the IP from, and to only use them.

Add support for fastify

At the moment you will always get null from fastify unless one of the headers match. Fastify puts most of the data you are looking for in raw, so my current workaround is to do the following, which is not ideal, but seems to work:

requestIP.getClientIp(request) ||
requestIP.getClientIp(request.raw)

So should be a simple addition to allow for this.

Add prioritize option for header check order

So X-Forwarded-For header can be exploited with this library if we add XFF header in the request.
On Nginx, we can use the alternative X-Real-IP header for $remote_addr value.

Maybe we can add something like below?

app.use( clientIp.mw({ prioritize: ["x-real-ip",], }) );

This will push change header priority list from default
[ 'x-client-ip', 'x-forwarded-for', 'cf-connecting-ip', 'fastly-client-ip', 'true-client-ip', 'x-real-ip', 'x-cluster-client-ip', 'x-forwarded', 'forwarded-for', 'forwarded', 'x-appengine-user-ip', ];

to

[ 'x-real-ip', 'x-client-ip', 'x-forwarded-for', 'cf-connecting-ip', 'fastly-client-ip', 'true-client-ip', 'x-cluster-client-ip', 'x-forwarded', 'forwarded-for', 'forwarded', 'x-appengine-user-ip', ];

Screen Shot 2022-12-20 at 4 27 59 PM

Screen Shot 2022-12-20 at 4 31 43 PM

lib/index.js is not up to date in master branch

The current master branch appears to be a build behind itself โ€” e.g., the lib/index.js file is not current with the src/index.js file. Specifically, the lookup for the DigitalOcean-specific way of including the client IP address that's present on line 82 of src/index.js:

https://github.com/NCI-CCR-OIT/request-ip/blob/d8215ca9147c2a20a8a3d0304c4d04531c415c20/src/index.js#L82

is missing in the lib/index.js file. I presume all that's needed is a new npm run build to catch it up...

optimized your code a bit (no need to evalutate every option before choosing first one that matches. just evaluate then return on first match)

     function getClientIp(req) {

         var ipAddress;


         if ((ipAddress = req.headers['x-client-ip'])) return ipAddress;

         var forwardedForAlt = req.headers['x-forwarded-for'];
         if (forwardedForAlt) {
             return forwardedForAlt.split(',')[0];
         }

        // x-cluster-client-ip 
        // (Rackspace LB and Riverbed's Stingray)
        // http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
        // https://splash.riverbed.com/docs/DOC-1926


         var keys=['x-real-ip', 'x-cluster-client-ip', 'x-forwarded', 'forwarded-for', 'forwarded'];
         var key,k,l=keys.length;
         for (k=0; k < l ; k++) {
             key=keys[k];
             if (req.headers[key]) {
                 return req.headers[key];
             }
         }
         // remote address checks
         if (req.connection) if (req.connection.remoteAddress) return req.connection.remoteAddress;

         if (req.socket) if (req.socket.remoteAddress) return req.socket.remoteAddress;

         if (req.connection) if (req.connection.socket) if (req.connection.socket.remoteAddress) return req.connection.socket.remoteAddress;

         if (req.info) if (req.info.remoteAddress) return req.info.remoteAddress;
         // return null if we cannot find an address 
         return null;
     }

  // wrapper to get ipv4
 function getClientIp4(req){
    var ip=typeof req==='string'?req:getClientIp(req);
    return (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined));
}

(node:71664) [FSTDEP005] FastifyDeprecation "request.connection"

Im using request-ip in my fastify application and after I updated to Fastify@4 Im getting following warning:

(node:71664) [FSTDEP005] FastifyDeprecation: You are accessing the deprecated "request.connection" property. 
Use "request.socket" instead.
    at Object.emit (xxxx/process-warning/index.js:52:13)
    at Request.get (xxxx/fastify/lib/request.js:211:17)
    at Object.getClientIp (xxxx/request-ip/lib/index.js:88:21)
    at resolveIp (xxxx/dist/middlewares/my-file.js:7:89)
    at Object.fastifyReqLogger [as req] (xxxxx/dist/main.js:62:69)
    at Pino.asJson (xxxx/pino/lib/tools.js:132:33)
    at Pino.write (xxxx/pino/lib/proto.js:205:28)
    at Pino.LOG [as info] (xxxx/pino/lib/tools.js:62:21)
    at Object.routeHandler [as handler] (xxxx/fastify/lib/route.js:470:19)
    at Router.callHandler (xxxx/find-my-way/index.js:398:14)"

It is a simple fix by modifying the following code snippet:
image

as the latest version of fastify suggests.

Can I open PR with that fix?

Invalid header

File: index.js
Line: 20
Invalid header - X-Forwarder-For
Need: X-Forwarded-For

Nginx problems

This module works great untill installing nginix, I get IP 127.0.0.1. any idea ?

How to receive IP in client

Hello. I'm working a Reactjs project. And in my understanding, this module reture IP on server, how to receive ip on client? Regards

IP is null, request to firebase emulator from within website iframe

const requestIp = require('request-ip');

exports.ipMiddleware = (req, res, next) => {
  req.clientIp = requestIp.getClientIp(req);
  next();
};

I have the above code and even when I am outputting in the console.log the req.clientIp it is null. This is through firebase running locally via an emulator. Ideas on why that may be?

The request is sent from within an iframe in a website.

Handle Firebase hosting header fastly-client-ip

Hello

Google cloud functions forwards original IP in the header x-forwarded-for. It works perfectly with this library.

Google cloud doesn't provide an option to use a custom domain with google cloud function. To achieve that we need to use Firebase hosting.

So when a user makes a request, it first comes to firebase hosting and firebase rewrites the request to google cloud function.

This time x-forwarded-for header will have firebase hosting (CDN) IP and they will add original IP in a header called fastly-client-ip

Sample request header forwared by firebase hosting

Header { host: 'us-central1-xyz.cloudfunctions.net',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  'accept-language': 'en-US,en;q=0.9',
  'cache-control': 'no-cache, no-store',
  'fastly-client': '1',
  'fastly-client-ip': '103.228.xxx.xxx', // Original IP
  'fastly-ff': 's48hDkrIORDrAz3sjuyh5gIWcInqIjSROZ47KAY+w/I=!MAA!cache-maa18320-MAA, s48hDkrIORDrAz3sjuyh5gIWcInqIjSROZ47KAY+w/I=!MAA!cache-maa18323-MAA',
  'fastly-orig-accept-encoding': 'gzip, deflate, br',
  'fastly-ssl': '1',
  'fastly-temp-xff': '103.228.xxx.xxx, 103.228.xx.xxx',
  'function-execution-id': '0hjs129juok9',
  pragma: 'no-cache',
  'upgrade-insecure-requests': '1',
  'x-appengine-api-ticket': '06df6279b81c6e08',
  'x-appengine-city': '?',
  'x-appengine-citylatlong': '0.000000,0.000000',
  'x-appengine-country': 'US',
  'x-appengine-https': 'on',
  'x-appengine-region': '?',
  'x-appengine-user-ip': '35.192.2.154',
  'x-cloud-trace-context': '44ad94ad1640fba12579d8ee8a393993/17096524669660557033;o=1',
  'x-forwarded-for': '35.192.2.154, 35.192.2.154',
  'x-forwarded-host': 'fun-api.xyz.com',
  'x-forwarded-proto': 'https',
  'x-forwarded-server': 'cache-maa18320-MAA',
  'x-forwarded-url': '/api/users/xxxx',
  'x-nginx-proxy': 'true',
  'x-real-ip': '157.52.84.23',
  'x-timer': 'S1533819437.997477,VS0',
  'x-varnish': '3227790704, 2976440830',
  'accept-encoding': 'gzip' }

Support Cloudflare?

https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

First exception: CF-Connecting-IP

To provide the client (visitor) IP address for every request to the origin, Cloudflare adds the CF-Connecting-IP header.

"CF-Connecting-IP: A.B.C.D"

where A.B.C.D is the client's IP address, also known as the original visitor IP address.

and

Sixth Exception: True-Client-IP Enterprise Plan only

To provide the client (visitor) IP address for every request to the origin, Cloudflare adds the True-Client-IP header.

"True-Client-IP: A.B.C.D"

where A.B.C.D is the client's IP address, also known as the original visitor IP address. This request header is only available on our Enterprise plan.

If you're willing, I can submit a PR.

Add support for Cloudflare's "Cf-Pseudo-IPv4" header (as a last resort)

In Cloudflare, you have the option to enable a pseudo-IPv4 header for servers that don't fully support IPv6. If this feature is enabled, every request will have a "Cf-Pseudo-IPv4" header which contains an IPv4 address. It would be cool if you could add this as a last fallback that gets tried if every other header fails.
Here's an article on it: https://blog.cloudflare.com/eliminating-the-last-reasons-to-not-enable-ipv6/#introducingpseudoipv4

ES2015 Support

As more of us start adopting ES6/ES2015 in node, we should think about re-writing the library to fit the modern landscape.

Here's the Node.js ES2015 Support: http://node.green/

What are you thoughts on having an ES2015 version and a backwards compatible ES5 version compiled with babel?

Is v3.3.0 released?

On the NPM registry, it is mentioned that the latest version is 3.3.0 but in the request-ip Github Repo, in the release section, we see support only till 3.2.0, and the same under changelog, we see that 3.3.0 is mentioned in the unreleased section.

Can anyone emphasize whether it's released or not after v3.0.2, there were build issues with the package.

Wrong IP if proxied via CloudFlare

Hi,
I'm getting proxy IP instead of client IP, when I have app proxied via CloudFlare. Cloudflare docs we shoud look in CF-Connecting-IP, because value of X-Forwarded-For is same as CF-Connecting-IP only if previous not set (in my example is set with proxy IP). Now I'm getting only proxy IP in X-Forwarded-For.

Example headers I get:

Host: <somehost>
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip
Accept-Language: en-US,en;q=0.5
Cdn-Loop: cloudflare
Cf-Connecting-Ip: <CLIENTIP>
Cf-Ipcountry: <someval>
Cf-Ray: <someval>
Cf-Request-Id: <someval>
Cf-Visitor: {"scheme":"https"}
Cookie: _ga=<someval>; __cfduid=<someval>
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 162.158.90.163
X-Forwarded-Host: <somehost>
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: <someval>
X-Real-Ip: 162.158.90.163

Incompatible with Next.js middleware/Vercel edge functions

I'm using the library to enable IP whitelisting for a Next.js app hosted on Vercel. This causes a build error:

Failed to compile.

../../node_modules/is_js/is.js
Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Middleware middleware

Import trace for requested module:
../../node_modules/request-ip/dist/index.js
./middleware.ts

This is this module's only dependency, can this import be dropped in favour of lightweight equivalents?

Does it support AdonisJS?

Hello, I have a question, and my suggestion, maybe the owner should enable the Discussion feature in this repository for questions like this, thanks.

RFC-7239 "Forwarded" header not properly supported

Current issue

  • The value of the Forwarded header is actually a complex object and not a simple IP, cf. RFC-7239
  • Example: for=123.34.567.89,for=192.0.2.43;by=[APIGW_IP];host=apiid.execute-api.us-east-1.amazonaws.com;proto=https
  • Example 2: for=94.134.90.17;host=public-api.example.org;proto=https (from our app logs)

Proposed solution

  • Write a function getClientIpFromForwarded similar to getClientIpFromXForwardedFor

Use Case

We are using AWS API Gateway with a private ALB (load balancer) and need the IP to use for getting the geo location. AWS API Gateway uses the Forwarded header for the client ip (see example 2). (And the ALB will set X-Forwarded-For with the private class-c IP from the ALB, but that's another issue)

I would also be open to contribute a PR with tests and the required changes. WDYT?

Sources

IP address calculated from X-Forwarded-For are insecure

The way that IP addresses are inferred from X-Forwarded-For is unsafe/incorrect here. You cannot trust any IP addresses in the headers except for the ones added by your proxies.

The code for this section links to:
http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html#x-forwarded-for

At the bottom of that line it says:

If a request from a client already contains an X-Forwarded-For header, Elastic Load Balancing appends the IP address of the client at the end of the header value. In this case, the last IP address in the list is the IP address of the client. For example, the following header contains two IP addresses added by the client, which might not be trustworthy, plus the client IP address added by Elastic Load Balancing:

X-Forwarded-For: ip-address-1, ip-address-2, client-ip-address

The correct way to detect this is to start at the end of the header and work backwards based on how many proxies you know are between your app and the internet. This should be configured by the user, or default to the last IP. For example, if you are running with a single ELB proxy, then you need to take the last value (which is added by ELB), not the first in the list.

azure web app adds port to x-forwarded-for

here's my header on an azure web app:
'x-forwarded-for': '187.65.xxx.xxx:61598',

when you call is.ip('187.65.xxx.xxx:61598'), it returns false.

would you accept a PR to fix this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.