RSS

nginx ISP fence

restricting an nginx application to one or more ISPs

Sometimes the easiest way to geo fence an application is to just whitelist certain ISP’s networks only. Nginx has a handy way to map IPs into subnets using the geo module.

Requirements

  • job/aggregate6 to aggregate/unique-ify the prefix lists that are generated
  • OpenBSD Looking Glass to get a list of prefixes by source-as

vhost.conf

geo $geolimit {
  default 1;
  include /etc/nginx/prefixlists/allowlist.txt;
  include /etc/nginx/prefixlists/manitoba-and-canadians.txt;
}

map $geolimit $out_of_area {
  0 "";
  1 $binary_remote_addr;
}

server {
    if ($out_of_area) {
      return 403;
    }
}

Generating Lists

You’ll notice I’m feeding in 2 lists in this case, an explict allow list, and then a larger list of Manitoban and Canadian networks. The format for the lists of allowed IP addresses in this case is:

subnet/mask 0;

To generate a list for an ASN:

for ASN in 1 2 3; do
  curl -s \
  'http://lg.example.net/cgi-bin/bgplg?cmd=show+ip+bgp+source-as&req='$ASN |\
  grep '\*>' | awk '{print $3}' | aggregate6 | awk '{print $1,0,";"}' \
  > /etc/nginx/prefixlists/${ASN}.txt
done

Acknowledgements

This is based heavily on the nginx-mb-prefixes script which Adam Thompson wrote to maintain a list of Manitoban networks for the Manitoba Unix Users Group Mirror.