Reputation: 581
How to limit endpoint access only to specific IPs with FastAPI?
Upvotes: 15
Views: 17097
Reputation: 23144
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.com
are 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).
Upvotes: 11
Reputation: 1
You can use ufw
sudo ufw allow from IP proto tcp to any port PORT
Upvotes: -1
Reputation: 5071
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.
Upvotes: 22