Normalise IP addresses across backend

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-03 18:19:41 +02:00
parent 85d05ee582
commit 96525573fa
6 changed files with 24 additions and 49 deletions

View File

@@ -57,6 +57,7 @@ from app.utils.fail2ban_response import (
ok,
to_dict,
)
from app.utils.ip_utils import normalise_ip
from app.utils.time_utils import since_unix
if TYPE_CHECKING:
@@ -96,10 +97,11 @@ async def ban_ip(socket_path: str, jail: str, ip: str) -> None:
except ValueError as exc:
raise ValueError(f"Invalid IP address: {ip!r}") from exc
normalized = normalise_ip(ip)
client = Fail2BanClient(socket_path=socket_path, timeout=FAIL2BAN_SOCKET_TIMEOUT)
try:
ok(await client.send(["set", jail, "banip", ip]))
ok(await client.send(["set", jail, "banip", normalized]))
except ValueError as exc:
if is_not_found_error(exc):
raise JailNotFoundError(jail) from exc
@@ -113,14 +115,15 @@ async def unban_ip(socket_path: str, ip: str, jail: str | None = None) -> None:
except ValueError as exc:
raise ValueError(f"Invalid IP address: {ip!r}") from exc
normalized = normalise_ip(ip)
client = Fail2BanClient(socket_path=socket_path, timeout=FAIL2BAN_SOCKET_TIMEOUT)
if jail is None:
ok(await client.send(["unban", ip]))
ok(await client.send(["unban", normalized]))
return
try:
ok(await client.send(["set", jail, "unbanip", ip]))
ok(await client.send(["set", jail, "unbanip", normalized]))
except ValueError as exc:
if is_not_found_error(exc):
raise JailNotFoundError(jail) from exc

View File

@@ -8,7 +8,7 @@ from __future__ import annotations
import structlog
from app.utils.ip_utils import is_valid_ip, is_valid_network
from app.utils.ip_utils import is_valid_ip, is_valid_network, normalise_ip
log: structlog.stdlib.BoundLogger = structlog.get_logger()
@@ -65,7 +65,7 @@ class BlocklistParser:
# Accept only individual IP addresses, skip CIDRs and malformed
if is_valid_ip(stripped):
valid_ips.append(stripped)
valid_ips.append(normalise_ip(stripped))
else:
skipped += 1
@@ -101,7 +101,8 @@ class BlocklistParser:
if is_valid_ip(stripped) or is_valid_network(stripped):
valid += 1
if len(entries) < sample_lines:
entries.append(stripped)
# Normalise individual IPs; keep networks as-is
entries.append(normalise_ip(stripped) if is_valid_ip(stripped) else stripped)
else:
skipped += 1

View File

@@ -48,6 +48,7 @@ from app.utils.fail2ban_response import (
ok,
to_dict,
)
from app.utils.ip_utils import normalise_ip
from app.utils.jail_socket import reload_all
from app.utils.runtime_state import JailServiceState # noqa: TC001
@@ -639,6 +640,7 @@ def _parse_ban_entry(entry: str, jail: str) -> DomainActiveBan | None:
# Validate IP
ipaddress.ip_address(ip)
ip = normalise_ip(ip)
if len(parts) < 2:
# Entry has no time info — return with unknown times.
@@ -1009,6 +1011,7 @@ async def lookup_ip(
except ValueError as exc:
raise ValueError(f"Invalid IP address: {ip!r}") from exc
ip = normalise_ip(ip)
client = Fail2BanClient(socket_path=socket_path, timeout=FAIL2BAN_SOCKET_TIMEOUT)
with contextlib.suppress(ValueError, Fail2BanConnectionError):