npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@fullerstack/nax-ipware

v0.10.0

Published

A node library for server applications retrieving user's real IP address

Downloads

47,249

Readme

NAX IPware (A Node Application Agnostic Library)

A node library for server applications retrieving user's real IP address

status-image version-image coverage-image

Overview

Best attempt to get client's IP address while keeping it DRY.

Notice

There is not a good out-of-the-box solution against fake IP addresses, aka IP Address Spoofing. You are encouraged to read the Advanced users section of this page and use trusted proxy prefixes and/or proxy count features to match your needs, especially if you are planning to include ipware in any authentication, security or anti-fraud related architecture. You are also encouraged to use ip filtering alongside ipware for optimal result.

How to install

npm install @fullerstack/nax-ipware OR yarn add @fullerstack/nax-ipware

How to use

 # In a view or a middleware where the `request` object is available

  // In your js file (e.g. app.js)
  import {Ipware} from '@fullerstack/nax-ipware';
  const ipware = new Ipware();
  app.use(function(req, res, next) {
    req.ipInfo = ipware.getClientIP(req)
    // { ip: '177.139.100.100', isPublic: true, isRouteTrusted: false }
    // do something with the ip address (e.g. pass it down through the request)
    // note: ip address doesn't change often, so better cache it for performance,
    // you should have distinct session ID for public and anonymous users to cache the ip address
    next();
  });

Advanced users:

| Flags ⇩ | ⇩ Description | | -------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | count ⇨ | : Total number of expected proxies (pattern: client, proxy1, ..., proxy2): if count = 0 then client: if count = 1 then client, proxy1: if count = 2 then client, proxy1, proxy2 : if count = 3 then client, proxy1, proxy2 proxy3 | | proxyList ⇨ | : List of trusted proxies (pattern: client, proxy1, ..., proxy2): if proxyList = ['10.1.'] then client, 10.1.1.1 OR client, proxy1, 10.1.1.1: if proxyList = ['10.1', '10.2.'] then client, 10.1.1.1 OR client, proxy1, 10.2.2.2: if proxyList = ['10.1', '10.2.'] then client, 10.1.1.1 10.2.2.2 OR client, 10.1.1.1 10.2.2.2 | | publicOnly ⇨ | : Returns only public and internet routable IP or null |

| Output Field ⇩ | ⇩ Description | | -----------------: | :------------------------------------------------------------------------------- | | ip ⇨ | : IP address of the client | | isPublic ⇨ | : If ip is public and internet routable, true, else false | | isRouteTrusted ⇨ | : If proxy count and/or proxyList provided and matched, true, else false |

Precedence Order

The client IP address can be found in one or more request headers attributes. The lookup order is top to bottom and the default attributes are as follow.

// The default meta precedence order
export const IPWARE_HEADERS_IP_ATTRIBUTES_ORDER: string[] = [
  'X_FORWARDED_FOR', // Load balancers or proxies such as AWS ELB (default client is `left-most` [`<client>, <proxy1>, <proxy2>`])
  'HTTP_X_FORWARDED_FOR', // Similar to X_FORWARDED_TO
  'HTTP_CLIENT_IP', // Standard headers used by providers such as Amazon EC2, Heroku etc.
  'HTTP_X_REAL_IP',
  'HTTP_X_FORWARDED',
  'HTTP_X_CLUSTER_CLIENT_IP',
  'HTTP_FORWARDED_FOR',
  'HTTP_FORWARDED',
  'HTTP_VIA',
  'X-REAL-IP', // NGINX
  'X-CLUSTER-CLIENT-IP', // Rackspace Cloud Load Balancers
  'X_FORWARDED',
  'FORWARDED_FOR',
  'CF-CONNECTING-IP', // CloudFlare
  'TRUE-CLIENT-IP', // CloudFlare Enterprise,
  'FASTLY-CLIENT-IP', // Firebase, Fastly
  'FORWARDED',
];

You can customize the order by providing your own list during initialization when calling new Ipware(options). You can pass your custom list on every call, when calling the api to fetch the ip.

  ipware.getClientIP(request, {
    requestHeadersOrder: ['X_FORWARDED_FOR'],
  });

  ipware.getClientIP(request, {
    requestHeadersOrder: ['X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR'],
  });

  // ... etc

Private Prefixes

A default list that holds the private IP prefixes is called IPWARE_PRIVATE_IP_PREFIX. This list is used to determine if an IP address is public or private.

It is recommended that you send us any private IP addresses that we have missed, to be included in the default list.

export const IPWARE_PRIVATE_IP_PREFIX: string[] = [
  '0.', // messages to software
  '10.', // class A private block
  ...[
    // carrier-grade NAT (IPv4)
    '100.64.',
    '100.65.',
    '100.66.',
    '100.67.',
  ],
  // many more prefixes
]

You can customize the private IP prefixes by providing your own list during initialization when calling new Ipware(options). You can pass your custom list on every call, when calling the api to fetch the ip.

  ipware.getClientIP(request, {
    privateIpPrefixes: ['0.', '10.'], // your own private IP addresses
  });

  ipware.getClientIP(request, {
    privateIpPrefixes: ['0.', '10.', '2001:10:'], // your own private IP addresses
  });

  // ... etc

Trusted Proxies

If your node server is behind one or more known proxy server(s), you can filter out unwanted requests by providing a trusted proxy list, or a known proxy count.

You can customize the proxy IP prefixes by providing your own list during initialization when calling new Ipware(options). You can pass your custom list on every call, when calling the proxy-aware api to fetch the ip.

// In the above scenario, use your load balancer IP address as a way to filter out unwanted requests.
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    proxyList: ['177.139.233.132']
  },
});

// If you have multiple proxies, simply add them to the list
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    proxyList: ['177.139.233.100', '177.139.233.132']
  },
});

// For proxy servers with fixed sub-domain and dynamic IP, use the following pattern.
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    proxyList: ['177.139.', '177.140']
  },
});

const ipInfo = ipware.getClientIP(request, {
  proxy: {
    proxyList: ['177.139.233.', '177.139.240']
  },
});

// For proxy by ip address and count
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    proxyList: ['177.139.', '177.140'],
    count: 2
  },
});

// For strict mode, we either return the ip that matches the proxy info, or none
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    strict: true,
    proxyList: ['177.139.233.', '177.139.240']
  },
});

In the following example, your public load balancer (LB) can be seen as a trusted proxy.

`Real` Client <public> <-> <public> LB (Server) <private> <-----> <private> Node Server
                                                             ^
                                                             |
`Fake` Client <private> <-> <private> LB (Server) <private> -+

Proxy Count

If your node server is behind a known number of proxies, but your deploy on multiple providers and don't want to track proxy IPs, you still can filter out unwanted requests by providing proxy count.

You can customize the proxy count by providing your count during initialization when calling new Ipware(options). You can pass your custom count on every call, when calling the proxy-aware api to fetch the ip.

// In the above scenario, the total number of proxies can be used as a way to filter out unwanted requests.
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    count: 1
  },
});

// For proxy by count, and proxy list
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    count: 1
    proxyList: ['177.139.233.']
  },
});

// For strict mode, we either return the ip that matches the proxy info, or none
const ipInfo = ipware.getClientIP(request, {
  proxy: {
    strict: true,
    count: 1
  },
});

In the following example, your public load balancer (LB) can be seen as the only proxy.

`Real` Client <public> <-> <public> LB (Server) <private> <---> <private> Node Server
                                                            ^
                                                            |
                                `Fake` Client  <private> ---+

Public IP Address ONLY (routable on the internet)

// For publicOnly mode, we either return the first public IP address based on order or none
const ipInfo = ipware.getClientIP(request, {
  publicOnly: true
});

Originating Request

If your proxy server has a custom configuration where the right-most IP address is that of the originating client, you can indicate right-most as the order when calling any api. Please note that the de-facto standard for the originating client IP address is the left-most as per client, proxy1, proxy2, and the right-most proxy is the most trusted proxy.

Running the tests

To run the tests against the current environment:

yarn nx test nax-ipware

License

Released under a (MIT) license.

Version

X.Y.Z Version

`MAJOR` version -- making incompatible API changes
`MINOR` version -- adding functionality in a backwards-compatible manner
`PATCH` version -- making backwards-compatible bug fixes

Sponsors

Neekware Inc.