How can I geoblock with an API gateway?
Imagine you release a new API that provides weather data for locations worldwide. Except, for some reason, your weather satellites have two blindspots on the globe. They’re not able to display accurate weather information for the island nations of American Samoa and Iceland.
While you work to fix the issue, you don’t want to frustrate users in either country by giving them inaccurate information. Instead, you want a clean user experience with a custom error message. You can do this by geoblocking with your API gateway.
Geoblocking is a strategy that restricts access to your API based on the request's geographic location or the regional Point of Presence (PoP) that received the request. Locations are pulled from geolocation registries, which store geolocation information and map it to IP addresses in the region. API gateways such as ngrok can use this information to filter, route, and block requests.
Why geoblocking matters
At its core, geoblocking is about control. With APIs often exposed globally, the ability to block traffic from specific regions can enhance security, reduce risk, and ensure compliance. In our example, we want to restrict requests seeking weather data in regions our API doesn’t support. However, you may have other reasons to geoblock requests.
For instance, if you're operating in a region with strict data privacy laws, you might want to restrict access from countries with uncertain compliance. Similarly, blocking traffic from regions with high malicious activity—like botnets or repeated DDoS attacks—can help reduce your attack surface.
Geoblocking can also improve performance. Limiting traffic to regions where you know your users are located can avoid unnecessary load on your servers and reduce latency for legitimate users.
Geoblocking with ngrok
ngrok enables geoblocking through Common Expression Language (CEL) expressions in the Traffic Policy engine. Those expressions also support a variety of variables and macros. Variables in the <code>conn.geo</code> namespace allow for ngrok to block requests based on the location of the request. The <code>conn.geo.country_code</code> variable allows you to build expressions using two-letter country codes. In the case of the weather API mentioned earlier, <code>conn.geo.country_code</code> allows you to identify all requests from America Samoa (AS) and Iceland (IS) using their country codes. To block those requests and return a <code>custom-response</code>, the Traffic Policy rule would look something like this:
on_http_request:
- expressions:
- "conn.geo.country_code in ['AS', 'IS']"
name: "Block traffic from unwanted countries"
actions:
- type: "custom-response"
config:
status_code: 403
content: "Forbidden request due to unsupported country of origin"
on_http_response: []
The rule blocks all requests originating from the listed countries and returns a <code>custom-response</code> with <code>status_code: 403</code>.
Should your geoblocking needs require more granularity, the <code>conn.geo</code> namespace also has variables for city, longitude, latitude, server region, and even radius–the kilometers around the latitude and longitude where the <code>conn.client_ip</code> is likely to originate.
You can even combine expressions. If you only want to geoblock certain endpoints, that expression would look like this:
- expressions:
- "conn.geo.country_code in ['AS', 'IS']"
- “req.URL.contains(‘/api/forecast’)”
Geoblocking isn’t just for HTTP connections. You can also filter requests on the TCP layer. Using Traffic Policy, the variables from the <code>conn.geo</code> namespace are still available to build expressions. The only difference is the expression would be under a <code>on_tcp_connect</code> phase rather than the <code>on_http_connect</code> phase.
While there are other strategies for geoblocking, such as DNS-based geoblocking and blocking at the application layer, blocking with the location of the client IP is the most common way to geoblock.
Things to consider with geoblocking
Geoblocking can be a powerful tool, but there are a few factors to keep in mind:
- False positives: Not all IP addresses are tied directly to a specific location. Determining their location can be tricky when users connect through VPNs and proxy services.
- Performance impact: There could be performance implications depending on how and where you implement geoblocking. IP-based geoblocking with a service like ngrok typically happens early in the request lifecycle and has a minimal impact on your application. However, blocking at the application level might add latency to your requests.
- Compliance vs. usability: Geoblocking can help ensure compliance with regional laws, but if done too broadly, it can frustrate users who should be allowed access. Be mindful of regions where your users may travel or use cross-border services, and balance blocking with legitimate access needs.
Get started with geoblocking
To get started working with the geolocations of requests on your API, sign up for an ngrok account and check out the documentation for ngrok’s Traffic Policy module to see how to formulate expressions and actions. Then, dive into the Connection Geo Variables section of the HTTP Variables document to discover the different ways to retrieve geoinformation for requests.