Geographic and IP-Based Rate Limiting
Geographic and IP-Based Rate Limiting
Geographic distribution of rate limits helps manage global traffic while preventing localized attacks. Different regions may have different usage patterns and attack profiles, requiring tailored rate limiting strategies. IP-based rate limiting provides an additional layer of defense against distributed attacks.
# Python example of geographic rate limiting
import geoip2.database
from ipaddress import ip_address, ip_network
from typing import Dict, List, Optional
class GeographicRateLimiter:
def __init__(self, geoip_db_path: str):
self.reader = geoip2.database.Reader(geoip_db_path)
self.country_limits = {
'default': {'rate': 100, 'burst': 1000},
'US': {'rate': 200, 'burst': 2000},
'CN': {'rate': 50, 'burst': 500},
'RU': {'rate': 50, 'burst': 500}
}
self.blocked_countries = {'KP', 'IR'} # Example blocked countries
self.suspicious_asns = {13335, 16509} # Example ASNs to monitor
def get_rate_limit(self, ip: str) -> Optional[Dict]:
try:
response = self.reader.city(ip)
country = response.country.iso_code
# Check if country is blocked
if country in self.blocked_countries:
return None
# Get country-specific limits or default
limits = self.country_limits.get(country, self.country_limits['default'])
# Check for suspicious ASNs
asn = self.get_asn(ip)
if asn in self.suspicious_asns:
# Reduce limits for suspicious networks
limits = {
'rate': limits['rate'] // 2,
'burst': limits['burst'] // 2
}
return limits
except Exception as e:
# Default limits for unknown IPs
return self.country_limits['default']
def is_ip_suspicious(self, ip: str) -> bool:
"""Check if IP exhibits suspicious characteristics"""
checks = [
self.is_datacenter_ip(ip),
self.is_proxy_ip(ip),
self.is_tor_exit_node(ip),
self.has_poor_reputation(ip)
]
return any(checks)
def is_datacenter_ip(self, ip: str) -> bool:
"""Check if IP belongs to known datacenter ranges"""
datacenter_ranges = [
'104.16.0.0/12', # Cloudflare
'35.0.0.0/8', # Google Cloud
'52.0.0.0/8' # AWS
]
ip_obj = ip_address(ip)
return any(ip_obj in ip_network(range) for range in datacenter_ranges)
# Integration with rate limiting
class EnhancedRateLimiter:
def __init__(self, geo_limiter: GeographicRateLimiter):
self.geo_limiter = geo_limiter
self.ip_buckets = {}
def check_rate_limit(self, ip: str, api_key: Optional[str] = None) -> Dict:
# Get geographic limits
geo_limits = self.geo_limiter.get_rate_limit(ip)
if not geo_limits:
return {'allowed': False, 'reason': 'Geographic restriction'}
# Apply stricter limits for suspicious IPs
if self.geo_limiter.is_ip_suspicious(ip):
geo_limits['rate'] = min(geo_limits['rate'], 10)
geo_limits['burst'] = min(geo_limits['burst'], 50)
# Apply rate limiting with geographic limits
return self.apply_token_bucket(ip, geo_limits['rate'], geo_limits['burst'])