如何阻止特定IP段/地区/国家访问网站部分页面?
Got it, let's break down the practical technical approaches to restrict access to specific pages (not your entire site) based on IP ranges, regions, or countries. These are the most reliable directions you can take:
This is often the most efficient option because access checks happen before requests reach your application, reducing unnecessary load. Let's cover the two most common servers:
Nginx Setup
Use Nginx's geo and geoip2 modules to define restricted IP ranges and countries, then apply rules only to specific page paths:
# Load GeoIP2 module (install via package manager first if missing) geoip2 /usr/share/GeoIP/GeoIP2-Country.mmdb { $geoip2_country_code country iso_code; } # Define restricted IP ranges geo $restricted_ip { default 0; 192.168.1.0/24 1; # Block this subnet 10.0.0.0/8 1; # Block this range } server { listen 80; server_name yoursite.com; # Allow full access to all public pages location / { try_files $uri $uri/ /index.php?$args; } # Restrict access to specific paths: /private-page and /admin/* location ~ ^/(private-page|admin/) { # Block restricted IP ranges if ($restricted_ip) { return 403; } # Block specific countries (e.g., CN = China, RU = Russia) if ($geoip2_country_code ~ ^(CN|RU)$) { return 403; } # Pass allowed requests through try_files $uri $uri/ /index.php?$args; } }
Note: For more reliable country detection, use MaxMind's GeoIP2 database. Avoid overusing if directives where possible—for complex rules, Nginx's map module is safer.
Apache Setup
Use mod_geoip and mod_rewrite to target restricted paths:
# Load required modules LoadModule geoip_module modules/mod_geoip.so LoadModule rewrite_module modules/mod_rewrite.so GeoIPEnable On GeoIPDBFile /usr/share/GeoIP/GeoIP.dat # Apply restrictions to specific pages RewriteEngine On # Match restricted IP ranges RewriteCond %{REMOTE_ADDR} ^192\.168\.1\. [OR] RewriteCond %{REMOTE_ADDR} ^10\.0\.0\. # Match restricted countries RewriteCond %{GEOIP_COUNTRY_CODE} ^(CN|RU)$ # Apply rule to /private-page and /admin paths RewriteRule ^/(private-page|admin/) - [F,L]
Note: The [F] flag returns a 403 Forbidden response, and [L] stops processing further rules.
If you need flexibility (like combining access rules with user authentication or app-specific logic), handle checks directly in your code. Here are examples for common languages:
PHP Example
// Get user's real IP (adjust if behind a CDN/proxy) $userIp = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR']; // Assume a helper function to get country code (use MaxMind's PHP library for accuracy) $countryCode = getCountryCodeFromIp($userIp); // Define restrictions $restrictedIps = ['192.168.1.0/24', '10.0.0.0/8']; $restrictedCountries = ['CN', 'RU']; $restrictedPaths = ['/private-page', '/admin']; // Check if current page is restricted $currentPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $isRestrictedPage = false; foreach ($restrictedPaths as $path) { if (str_starts_with($currentPath, $path)) { $isRestrictedPage = true; break; } } if ($isRestrictedPage) { // Check IP against restricted ranges foreach ($restrictedIps as $range) { if (isIpInRange($userIp, $range)) { http_response_code(403); exit("Access Denied: Your IP range is restricted."); } } // Check country if (in_array($countryCode, $restrictedCountries)) { http_response_code(403); exit("Access Denied: Your region is restricted."); } } // Helper function to validate IP ranges function isIpInRange($ip, $range) { list($subnet, $mask) = explode('/', $range); $ipDecimal = ip2long($ip); $subnetDecimal = ip2long($subnet); $maskDecimal = -1 << (32 - $mask); return ($ipDecimal & $maskDecimal) === ($subnetDecimal & $maskDecimal); }
Node.js (Express) Example
const express = require('express'); const geoip = require('geoip-lite'); const ipRangeCheck = require('ip-range-check'); const app = express(); // Define restrictions const restrictedIps = ['192.168.1.0/24', '10.0.0.0/8']; const restrictedCountries = ['CN', 'RU']; const restrictedPaths = ['/private-page', '/admin']; // Middleware to check access const checkAccess = (req, res, next) => { const userIp = req.headers['x-forwarded-for'] || req.connection.remoteAddress; const geoData = geoip.lookup(userIp); const currentPath = req.path; // Skip checks for unrestricted pages const isRestricted = restrictedPaths.some(path => currentPath.startsWith(path)); if (!isRestricted) return next(); // Block restricted IPs if (ipRangeCheck(userIp, restrictedIps)) { return res.status(403).send('Access Denied: IP range restricted'); } // Block restricted countries if (geoData && restrictedCountries.includes(geoData.country)) { return res.status(403).send('Access Denied: Region restricted'); } next(); }; // Apply middleware to all routes app.use(checkAccess); // Define your routes app.get('/', (req, res) => res.send('Public Page')); app.get('/private-page', (req, res) => res.send('Private Page')); app.get('/admin/dashboard', (req, res) => res.send('Admin Dashboard')); app.listen(3000, () => console.log('Server running on port 3000'));
If you use a CDN or WAF (like Cloudflare, AWS CloudFront, or Akamai), this is the easiest and most scalable approach—no server config changes needed. For example, with Cloudflare:
- Go to your Cloudflare Dashboard → Rules → Page Rules
- Create a new rule with a URL match for
yoursite.com/private-page*andyoursite.com/admin* - Add a Security action: select "Block", then choose "Country" or "IP Address" to define restricted groups
- Save the rule, and Cloudflare will block matching requests at the edge before they reach your server
- IP Forwarding: If behind a CDN/proxy, ensure your server reads the
X-Forwarded-Forheader (and trusts the proxy) to get the real user IP—otherwise you'll block the CDN's IPs instead of users. - GeoIP Accuracy: Free GeoIP databases have minor errors; for precision, use a paid tier (like MaxMind's GeoIP2 Precision).
- Testing: Use a VPN to simulate different regions, or IP-spoofing tools, to verify rules work without accidental false blocks.
- User Experience: Customize your 403 error page to explain why access was denied, instead of showing a generic message.
内容的提问来源于stack exchange,提问作者Neha Patel

