function getClientIp(req) { // Server is probably behind a proxy. if (req.headers) { // Standard headers used by Amazon EC2, Heroku, and others. if (is.ip(req.headers['x-client-ip'])) { return req.headers['x-client-ip']; } // Load-balancers (AWS ELB) or proxies. const xForwardedFor = getClientIpFromXForwardedFor(req.headers['x-forwarded-for']); if (is.ip(xForwardedFor)) { return xForwardedFor; } // Cloudflare. // @see https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers- // CF-Connecting-IP - applied to every request to the origin. if (is.ip(req.headers['cf-connecting-ip'])) { return req.headers['cf-connecting-ip']; } // Akamai and Cloudflare: True-Client-IP. if (is.ip(req.headers['true-client-ip'])) { return req.headers['true-client-ip']; } // Default nginx proxy/fcgi; alternative to x-forwarded-for, used by some proxies. if (is.ip(req.headers['x-real-ip'])) { return req.headers['x-real-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 if (is.ip(req.headers['x-cluster-client-ip'])) { return req.headers['x-cluster-client-ip']; } if (is.ip(req.headers['x-forwarded'])) { return req.headers['x-forwarded']; } if (is.ip(req.headers['forwarded-for'])) { return req.headers['forwarded-for']; } if (is.ip(req.headers.forwarded)) { return req.headers.forwarded; } } // Remote address checks. if (is.existy(req.connection)) { if (is.ip(req.connection.remoteAddress)) { return req.connection.remoteAddress; } if (is.existy(req.connection.socket) && is.ip(req.connection.socket.remoteAddress)) { return req.connection.socket.remoteAddress; } } if (is.existy(req.socket) && is.ip(req.socket.remoteAddress)) { return req.socket.remoteAddress; } if (is.existy(req.info) && is.ip(req.info.remoteAddress)) { return req.info.remoteAddress; } return null; }
...
## Getting Started
```javascript
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
```
...
function getClientIpFromXForwardedFor(value) { if (!is.existy(value)) { return null; } if (is.not.string(value)) { throw new TypeError(`Expected a string, got "${typeof value}"`); } // x-forwarded-for may return multiple IP addresses in the format: // "client IP, proxy 1 IP, proxy 2 IP" // Therefore, the right-most IP address is the IP address of the most recent proxy // and the left-most IP address is the IP address of the originating client. // source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html const forwardedIps = value.split(',').map(e => e.trim()); // Sometimes IP addresses in this header can be 'unknown' (http://stackoverflow.com/a/11285650). // Therefore taking the left-most IP address that is not unknown // A Squid configuration directive can also set the value to "unknown" (http://www.squid-cache.org/Doc/config/forwarded_for/) return forwardedIps.find(is.ip); }
...
}
});
});
});
test('getClientIpFromXForwardedFor', (t) => {
t.plan(3);
t.equal(requestIp.getClientIpFromXForwardedFor('107.77.213.113, 172.31.41.116'
;), '107.77.213.113');
t.equal(requestIp.getClientIpFromXForwardedFor('unknown, unknown'), undefined);
t.throws(() => requestIp.getClientIpFromXForwardedFor({}), TypeError);
});
test('x-client-ip', (t) => {
t.plan(1);
const options = {
...
function mw(options) { // Defaults. const configuration = is.not.existy(options) ? {} : options; // Validation. if (is.not.object(configuration)) { throw new TypeError('Options must be an object!'); } const attributeName = configuration.attributeName || 'clientIp'; return (req, res, next) => { req[attributeName] = getClientIp(req); // eslint-disable-line no-param-reassign next(); }; }
...
// or ::1, ::ffff:127.0.0.1 if you're using IPv6
```
### As Connect Middleware
```javascript
const requestIp = require('request-ip');
app.use(requestIp.mw())
app.use(function(req, res) {
const ip = req.clientIp;
res.end(ip);
});
```
...