FastAPI как разрешить доступ к конечной точке только для определенного IP?

#fastapi

#fastapi

Вопрос:

Как ограничить доступ к конечной точке только определенными IP-адресами с помощью FastAPI?

Ответ №1:

Принятый ответ использует программное обеспечение 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)
 

Я бы сохранил список IP-адресов, внесенных в белый список, а затем сравнил бы IP-адрес клиента со списком и вернул 400 Bad Request ошибку, если IP-адрес отсутствует в списке IP-адресов, внесенных в белый список.

Комментарии:

1. Обратите внимание, что если вы работаете за обратным прокси, request.client.host всегда будет IP обратного прокси. В этом случае вам нужно получить IP-адрес клиента из X-Forwarded-For заголовка. Есть uvicorn ProxyHeaderMiddleware , который делает именно это, учитывая список доверенных IP-адресов.

Ответ №2:

FastAPI предоставляет программное обеспечение TrustedHostMiddleware, которое:

Обеспечивает, чтобы все входящие запросы имели правильно установленный заголовок хоста, чтобы защититься от атак HTTP Host Header.

 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"}
 

Поддерживаются следующие аргументы:

  • allowed_hosts — Список доменных имен, которые должны быть разрешены в качестве имен хостов. Поддерживаются подстановочные домены, такие как *.example.com для сопоставления поддоменов, чтобы разрешить любому имени хоста использовать allowed_hosts=["*"] или опускать промежуточное программное обеспечение.

Если входящий запрос не проверяется правильно, будет отправлен ответ 400.

Другим решением было бы составить белый список IP-адресов для вашей среды развертывания (например, k8).