How to limit endpoint access only to specific IPs with FastAPI?
How to limit endpoint access only to specific IPs with FastAPI?
The accepted answer makes use of the TrustedHostMiddleware but that can be easily spoofed using a reverse proxy, i.e. using NGINX or using any other technique. In my opinion, validating IP address in a custom middleware is more secure:
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)
I'd maintain a list of whitelisted IPs and then I'd compare the client IP to the list and will return a 400 Bad Request error if the IP is not in the whitelisted IPs list.
FastAPI provides a TrustedHostMiddleware that:
Enforces that all incoming requests have a correctly set Host header, in order to guard against HTTP Host Header attacks.
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"}The following arguments are supported:
allowed_hosts- A list of domain names that should be allowed as hostnames. Wildcard domains such as*.example.comare supported for matching subdomains to allow any hostname either useallowed_hosts=["*"]or omit the middleware.If an incoming request does not validate correctly then a 400 response will be sent.
Another solution would be to compose an IP whitelist for your deployment medium (ex: k8).