基于Nginx部署React应用,如何配置API仅服务器访问并阻止非法调用?
Alright, let's tackle this problem head-on. First off, you’ve hit a key issue: Referer headers are extremely easy to fake (as your curl test clearly shows), so relying solely on checking that won’t stop determined attackers. We need to layer up defenses with Nginx configuration tweaks and core API-side validation to lock this down properly.
1. Hardened Nginx Config: First Line of Defense
First, make sure your Nginx setup is correctly serving your React build and proxying API requests to port 9001. Then add these safeguards to the /api/ location block to filter out obvious bad requests:
Sample Nginx Config
server { listen 8081; server_name localhost; # Serve React static files location / { root /path/to/your/react/app/build; try_files $uri $uri/ /index.html; } # Proxy API requests to your backend location /api/ { # Block requests without a valid referer from your React app valid_referers none blocked localhost:8081; if ($invalid_referer) { return 403 Forbidden; } # Restrict to only the HTTP methods your API actually uses limit_except GET POST { deny all; } # Add a custom header only Nginx sends (for API validation later) proxy_set_header X-Trusted-Proxy "your-unique-secret-string"; # Forward the request to your API server proxy_pass http://localhost:9001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
Note: This will block casual attempts, but as you saw, someone can still fake the Referer. Think of this as a "speed bump" rather than a full barrier.
2. API-Side Validation: The Real Security Lock
Since any client-side header can be forged, the real protection has to happen on your API server (port 9001). Here are the most effective options:
Option A: Validate the Custom Nginx Header
Since we added X-Trusted-Proxy to the Nginx config, your API can check for this header and verify its value matches the secret string you set. If it doesn’t exist or is wrong, reject the request with a 403.
For example, if your API is in Node.js/Express:
app.use('/api', (req, res, next) => { const trustedProxySecret = req.headers['x-trusted-proxy']; if (!trustedProxySecret || trustedProxySecret !== 'your-unique-secret-string') { return res.status(403).send('Unauthorized access'); } next(); });
This works because only requests routed through your Nginx will have this header—anyone hitting the API directly (even if they find port 9001) won’t know the secret string.
Option B: Add CSRF Protection
If your app uses user sessions, implement CSRF tokens:
- When your React app loads, fetch a CSRF token from your API (store it in memory or an HttpOnly cookie).
- Include this token in every API request (e.g., in an
X-CSRF-Tokenheader). - Your API validates that the token matches the one associated with the user’s session.
This prevents cross-site request forgery and makes it much harder for attackers to craft valid requests without interacting with your React app first.
Option C: Restrict API Port Access with Firewall
Add a firewall rule (like iptables on Linux) to block external access to port 9001 entirely. Only allow localhost (where Nginx is running) to connect to it:
iptables -A INPUT -p tcp --dport 9001 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 9001 -j DROP
This way, attackers can’t even reach your API directly—all requests must go through Nginx first.
3. Extra Security Touches
- Rate Limiting: Add rate limits to Nginx to prevent brute-force attempts:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=15r/m; location /api/ { limit_req zone=api_limit burst=5 nodelay; # Existing config... }
- Use HTTPS: In production, always serve your app over HTTPS. This encrypts all request headers, making it harder for attackers to snoop on or modify them.
Final Takeaway
Don’t rely on Referer checks alone—they’re too easy to bypass. Combine Nginx’s basic filtering with API-side header validation (Option A is my top pick here) and firewall restrictions, and you’ll have a robust defense against unauthorized API access.
内容的提问来源于stack exchange,提问作者jrock2004

