feat: Add GeoIP blocking for high-risk countries (RU, CN, KP, IR, BY, SY, VE, CU)
- Update security_service.py with BLOCKED_COUNTRIES list - Add check_geoip() middleware in app.py - Log blocked attempts with security alerts - Uses MaxMind GeoLite2-Country database Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1a06b6ab29
commit
cb574851cf
32
app.py
32
app.py
@ -453,6 +453,38 @@ def get_or_create_analytics_session():
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def check_geoip():
|
||||||
|
"""Block requests from high-risk countries (RU, CN, KP, IR, BY, SY, VE, CU)."""
|
||||||
|
# Skip static files and health checks
|
||||||
|
if request.path.startswith('/static') or request.path == '/health':
|
||||||
|
return
|
||||||
|
|
||||||
|
if not is_ip_allowed():
|
||||||
|
ip = request.headers.get('X-Forwarded-For', request.remote_addr)
|
||||||
|
if ip:
|
||||||
|
ip = ip.split(',')[0].strip()
|
||||||
|
from security_service import get_country_code
|
||||||
|
country = get_country_code(ip)
|
||||||
|
logger.warning(f"GEOIP_BLOCKED ip={ip} country={country} path={request.path}")
|
||||||
|
|
||||||
|
# Create alert for blocked access
|
||||||
|
try:
|
||||||
|
db = SessionLocal()
|
||||||
|
from security_service import create_security_alert
|
||||||
|
create_security_alert(
|
||||||
|
db, 'geo_blocked', 'low',
|
||||||
|
ip_address=ip,
|
||||||
|
details={'country': country, 'path': request.path, 'user_agent': request.user_agent.string[:200]}
|
||||||
|
)
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to create geo block alert: {e}")
|
||||||
|
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def track_page_view():
|
def track_page_view():
|
||||||
"""Track page views (excluding static files and API calls)"""
|
"""Track page views (excluding static files and API calls)"""
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Norda Biznes - Security Service
|
|||||||
Security utilities for NordaBiz platform:
|
Security utilities for NordaBiz platform:
|
||||||
- Audit logging (admin action tracking)
|
- Audit logging (admin action tracking)
|
||||||
- Security alerting (email notifications)
|
- Security alerting (email notifications)
|
||||||
- GeoIP blocking (Poland only)
|
- GeoIP blocking (block high-risk countries: RU, CN, KP, IR, BY, SY, VE, CU)
|
||||||
- 2FA (TOTP) helpers
|
- 2FA (TOTP) helpers
|
||||||
|
|
||||||
Author: Norda Biznes Development Team
|
Author: Norda Biznes Development Team
|
||||||
@ -180,8 +180,9 @@ def _send_alert_email(alert):
|
|||||||
|
|
||||||
# GeoIP configuration
|
# GeoIP configuration
|
||||||
GEOIP_ENABLED = os.getenv('GEOIP_ENABLED', 'false').lower() == 'true'
|
GEOIP_ENABLED = os.getenv('GEOIP_ENABLED', 'false').lower() == 'true'
|
||||||
GEOIP_DB_PATH = os.getenv('GEOIP_DB_PATH', '/var/lib/GeoIP/GeoLite2-Country.mmdb')
|
GEOIP_DB_PATH = os.getenv('GEOIP_DB_PATH', '/var/www/nordabiznes/geoip/GeoLite2-Country.mmdb')
|
||||||
ALLOWED_COUNTRIES = {'PL'} # Only Poland allowed
|
# Block high-risk countries (Russia, China, North Korea, Iran, etc.)
|
||||||
|
BLOCKED_COUNTRIES = {'RU', 'CN', 'KP', 'IR', 'BY', 'SY', 'VE', 'CU'}
|
||||||
GEOIP_WHITELIST = set(os.getenv('GEOIP_WHITELIST', '').split(',')) - {''} # Whitelisted IPs
|
GEOIP_WHITELIST = set(os.getenv('GEOIP_WHITELIST', '').split(',')) - {''} # Whitelisted IPs
|
||||||
|
|
||||||
# GeoIP reader (lazy loaded)
|
# GeoIP reader (lazy loaded)
|
||||||
@ -233,7 +234,7 @@ def get_country_code(ip_address: str) -> str:
|
|||||||
|
|
||||||
def is_ip_allowed(ip_address: str = None) -> bool:
|
def is_ip_allowed(ip_address: str = None) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if an IP address is allowed (from Poland or whitelisted).
|
Check if an IP address is allowed (not from blocked high-risk countries).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ip_address: IP to check (defaults to current request IP)
|
ip_address: IP to check (defaults to current request IP)
|
||||||
@ -264,7 +265,8 @@ def is_ip_allowed(ip_address: str = None) -> bool:
|
|||||||
if country is None:
|
if country is None:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return country in ALLOWED_COUNTRIES
|
# Block high-risk countries
|
||||||
|
return country not in BLOCKED_COUNTRIES
|
||||||
|
|
||||||
|
|
||||||
def geoip_check():
|
def geoip_check():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user