mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-16 11:42:47 +03:00
validate trusted_proxies at config load
Malformed trusted_proxies entries were only parsed per request in get_remote_addr, so a typo logged a warning on every proxied request and the entry was skipped, collapsing all clients behind that proxy into one rate-limit bucket. The config now rejects unparseable entries at startup and get_remote_addr no longer needs the fallback. Host bits are accepted (192.168.1.1/24 reads as 192.168.1.0/24) so a common typo doesn't take down safe mode, which copies the auth section verbatim.
This commit is contained in:
+4
-8
@@ -314,14 +314,10 @@ def get_remote_addr(request: Request):
|
|||||||
|
|
||||||
route = list(reversed(forwarded_for.split(",")))
|
route = list(reversed(forwarded_for.split(",")))
|
||||||
logger.debug(f"IP Route: {[r for r in route]}")
|
logger.debug(f"IP Route: {[r for r in route]}")
|
||||||
trusted_proxies = []
|
trusted_proxies = [
|
||||||
for proxy in request.app.frigate_config.auth.trusted_proxies:
|
ipaddress.ip_network(proxy, strict=False)
|
||||||
try:
|
for proxy in request.app.frigate_config.auth.trusted_proxies
|
||||||
network = ipaddress.ip_network(proxy)
|
]
|
||||||
except ValueError:
|
|
||||||
logger.warning(f"Unable to parse trusted network: {proxy}")
|
|
||||||
continue
|
|
||||||
trusted_proxies.append(network)
|
|
||||||
|
|
||||||
# return the first remote address that is not trusted
|
# return the first remote address that is not trusted
|
||||||
for addr in route:
|
for addr in route:
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import ipaddress
|
||||||
|
|
||||||
from pydantic import Field, field_validator, model_validator
|
from pydantic import Field, field_validator, model_validator
|
||||||
|
|
||||||
from .base import FrigateBaseModel
|
from .base import FrigateBaseModel
|
||||||
@@ -68,6 +70,14 @@ class AuthConfig(FrigateBaseModel):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@field_validator("trusted_proxies")
|
||||||
|
@classmethod
|
||||||
|
def validate_trusted_proxies(cls, v: list[str]) -> list[str]:
|
||||||
|
for proxy in v:
|
||||||
|
ipaddress.ip_network(proxy, strict=False)
|
||||||
|
|
||||||
|
return v
|
||||||
|
|
||||||
@field_validator("roles")
|
@field_validator("roles")
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_roles(cls, v: dict[str, list[str]]) -> dict[str, list[str]]:
|
def validate_roles(cls, v: dict[str, list[str]]) -> dict[str, list[str]]:
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ class TestConfig(unittest.TestCase):
|
|||||||
DetectorTypeEnum.cpu
|
DetectorTypeEnum.cpu
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_trusted_proxies_reject_invalid_networks(self):
|
||||||
|
config = {
|
||||||
|
"auth": {"trusted_proxies": ["172.18.0.0/16", "192.168.1.1/24", "fd00::/8"]}
|
||||||
|
}
|
||||||
|
FrigateConfig(**deep_merge(config, self.minimal))
|
||||||
|
|
||||||
|
config = {"auth": {"trusted_proxies": ["172.18.0.0/33"]}}
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
FrigateConfig(**deep_merge(config, self.minimal))
|
||||||
|
|
||||||
@patch("frigate.detectors.detector_config.load_labels")
|
@patch("frigate.detectors.detector_config.load_labels")
|
||||||
def test_model_custom_path(self, mock_labels):
|
def test_model_custom_path(self, mock_labels):
|
||||||
mock_labels.return_value = {}
|
mock_labels.return_value = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user