Add user agent blocklist, use X-Real-IP header for IP detection

This commit is contained in:
2025-11-10 16:06:30 +03:00
Unverified
parent 320442c5fc
commit 0f86e9541c
11 changed files with 499 additions and 0 deletions
+35
View File
@@ -17,6 +17,8 @@ import os
from security.audit import log_security
from security.profanity import contains_profanity
from security.user_agent_blocklist import is_user_agent_blocked
from security.rate_limit import rate_limit_per_ip, rate_limit_per_user
router = APIRouter()
_FAILED_ATTEMPT_WINDOW_SECONDS = 300
@@ -65,9 +67,25 @@ def check_auth(current_user: User = Depends(get_current_user)):
@router.post("/login")
@rate_limit_per_ip("5/minute")
def login(request: LoginRequest, http: Request, db: Session = Depends(get_db)):
username = request.username.strip()
client_ip = get_client_ip(http)
raw_ua = http.headers.get("user-agent")
if is_user_agent_blocked(raw_ua):
log_security(
"blocked_user_agent",
severity="warning",
username=username,
ip=client_ip,
user_agent=raw_ua or "Unknown",
action="login",
)
raise HTTPException(
status_code=403,
detail="Доступ запрещён"
)
user = db.query(User).filter(User.username == username).first()
@@ -162,12 +180,28 @@ def login(request: LoginRequest, http: Request, db: Session = Depends(get_db)):
@router.post("/register")
@rate_limit_per_ip("3/hour")
def register(request: RegisterRequest, http: Request, db: Session = Depends(get_db)):
username = request.username.strip()
display_name = request.display_name.strip()
password = request.password.strip()
confirm_password = request.confirm_password.strip()
client_ip = get_client_ip(http)
raw_ua = http.headers.get("user-agent")
if is_user_agent_blocked(raw_ua):
log_security(
"blocked_user_agent",
severity="warning",
username=username,
ip=client_ip,
user_agent=raw_ua or "Unknown",
action="registration",
)
raise HTTPException(
status_code=403,
detail="Доступ запрещён"
)
# Determine if owner already exists
owner_exists = db.query(User).filter(User.username == OWNER_USERNAME).first() is not None
@@ -411,6 +445,7 @@ def logout(
@router.post("/change-password")
@rate_limit_per_user("5/hour")
def change_password(
request: ChangePasswordRequest,
http: Request,