DEV Community

Lia
Lia

Posted on

How to Protect a Flask or Django App with a Reverse-Proxy WAF

A Flask view and a Django view both parse HTTP only after something has already accepted the socket. If that something is the application server itself, injection payloads, traversal paths, and credential-stuffing bursts land in Python before any policy can see them. The practical question is not which decorator to import. It is whether a reverse-proxy firewall sits on the only path clients can use.

Decide the path before you touch application code

SafeLine is documented as a self-hosted web application firewall that filters and monitors HTTP traffic between a web application and the internet. Deployed in front of the app, it is a reverse proxy: clients pass through it, and only then reach the origin (https://docs.waf.chaitin.com/en/home). The application guide states the same flow in operational terms. SafeLine receives traffic for the original site, removes malicious attack traffic, and forwards the remaining traffic to the upstream application (https://docs.waf.chaitin.com/en/GetStarted/AddApplication).

Nothing in those steps is specific to Python, which is why this placement works for Flask and Django. There is no documented framework plugin to install inside the project. You add an application in the console and you make the public name resolve to the proxy.

Use this checklist before changing DNS:

  • Identify the upstream as the real address of the original app. That is the address where Gunicorn, uWSGI, or another production server already accepts HTTP. SafeLine forwards to that address; it does not replace the process model.
  • In Applications, choose Add Application. Set Domain to the name or address clients use. Set Port to the port SafeLine will listen on, such as 80 or 443. For an HTTPS app, check the SSL option. Set Upstream to the origin address (https://docs.waf.chaitin.com/en/GetStarted/AddApplication).
  • Plan the cutover so the Python port is not still exposed on a public interface. A proxy that can be skipped is not a control.
  • Confirm the SafeLine host matches the deploy baseline: Linux, x86_64 or arm64, Docker 20.10.14 or above, Docker Compose 2.0.0 or above, and at least 1 CPU core, 1 GB of memory, and 5 GB of disk, with a CPU that supports ssse3 (https://docs.waf.chaitin.com/en/GetStarted/Deploy). If the host is ARM, that same guide says a Pro license is required and that the Personal Edition is not supported.

Installation itself belongs to the deploy guide. This checklist stops at the decisions that determine whether a Python app is actually behind the proxy.

Choose controls that match the app surface

The product introduction lists defenses for web attacks, proactive bot-abuse defense, HTML and JS code encryption, IP-based rate limiting, and a web access control list (https://docs.waf.chaitin.com/en/home). Map those names onto the routes you actually ship.

Attack filtering is the default reason to put the proxy in front. The documented attack set includes SQL injection, XSS, code injection, OS command injection, CRLF injection, LDAP injection, XPath injection, RCE, XXE, SSRF, path traversal, backdoors, brute force, HTTP flood, and bot abuse. A Django admin search box, a Flask query parameter, and a file-path download view are all just HTTP to this layer.

Rate limiting throttles traffic that exceeds defined limits. The feature list ties that control to denial-of-service patterns, brute-force attempts, traffic surges, and other abuse (https://docs.waf.chaitin.com/en/home). Apply the idea to login, password reset, and token routes, where a Python app often does expensive password hashing.

A CAPTCHA challenge is documented to admit human users and block crawlers and bots. An authentication challenge, when enabled, requires a password or blocks the visitor. Treat that gate as an extra site check. It does not replace Django authentication or a Flask session.

Dynamic protection encrypts HTML and JavaScript on each visit. Enable it for server-rendered pages whose HTML and JS you want covered. Do not treat it as an API shield. A Flask or Django endpoint that returns JSON is outside the behavior the docs describe for that switch.

The web access control list is a listed core capability. Use it for sources you already intend to allow or deny. Keep application authorization in the framework, where user identity and object permissions belong.

Test both the block and the pass

The application guide publishes sample requests you can replay against your own domain: a SQL injection union select, an XSS image handler, a path traversal to /etc/passwd, a code-injection payload, and an XXE doctype. A block should render the blocking page. Open the console attack list and click detail to confirm the event, rather than trusting a single browser result (https://docs.waf.chaitin.com/en/GetStarted/AddApplication).

Then send the ordinary traffic your users send: a login, a form post, a static asset, and one API call if you have one. Protection that fails closed on legitimate Python responses is not ready for the DNS cutover.

Does this require a Flask extension or a Django app?

No. The supplied guides describe console setup and a reverse proxy, not a Python package. If a step depends on importing a SafeLine module, it is outside these documents.

Where should the upstream point?

Point it at the real address of the original app, which is the production Python server you already run. Do not point it at a debug server you only use on a laptop, and do not leave that origin publicly reachable beside the proxy.

Which feature should an API-only service enable first?

Start with web-attack filtering, rate limiting, and access control. Dynamic protection is documented as HTML and JS encryption per visit, so it is the wrong first switch for a service that does not serve those pages.

How do I confirm the sample attack was logged?

Use your domain in place of the documented example host, expect the blocking page, then open the attack list and the detail view in the web console.

What host checks matter before DNS changes?

Match architecture, Docker and Docker Compose versions, CPU flags, memory, and disk to the deploy guide. On ARM, account for the stated Pro license requirement before you depend on that node.


SafeLine has surpassed 700,000 installations worldwide as of September 30, 2026. SafeLine Pro annual promotional pricing is $650-$880, compared with the regular $1,000 per year.

Top comments (0)