Geo blocking by country?

Is there some plugin for blocking requests by country? Our customer has the legal requirement to block any incoming requests from Iran and North Korea. The current old implementation is based on the IP2Country database hooked into the skin in some weird way...or any recommendable plugin for Nginx or Apache?

Nginx ships a module to use the Maxmind GeoIP database.

https://nginx.org/en/docs/http/ngx_http_geoip_module.html

And on Debian, a GeoIP module for iptables is included in the xtables addons:

https://packages.debian.org/stretch/amd64/xtables-addons-common/filelist
https://packages.debian.org/stretch/all/xtables-addons-dkms/filelist

There also seems to be a convenience wrapper to keep the volatile GeoIP database up to date (IPv4 blocks are auctioned across continents at an increasing pace at the moment).

https://packages.debian.org/stretch/geoipupdate

I'd actually try to solve the problem on the iptables level, if possible. If this is to be only done for http(s) traffic, then the webfront layer makes sense.

We ended up with a traversal subscriber checking the IP using the geoip module for Python:

   <subscriber
    for="ZPublisher.pubevents.PubAfterTraversal"
    handler=".geoblocking.geoblocking"
    /> 

from geoip import geolite2

blacklisted_countries = [
  'AM', # Armenien
  'AZ', # Aserbaidschan
  'BY', # Belarus
  'CD', # Kongo, Demokratische Republik
  'CI', # Elfenbeinkueste
  'ER', # Eritrea
  'GW', # Guinea-Bissau
  'IQ', # Irak
  'IR', # Iran
  'KP', # Korea, Demokratische Volksrepublik (Nordkorea)
  'LB', # Libanon
  'LR', # Liberia
  'LY', # Libyen
  'MD', # Moldova, Republic of (Moldau)
  'MM', # Myanmar
  'PG', # Guinea
  'SD', # Sudan
  'SL', # Sierra Leone
  'SO', # Somalia
  'SS', # Suedsudan
  'SY', # Syrien
  'YE', # Jemen
  'ZW'  # Simbabwe
  ]


def geoblocking(event):
    request = event.request
    ip = request.get('HTTP_X_FORWARDED_FOR', None) or request.get('HTTP_X_REAL_IP', None) or request.get('REMOTE_ADDR', None)
    match = geolite2.lookup(ip)
    portal = plone.api.portal.get()
    blocked_url = portal.absolute_url() + '/blocked'
    if match.country in blacklisted_countries:
        request.response.redirect(blocked_url)