FreeBSD + pf + ikiwiki captive portal
The idea here is not to be secure, but to provide the splash page for visitors using the wifi. This is done through a series of crazy scripts.
This is a C inetd-daemon that will add your IP to the pf tables. It runs as root, from inetd, and gets your IP from the socket directly. It can therefore be loaded in an iframe.
I have also tried to talk directly to pf, but gave up. Here was the code I had so far.
Router configuration
This is done on the FreeBSD router:
Compile the code into binary:
gcc pftableadd.c -o /usr/local/sbin/pftableadd
Hook up as a webserver in inetd:
http stream tcp nowait root /usr/local/sbin/pftableadd pftableadd http stream tcp6 nowait root /usr/local/sbin/pftableadd pftableadd
Configure inetd to start at boot:
echo 'inetd_enable="YES"' >> /etc/rc.conf
Enable a redirect rule for all machines to the webserver:
table <cleared> persist rdr pass on $dmz_if proto tcp from ! <cleared> to ! 192.168.2.1 port 80 -> $marcos port 80
Enable a cronjob to purge the old entries from the table:
echo '*/5 * * * * root pfctl -q -t cleared -Texpire 86400' >> /etc/crontab
Webserver configuration
Now the webserver must answer those requets! It needs to be able to answer to any vhost so you want your _default_
vhost to point somewhere sane, that will actually call the webserver defined on the router above.
To call the command, you need an iframe like this:
<iframe height="100px" width="500px" src="http://192.168.2.1/"></iframe>
It can probably be styled better, but that's the general idea. To to this in ikiwiki, I have created the portal page with the htmlscrubber plugin disabled, with locked edit. See tips/embedding content/ for more information about how to embed content in ikiwiki.
I actually had to use the IP because DNS/IPv6 wasn't working (ie. IPv6 doesn't work on OpenWRT and I can't publish the private NAT IP on DNS).
Issues
- The daemon runs as root. This may be a huge security issue, but then again the code is very small (32 lines) and uses only basic system calls.
- The portal page doesn't refresh: I haven't figured out how to refresh a page in ikiwiki.