Flask middleware to restrict access to Cloudflare IP ranges
Project description
Flask Cloudflare IP Filter
A Flask extension to restrict access to your application, allowing requests only from official Cloudflare IP ranges. This prevents attackers from bypassing Cloudflare's security (like WAF and DDoS protection) by directly accessing your origin server's IP.
Features
- Blocks Unauthorized Access: Rejects any request not originating from a Cloudflare IP with an HTTP 403 Forbidden error.
- Automatic IP List Updates: Fetches the latest IPv4 and IPv6 ranges from Cloudflare's API on startup and updates them periodically in the background (default: every 24 hours).
- Robust & Safe: If the initial IP list fetch fails, the application will refuse to start to prevent running in an insecure state.
- Real IP Logging: Logs the actual visitor IP address using the
CF-Connecting-IPorX-Forwarded-Forheader. - Easy Integration: Integrates with Flask using the familiar extension pattern.
Why is this necessary?
When you use Cloudflare, all legitimate traffic is proxied through their network. However, if an attacker discovers your server's direct IP address, they can send requests directly to it, bypassing all of Cloudflare's protections. This middleware ensures that your application layer only processes requests that have passed through the Cloudflare network.
Important: For maximum security, this application-level protection should be combined with a network-level firewall (like iptables, ufw, or a cloud security group) that is also configured to only accept traffic from Cloudflare's IP ranges.
Requirements
- Python 3.7+
- Flask
- requests
Install dependencies:
pip install Flask requests
Usage
-
Save the code as a file in your project, for example, your_project/cloudflare_filter.py.
-
In your main application file, import and initialize the CloudflareFilter extension.
from flask import Flask
from cloudflare_filter import CloudflareFilter
app = Flask(__name__)
# Initialize the filter and connect it to the app
# This will automatically fetch IPs and register the before_request hook.
cf_filter = CloudflareFilter(app)
@app.route('/')
def index():
# You can get the real visitor IP for your application logic
real_ip = cf_filter.get_real_ip()
return f"This page is protected. Your real IP is {real_ip}"
if __name__ == '__main__':
app.run()
The filter is now active. All routes in your application will be protected automatically.
Example Log Output
[2025-10-11 19:30:00,123] [INFO] Cloudflare IP ranges loaded successfully. (15 IPv4, 13 IPv6 networks)
[2025-10-11 19:30:00,124] [INFO] Cloudflare IP list will be updated every 86400 seconds.
[2025-10-11 19:30:05,456] [INFO] Allowed access from Cloudflare proxy 172.68.54.45. Real IP: 203.0.113.199
[2025-10-11 19:30:10,789] [WARNING] Blocked direct access from non-Cloudflare IP: 198.51.100.23
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloudflare_ip_filter-0.2.1.tar.gz.
File metadata
- Download URL: cloudflare_ip_filter-0.2.1.tar.gz
- Upload date:
- Size: 4.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93e8f769b110073455ba5918fefb8aa30ccae28a9326bb568be4430f879e4881
|
|
| MD5 |
ad9d5177a24bcce7a48a3af597c71b69
|
|
| BLAKE2b-256 |
84f549ebcc107bdaad48b543cf3691692c1bd565d58bfddbd117254799ad5d7e
|
File details
Details for the file cloudflare_ip_filter-0.2.1-py3-none-any.whl.
File metadata
- Download URL: cloudflare_ip_filter-0.2.1-py3-none-any.whl
- Upload date:
- Size: 5.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b6d108e8f1b8ffb00b9b426975c26a8d0dbc7e90dd81371094414470187d404
|
|
| MD5 |
6a925652c9b517f8decd29e729ad9d59
|
|
| BLAKE2b-256 |
a5323508b7d3003548256264c9654f26fe6413d9fdd6c36f5316a40f39909919
|