fix(security): funnel公网流量强制校验API_KEY双保险(Tailscale-Funnel-Request头,不可伪造)
This commit is contained in:
+25
-7
@@ -55,13 +55,17 @@ def _is_trusted(ip: str) -> bool:
|
||||
return any(addr in net for net in TRUSTED_NETWORKS)
|
||||
|
||||
|
||||
async def require_api_key(
|
||||
request: Request,
|
||||
x_api_key: Optional[str] = Header(default=None, alias="X-API-Key"),
|
||||
) -> None:
|
||||
"""校验 API Key:Tailscale 内网/本机放行,外部来源必须携带有效 Key"""
|
||||
if _is_trusted(_client_ip(request)):
|
||||
return
|
||||
def _is_funnel_request(request: Request) -> bool:
|
||||
"""判断是否 tailscale funnel 公网流量
|
||||
|
||||
tailscale serve 转发时会把客户端伪造的 Tailscale-* 头清空后按真实
|
||||
情况设置:tailnet 内无此头,funnel 公网流量为 "?1"(不可伪造)。
|
||||
"""
|
||||
return request.headers.get("tailscale-funnel-request") == "?1"
|
||||
|
||||
|
||||
async def _require_key(x_api_key: Optional[str]) -> None:
|
||||
"""按外部来源校验 API Key(可信内网已在调用方排除)"""
|
||||
if not settings.API_KEY:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
@@ -74,6 +78,20 @@ async def require_api_key(
|
||||
)
|
||||
|
||||
|
||||
async def require_api_key(
|
||||
request: Request,
|
||||
x_api_key: Optional[str] = Header(default=None, alias="X-API-Key"),
|
||||
) -> None:
|
||||
"""校验 API Key:Tailscale 内网/本机放行,外部来源必须携带有效 Key"""
|
||||
# funnel 公网流量:即使来源 IP 恰在 tailnet 网段也强制校验(双保险)
|
||||
if _is_funnel_request(request):
|
||||
await _require_key(x_api_key)
|
||||
return
|
||||
if _is_trusted(_client_ip(request)):
|
||||
return
|
||||
await _require_key(x_api_key)
|
||||
|
||||
|
||||
async def require_agent_key(
|
||||
x_agent_key: Optional[str] = Header(default=None, alias="X-Agent-Key"),
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user