User Tools

Site Tools


Setting up a captive portal from scratch using Debian


The following pages detail the installation of a Debian based operating system to do the following:

  • Share an internet connection to a number of users
  • Force people to sign up via a webpage before access is granted (with optional token system)
  • Traffic shape, so that P2P is given minimal bandwidth and web browsing is given priority
  • Display splash page periodically for advertising
  • Log all web browsing with Squid proxy server
  • Internet access is provided through an Alcatel speedtouch modem or a Solos ADSL2+ PCI card

Although all the steps are shown to achieve this, they are not all explained in depth. This is more of a reminder to me so that a reinstall can be performed! If you do have any questions, please email me. The following assumptions are made:

  • Subnet of the network is
  • Domain is called 'wardroom'

Install Debian

Initial install

The assumption of the install is that no internet connection is available. Therefore the following are required initially:

  • CD1 of the standalone Debian install (V6)
  • Speedtouch firmware files (see below - assuming a speedtouch modem is used)

Install as follows:

  • Boot from CD
  • Select the options as appropriate
  • Set up manual networking, using for all the IP addresses and as the network mask.
    • For this example the hostname will be called qualso
    • For this example the domain will be called wardroom


Set up partitioning as required. I used automatic partitioning.

Remaining system installation

  • Let system install base software
  • Enter root password as required
  • When prompted create new user 'user' with required password
  • Select No to the option to scan another CD/DVD
  • Select No to use a network mirror for packages
  • Select No to package usage survey
  • Install Debian with web, DNS, SSH server and Standard packages
  • Select 'yes' to install GRUB to master boot record
  • Installation should now be finished. Take CD out and reboot into new system.

Setup the internet connection

We setup the internet connection now so that we can download further packages.

Using a Solos PCI ADSL internal modem

The Solos PCI drivers are bundled with recent kernel versions. I have previously had problems with the bundled versions and had to install from source. However, as of Squeeze they work out of the box.

  • Install PPP using the command
apt-get install ppp
  • Create file /etc/ppp/chap-secrets with the following contents:

"username@isp" "*" "password"

Replace username and password as appropriate

  • Create file /etc/ppp/peers/isp0 with the following contents:
user username@isp

Replace username as appropriate

Using a Speedtouch modem

  • Install the ADSL Speedtouch modem firmware. Full details are here but you should just be able to copy the 2 firmware files into /lib/firmware.

For ease, both files are located at:

Alternatively, these firmware files may work (for other versions):

Obviously you will need to download these on another PC if you do not currently have internet on the current server.

  • Install PPP using the command
apt-get install ppp

Create file /etc/ppp/chap-secrets with the following contents:

"username@isp" "*" "password"

Replace username and password as appropriate

Create file /etc/ppp/peers/isp0 with the following contents:

user username@isp

Replace username as appropriate

Disconnect and reconnect the USB modem to force it to load the firmware. Once the modem has synced, connect as below.

Temporarily connect to the internet

Connect to the internet using pppd call isp0

This will be set to happen automatically later.

Further packages to install

A number of additional packages are needed and can be installed using apt. Because the installation was initially done from a CD, no network repositories will be available, so it is best to set one up using the netselect command. However, netselect is not currently installed and is not on the CD! So, setup a temporary network repository first:

echo deb squeeze main > /etc/apt/sources.list
apt-get update

Then install netselect-apt:

apt-get install netselect-apt

And finally use netselect to setup the best repositories:

cd /etc/apt
netselect-apt squeeze
apt-get update
  • Now install additional packages using the command:

apt-get install conntrack iptraf joe sudo squid3 php5 mysql-server php5-mysql

  • Install the DHCP server (this will fail to start after installation):

apt-get install dhcp3-server

Restart apache to load PHP (apache2ctl restart)

  • Edit /etc/apt/sources.list and uncomment the security updates line at the end

Set up ethernet IP address

  • Edit /etc/network/interfaces
  • Ensure the eth0 entry looks as follows:
auto eth0
iface eth0 inet static
  • If required set up a second ethernet interface. This can be used to provide internet access for a separate independent network if required. Add the following code to /etc/network/interface:
auto eth1
iface eth1 inet static
  • Restart networking:
/etc/init.d/networking restart

Update config files

Whenever told to edit files from this point use the Joe editor started with the command “joe <file to edit>

  • Set up web server for captive portal (apache). The following instructions download all the files from this website. They can be edited as required, or alternatively full instructions for this method of setting up a captive portal are detailed elsewhere on this site.
cd /var/
tar -zxvf portalshaper-www.tar.gz
rm portalshaper-www.tar.gz
  1. Edit settings.php and set all variables at beginning of the file as required, including the passwords
  2. Edit key.php and add your own random key
  3. Create blank database:
  4. echo create database portal | mysql -p
  5. mysql -p portal < portal-schema.sql
  6. Setup mysql user (using password chosen in settings.php)
  7. echo grant INSERT,UPDATE,DELETE,SELECT,LOCK TABLES on portal.* to 'portal'@'localhost' identified by \'<password>\'|mysql -p
  8. You may also want to manually configure the hostname in /etc/apache2/apache2.conf by using the ServerName directive.
  • Configure URL redirect for captive portal by enabling mod_rewrite:
cd /etc/apache2/mods-enabled
ln -s ../mods-available/rewrite.load
  • Edit /etc/apache2/sites-enabled/000-default and add rewrite rules after ServerAdmin (be sure to edit server name qualso and add any other webserver names):
Options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_HOST} !^qualso [NC]
RewriteCond %{HTTP_HOST} !^earth [NC]
RewriteRule . http://qualso.wardroom/index.php/%{HTTP_HOST}%{REQUEST_URI}?%{QUERY_STRING} [L,R]
  • Restart Apache: apache2ctl restart
  • Set up DNS server

The DNS server is used to serve domain names of the local network and can also be used as a caching nameserver.

  • Edit /etc/bind/named.conf.local
  • Add the following after the “localhost” domain:
zone "wardroom" {
    type master;
    file "/etc/bind/db.wardroom";
  • Go to /etc/bind
  • Copy db.local to db.wardroom
  • Edit db.wardroom
  • Add required hostnames at the end of the file. These entries setup 3 different names for the main server (spaces should be tabs, and make sure that you increase the serial number). qualso is the name you gave your server earlier, earth is the name of the server as assumed by the web server and the captive portal web scripts.
qualso      A
earth       A
mail        A
  • Reload BIND with /etc/init.d/bind9 reload
  • Set up DHCP server for serving IP addresses to the local network:
  1. Edit /etc/dhcp/dhcpd.conf:
  2. Uncomment authoritative
  3. Change option domain-name to wardroom
  4. Change option domain-name-servers to
  5. Add allow booting; and allow bootp; after the above lines (only if using network boot clients - see later)
  6. Add the following at the end of the file:
subnet netmask {
  option subnet-mask;
  option broadcast-address;
  option routers;
  option root-path "";
  filename "pxelinux.0";

The last 3 lines are only for network booting of clients. On a separate page (see link later) it is shown how to set up some network booting deskstations that will boot a network live copy of Ubunutu.

Restart the DHCP server: <code>

/etc/init.d/isc-dhcp-server restart

Install IPSet

IPSet is a program that allows sets of IP addresses to be stored within iptables rules. It is used to collate a list of clients using P2P software. IPSet consists of both a kernel module and a userspace program. The module is not yet in the kernel provided with Debian. The following will install both the userspace program and the kernel module.

aptitude install ipset ipset-source module-assistant
module-assistant auto-install ipset-source

Install specialist internet scripts

These are a variety of scripts to do traffic shaping, force users to log on, and check that the PPP link is up. Full details are available on other pages of this Wiki.

  • This program removes cached tracks from the tracking table for a particular client. When a client is registered or unregistered from the network, this makes sure the correct web pages are presented on browsing the internet, otherwise any redirects are not properly flushed.
cd /usr/local/bin
chmod +x rmtrack
  • The following checks that the PPP link is up and reconnects if it is not
cd /usr/local/bin
chmod +x test-ppp
cd /etc/init.d
chmod +x test-ppp.init
insserv test-ppp.init
  • The next 3 show the current internet bandwidth use in classes
cd /usr/local/bin
chmod +x linkstats-ppp0
chmod +x linkstats-eth0
chmod +x tc-viewer
  • And finally the firewall which sets up all the required iptables rules including the captive portal and shaping. This downloads the scripts and forces them to run when the network is brought up.
cd /usr/local/
tar -zxvf portalshaper-sh.tar.gz
rm portalshaper-sh.tar.gz
  • Edit /usr/local/portal/settings as required

The scripts within /usr/local/portal can be edited as required. Load balancing is enabled by default, but will obviously make no difference for only one interface.

  • If using a second ADSL line, create a new file in /etc/ppp/peers editing as required. The following is an example:


  • Add the associated entry into /etc/ppp/chap-secrets
  • Create a routing table for each interface (2 in this case):

echo '101     balance1' >> /etc/iproute2/rt_tables
echo '102     balance2' >> /etc/iproute2/rt_tables

The following are some further optional examples:

  • To add a second independent ethernet interface:

Use the script at

And add it to the “master” script just after the captive-portal entry

Connecting automatically using /etc/network/interfaces

  • Edit /etc/network/interfaces adding the following:
auto ppp0
iface ppp0 inet ppp
        pre-up /etc/network/solos-preload solos-pci0
        provider isp0
        post-up /usr/local/portalshaper/master
  • If using a second interface add it as well:
auto ppp1
iface ppp1 inet ppp
        pre-up /etc/network/solos-preload solos-pci1
        provider isp1
        post-up /usr/local/portalshaper/master
  • Add pre-connection helper script (will need editing if using a speedtouch modem):
cd /etc/network/
chmod +x solos-preload
  • Disconnect the current connection:

killall pppd

  • Connect using ifup:

ifup ppp0

Update sudoers file

  • Run visudo and add the following lines. Sudo is used to allow the apache web server to add and remove the needed iptables rules each time a user signs up to access the internet, as well as update the Squid session helper when displaying announcement pages
www-data ALL = NOPASSWD: /sbin/iptables -I internet 1 -t nat -m time --datestop ??????????????????? -m mac --mac-source ??\:??\:??\:??\:??\:?? -j RETURN
www-data ALL = NOPASSWD: /sbin/iptables -D internet -t nat -m time --datestop ??????????????????? -m mac --mac-source ??\:??\:??\:??\:??\:?? -j RETURN
www-data ALL = NOPASSWD: /usr/local/bin/rmtrack [0-9]*.[0-9]*.[0-9]*.[0-9]*
www-data ALL = (proxy) NOPASSWD: /usr/lib/squid3/ext_session_acl

Note: sudo does not use regular expressions, so the last statement is not as accurate as it should be

Configure Squid

Squid is configured to show splash page announcements and mark packets for traffic shaping. Both of these require recent patches which are only contained in the latest beta version of Squid. Therefore, a very recent version of Squid will need to be compiled and installed over the standard Debian build


The web proxy is used to speed up requests, as well as log all requests and show a splash page periodically.

  • Edit /etc/squid3/squid.conf
  • Add the following to the beginning of the file:
# We don't want persistent connections, otherwise lots
# of requests to the same server will look like a bulk download
server_persistent_connections off

# Add a "fake" mark. This will stop packets being routed
# incorrectly, at the early routing stages. They will be
# properly routed at the re-route stage.
qos_flows mark miss=0x1000000/0xF000000
  • Change “http_port 3128” to “http_port 3128 transparent”
  • Comment out the following lines if upgrading from v3.1:

acl manager proto cache_object
acl localhost src ::1
acl to_localhost dst ::1

  • Locate the section “INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS” and add the following rules (replacing qualso as required):
acl our_networks src

# This ACL will only allow active sessions. Sessions are made active with separate
# PHP code within the announce.php splash page
external_acl_type session_active_def concurrency=100 ttl=3 %SRC /usr/lib/squid3/ext_session_acl -a -T 10800 -b /var/lib/squid/session/
acl session_is_active external session_active_def

external_acl_type session_day_def ttl=60 %SRC /usr/lib/squid3/ /var/www/announce_days.txt
acl session_day external session_day_def

acl images urlpath_regex -i (\.gif$|\.jpg$|\.png$|\.jpeg$)

deny_info http://qualso.wardroom/announce.php?url=%u session_day session_is_active images
http_access deny session_day !session_is_active !images
http_access allow our_networks
  • Create a session database. This is used to display the splash pages periodically. The associated /var/www/announce_days.txt file should be created when the web files are installed.
mkdir -p /var/lib/squid/session
chown proxy:proxy /var/lib/squid/session/
  • Install the date/time external ACL helper:

cd /usr/lib/squid3/
wget ''%%''
chmod +x

  • Restart squid with /etc/init.d/squid3 restart

Set up a software RAID (optional)

If you have 2 hard drives, use the steps in the following website to set up a software RAID:

Set up a USB memory stick for MYSQL backup (optional)

  • Install autofs:

apt-get install autofs udev

  • Create a mount area:

mkdir /mnt/usb

  • Plug the USB memory stick in and find its UUID:

udevadm info --query all --path /sys/block/sdc/sdc1/ |grep UUID

  • Edit /etc/auto.master and add:

/mnt/usb   /etc/auto.removable --timeout=2,sync,nodev,nosuid

  • Create the file /etc/auto.removable and add (replacing UUID):

backupusb             -fstype=auto       UUID=c9a095d8-c867-496b-98d4-d09c5c7f109f

  • Restart autofs:

/etc/init.d/autofs restart

Whenever the USB stick is pugged in, it will be mounted in /mnt/usb/backupusb

  • Create the file /root/backup.cnf for the mysql loging details:


  • Run crontab -e and add the following line:

0 12 * * * /usr/bin/mysqldump --defaults-extra-file=/root/backup.cnf --lock-tables portal > /mnt/usb/backupusb/portal-`/bin/date +\%a`.sql

Set up a local mail server to forward mail through using Postfix and ISP smarthost (optional)

Performing this step allows any user on the network to send mail through the server. By creating the setup shown below, any user wishing to send mail from their PC on the network will have to set up their mail client to authenticate with the server before they can send.

The setup as shown will configure postfix as a smarthost, sending email to the ISP's mail server. This is preferable to sending email directly, as it is fairly likely that the IP address of the ADSL connection will be blacklisted.

  • apt-get install postfix (this will remove Exim)
  • When prompted, select “Internet with smarthost”
  • Enter the FQDN of the server (eg. qualso.wardroom)
  • Enter the server name of the ISP to relay mail through
  • Install the SASL libraries: apt-get install libsasl2-modules
  • Create a file /etc/postfix/relay_passwd with the following contents, replacing values as required: USERNAME:PASSWORD
  • Change the permissions on the file:
chown root:root /etc/postfix/relay_passwd  
chmod 600 /etc/postfix/relay_passwd  
  • Setup the files hash:
postmap /etc/postfix/relay_passwd
  • Edit /etc/postfix/ and add the following lines below the relayhost option:
smtp_sasl_auth_enable = yes  
smtp_sasl_password_maps = hash:/etc/postfix/relay_passwd  
smtp_sasl_security_options =
  • Edit /etc/mailname and set a valid FQDN (eg. This will be the default mail domain for mail sent from the server.
  • If you want to allow local network users to send email without authentication, then just edit /etc/postfix/ and add to the “mynetworks” configuration line

If you want to force people to authenticate, then:

  • Add a linux local user to the system with appropriate password. Users will use this account to authenticate against the SMTP server:
useradd -g users mailuser
passwd mailuser
  • After adding the user edit /etc/passwd and add /bin/false on the end of the line for the new user. This will stop people logging into the server using that username and password!
  • Setup SASL authentication using the steps detailed at SMTP authentication and Postfix

In use

  • Any user connecting to the Internet will be presented with a sign up page before given access
  • Bandwidth stats can be viewed with either the commands iptraf or linkstats
  • Users and splash pages can be managed using http://qualso.wardroom/admin.php

Setting up network bootable live deskstations for internet browsing

The page here shows how to set up an image on the server for any deskstation to network boot from. The great advantage of this is that each time a user has used the deskstation in question, the PC can be rebooted and the operating system will effectively be 're-installed'. Very low maintenance! Each time a user closes the firefox web browser, they will be presented with a single-click 'I agree to the terms and conditions' screen.

setting_up_a_captive_portal_from_scratch_using_debian.txt · Last modified: 2018/12/06 20:16 by abeverley