FastAPI如何仅允许特定IP的端点访问?

MrF*_*fer 14 fastapi

如何使用 FastAPI 将端点访问限制为仅特定 IP?

Reh*_*mat 19

接受的答案使用 TrustedHostMiddleware 但可以使用反向代理轻松欺骗,即使用 NGINX 或使用任何其他技术。在我看来,在自定义中间件中验证 IP 地址更安全:

from fastapi import FastAPI, Request, status
from fastapi.responses import JSONResponse


app = FastAPI()

# Whitelisted IPs
WHITELISTED_IPS = []

@app.middleware('http')
async def validate_ip(request: Request, call_next):
    # Get client IP
    ip = str(request.client.host)
    
    # Check if IP is allowed
    if ip not in WHITELISTED_IPS:
        data = {
            'message': f'IP {ip} is not allowed to access this resource.'
        }
        return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content=data)

    # Proceed if IP is allowed
    return await call_next(request)
Run Code Online (Sandbox Code Playgroud)

我会维护一个白名单 IP 列表,然后将客户端 IP 与该列表进行比较,400 Bad Request如果该 IP 不在白名单 IP 列表中,则会返回错误。

  • 请注意,如果您在反向代理后面运行,则“request.client.host”将始终是反向代理的 IP。在这种情况下,您需要从“X-Forwarded-For”标头获取客户端的 IP。[uvicorn 的 `ProxyHeaderMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) 可以在给定可信 ip 列表的情况下完成此操作。 (3认同)

Joh*_*fis 10

FastAPI 提供了一个TrustedHostMiddleware来:

强制所有传入请求都具有正确设置的主机标头,以防止 HTTP 主机标头攻击。

from fastapi import FastAPI
from fastapi.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["example.com","*.example.com"] 
)


@app.get("/")
async def main():
    return {"message": "Hello World"}
Run Code Online (Sandbox Code Playgroud)

支持以下论点:

  • allowed_hosts- 应允许作为主机名的域名列表。*.example.com支持 通配符域,例如匹配子域,以允许任何主机名使用allowed_hosts=["*"]或省略中间件。

如果传入请求未正确验证,则会发送 400 响应。

另一种解决方案是为您的部署介质(例如:k8)编写 IP 白名单。