nginx ISP fence
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.