Hardening the Captive Portal
-
Considering that CP might be used in a potentially "hostile" environment e.g. in a public Hotspot, and as such be subject to various DoS attacks, has anyone attempted to harden it?
One idea would be using ipfw limit src-addr type directives to throttle connections to the lighttpd webserver that serves the CP pages. Another idea would be tuning the lighttpd conf to set more aggressive timeouts and increase the number of max concurrent connections and worker processes to spawn.
Finally, I noticed that the first item in m0n0wall's todo list (afaik pfsense shares most of its CP code with m0n0wall) is "improve captive portal reliability and performance (e.g. by introducing SQLite to replace the various flat text files and corresponding lockfiles)", but it's been listed there since 2009 so I am not holding my breath…
-
You can throttle connections and much more with the normal firewall rules, no need for any abuse to get through PF to ipfw.
We've already improved the scalability of it quite a bit by fixing locking problems 2-3 years ago. We have some other things in the works in private builds that may or may not make it in time for 2.1, in replacing the flat files. Our CP is pretty significantly different from m0n0wall in 1.2.3 and especially 2.0 and newer versions.
-
I had the impression that CP traffic pre-authentication is handled by ipfw and PF only gets to see the packets after a user has logged-in successfully and his IP/MAC added to ipfw's table(1)/table(2).
Also, while PF does have some powerful anti-DoS features (max-src-conn, max-src-conn-rate directives), they don't seem to be configurable from pfSense's webGUI. I actually filed a related feature request here. I did some testing of max-conn-* with overload a few months back by adding such rules from CLI, but triggering those directives caused pfsense to panic so I didn't pursue it further.
Glad to hear you've working on CP scalability.
-
I had the impression that CP traffic pre-authentication is handled by ipfw and PF only gets to see the packets after a user has logged-in successfully and his IP/MAC added to ipfw's table(1)/table(2).
Also, while PF does have some powerful anti-DoS features (max-src-conn, max-src-conn-rate directives), they don't seem to be configurable from pfSense's webGUI. I actually filed a related feature request here. I did some testing of max-conn-* with overload a few months back by adding such rules from CLI, but triggering those directives caused pfsense to panic so I didn't pursue it further.
Glad to hear you've working on CP scalability.
Create an TCP rule in firewall, scroll down to advanced options and then check "advanced options".
Ther is:
Maximum number of established connections per host
Maximum new connections / per second(s)This could help you. Create a firewall rule with:
Source IP: any (or CP interface subnet)
Sourceport: any
Destination IP: pfsense CP interface
Destination Port: 8000 (but perhaps you can choose here any)And then set "Maximum number of established connections per host"
-
Possible to have it add the users MAC address to a deny rule if password attempt fails more than x number of times?
-
Possible to have it add the users MAC address to a deny rule if password attempt fails more than x number of times?
It's very easy to spoof a MAC address, therefore I doubt such a feature would be of any help, in fact it could be used to cause problems to legitimate users.
-
Going back to the subject of protecting the CP against abuse, I noticed the "Maximum concurrent connections per client IP address" ($maxprocperip) setting. A quick look at the source code (captiveportal.inc and system.inc) suggests it sets lighttpd's evasive.max-conns-per-ip directive.
However, if the $maxprocperip "Maximum concurrent connections" field is left empty in webGUI config, it doesn't create a lighty evasive.* directive at all in /var/etc/lighty-Captive*.
I can't find any other way to enforce the "Default 4 connections per client IP, with a max of 16" so it seems like a small bug to me (either fix the comment in the webGUI, or put a value in $captive_portal_mod_evasive in system.inc)