metcoder95 / fastify-ip

Infer the Request IP (or IPs if behind a proxy) based on custom headers
MIT License
7 stars 0 forks source link
fastify fastify-plugin ip proxy

fastify-ip

NPM npm CI


fastify-ip is a plugin which allows to infer the incoming request's IP based on a custom subset of well known headers used by different providers or technologies that possible sits in-front of your fastify application.

How it works?

The plugin will make a best-effort to infer the request's IP based on a subset of well-known headers, which looks as follows:

'x-client-ip' // Most common
'x-forwarded-for' // Mostly used by proxies
'cf-connecting-ip' // Cloudflare
'Cf-Pseudo-IPv4' // Cloudflare
'fastly-client-ip'
'true-client-ip' // Akamai and Cloudflare
'x-real-ip' // Nginx
'x-cluser-client-ip' // Rackspace LB
'forwarded-for'
'x-forwarded'
'forwarded'
'x-appengine-user-ip' // GCP App Engine

The plugin will use a FIFO strategy to infer the right IP. This can be customised by passing a custom order property that includes your custom headers.

Note: It is important to remark that this does not alters the Request#ips behaviour for inferring IPs when setting the FastifyOptions#trustProxy to true. It rather allows you to infer the IP of a given request by headers out of the common spec or standard.

Setup

Install by running npm install fastify-ip.

Then register the plugin to your fastify instance:

const fastify = require('fastify')({
  logger: true
})

fastify.register(require('fastify-ip'), {
    order: ['x-my-ip-header'],
    strict: false,
    isAWS: false,
})

Options

API

The plugin will decorate the Request object with a set of utils that can be handy for managing IPs.

How to use it?

JavaScript

app.get('/', (req, reply) => {
    req.log.info({ ip: req.ip }, 'my ip!')
    req.log.info({ isValid: req.isIP('hello!') } /* false */)
    req.log.info({ isIPv4: req.isIPv4('127.0.0.1') })
    req.log.info({ isIPv6: req.isIPv6('::1') })
    req.log.info({ version: req.inferIPVersion('127.0.0.1') /* 4 */ })
    req.log.info({ version: req.inferIPVersion('::1') /* 6 */ })
    req.log.info({ version: req.inferIPVersion('asd') /* 0 */ })

    reply.send(req.ip)
})

TypeScript

app.post('/', (request: FastifyRequest, reply: FastifyReply) => {
    req.log.info({ ip: req.ip }, 'my ip!')
    req.log.info({ isValid: req.isIP('hello!') } /* false */)
    req.log.info({ isIPv4: req.isIPv4('127.0.0.1') })
    req.log.info({ isIPv6: req.isIPv6('::1') })
    req.log.info({ version: req.inferIPVersion('127.0.0.1') /* 4 */ })
    req.log.info({ version: req.inferIPVersion('::1') /* 6 */ })
    req.log.info({ version: req.inferIPVersion('asd') /* 0 */ })

    reply.send(req.ip)
});

Type Definitions

export interface FastifyIPOptions {
  order?: string[] | string;
  strict?: boolean;
  isAWS?: boolean;
}

declare module 'fastify' {
  interface FastifyRequest {
    isIP(pseudo: string): boolean;
    isIPv4(pseudo: string): boolean;
    isIPv6(pseudo: string): boolean;
    inferIPVersion(pseudo: string): 0 | 4 | 6;
  }
}

See test for more examples.