如何通过Nginx实现未发起GET请求则拦截POST请求?
Got it, let's walk through how to set up this NGINX rule to block spammy POST requests that don't come after a legitimate GET—no captchas required, so your users won't be annoyed. This aligns with the smart first-line defense approach you mentioned, and here's how to make it work with your proxy IP setup:
Core Idea
We'll use NGINX's built-in modules to track IPs that have made legitimate GET requests first. When a POST comes in, we check if the IP has that "validated" marker; if not, we block the request. We'll use $http_x_forwarded_for to capture the real client IP behind proxies (just make sure your proxy is setting this header correctly!).
Full NGINX Configuration Snippet
# Define a shared memory zone to track validated IPs # 10m is enough for most sites (stores ~160k IP entries) limit_req_zone $validated_ip zone=get_validated:10m rate=1000r/s; # Map the client IP (from X-Forwarded-For) to our validation variable # We prioritize the first IP in X-Forwarded-For to avoid proxy IPs map $http_x_forwarded_for $validated_ip { default ""; ~^(?P<first_ip>\d+\.\d+\.\d+\.\d+) $first_ip; } server { # ... your existing server config (listen, server_name, etc.) ... # Handle GET requests: mark the IP as validated location / { if ($request_method = GET) { # This "touches" the limit zone to register the IP limit_req zone=get_validated burst=1 nodelay; } # ... your existing location config (proxy_pass, root, index, etc.) ... } # Protect POST endpoints (adjust the location to match your needs) location /submit-form { if ($request_method = POST) { # Require the IP to exist in the get_validated zone # If not, return 403 Forbidden limit_req zone=get_validated burst=0; } # ... your existing POST handling config (proxy_pass to backend, etc.) ... } }
Breakdown of Key Parts
limit_req_zone: Creates a shared memory zone (get_validated) to store IPs that have made GET requests. Therate=1000r/sis set high enough so legitimate users never hit a rate limit here—it's just a way to track IP presence.map $http_x_forwarded_for $validated_ip: Extracts the real client IP from theX-Forwarded-Forheader (critical if you're behind a CDN or reverse proxy like Cloudflare, Nginx Proxy Manager, etc.). It grabs the first IP in the header to ignore proxy hops.- GET Request Handling: When a user makes a GET request, we run
limit_reqwithburst=1 nodelay—this doesn't restrict the request, but adds their IP to theget_validatedzone. - POST Request Protection: For POST endpoints, we use
limit_req zone=get_validated burst=0—this rejects any POST from an IP that isn't already in the zone (i.e., didn't make a GET first) with a 403 error.
Important Notes
- Proxy Header Validation: Ensure your proxy (CDN, load balancer) is correctly setting
X-Forwarded-Forand that you trust this header. Addreal_ip_header X-Forwarded-For;andset_real_ip_from <proxy-ip-or-cidr>;to your server block if needed to prevent IP spoofing. - Adjust Locations: Modify the
locationblocks to match your actual GET pages and POST endpoints. If you want to protect all POSTs across the site, you can move the POST check to the server context instead of a specific location. - Testing: Test this thoroughly with legitimate users—make sure that navigating to the page (GET) then submitting the form (POST) works, while direct POSTs to the endpoint get blocked.
- Rate Limit Tuning: The
rate=1000r/sis arbitrary—set it higher if you have high traffic; it just needs to be above your normal GET request rate so valid users don't get accidentally blocked.
内容的提问来源于stack exchange,提问作者Ed Tv
相关产品推荐
相关产品推荐

