How to protect API endpoints using nginx in a more convenient way

How to protect API endpoints using nginx in a more convenient way. This approach can slightly impact performance, but simplifies configuration and rate limiting.

We have a web service API, some endpoints should be internal only, some may have rate limits. Traditionally, this requires many lines in nginx config. Here's a cleaner approach.

nginx configuration

map $http_x_forwarded_for $uri_acl {
  default 0;
  ~^/remote/downloads 2;
  ~^/remote/uploads 2;
  ~^/a/v1/capabilities 1;
  ~^/a/v1/users 1;
}

map $uri_acl $url_limit_key {
  0 "";
  1 $remote_addr$request_uri;
  2 "";
}

geo $remote_addr $ip_acl {
  default 0;
  172.16.1.21 1;
  172.16.2.21 1;
  172.16.3.21 1;
  172.16.4.21 1;
}

limit_req_zone $url_limit_key zone=api_limit:100m rate=3r/s;

server {
  listen 80;
  listen 443 ssl http2;

  ...

  set $ip_acl_status 0;
  if ($ip_acl = "1") { set $ip_acl_status 1; }
  set $uri_acl_status 0;
  if ($uri_acl = "1") { set $uri_acl_status 1; }
  if ($uri_acl = "2") { set $uri_acl_status 1; }
  set $acl_status "${uri_acl_status}${ip_acl_status}";

  if ( $acl_status ~ (00) ) { return 403; }

  limit_req zone=api_limit burst=5 nodelay;
  limit_req_status 429;
  limit_req_log_level warn;

  ...

  location / {
    ...
  }

}

Result

1. Endpoint with uri_acl=0: 200 + NoRateLimit from allowed IPs, 403 + NoRateLimit from everyone else.

2. Endpoint with uri_acl=1: 200 + NoRateLimit from everyone.

3. Endpoint with uri_acl=2: 200 + RateLimit from everyone.

4. Any other combination can be implemented similarly.

Human Logic, AI Syntax... Note on Content: I'm a Systems Engineer, not a native English writer. To ensure my technical ideas are clear and accessible, I use AI tools to polish the grammar and style. The workflow is simple: I provide the logic, the code, and the real-world experience. The AI handles the "English-to-Human" translation layer. If you find a bug, that's on me. If you find a perfectly placed comma, that's probably the AI.

Comments

Popular posts from this blog

FreeRadius with Google Workspace LDAP

Fixing pssh (parallel-ssh) Problems on Debian 10 with Python 3.7