Wednesday, 27 January 2016

Creating a captive portal on the raspberry pi that functions separately to the ethernet connection using a Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

I wanted to add a USB WiFi dongle to my Raspberry Pi to allow connection to it with a mobile phone, and to display a status page in the browser, but I didn't want to bridge the WiFi network to the internet, so that I didn't have to worry about unauthorised people accessing the internet through my WiFi connection. I also didn't want to disconnect the Raspberry Pi from the internet completely, as it it "phones home" to my server occasionally so that I know it is still running, and by leaving the ethernet connection functioning fully, it also allows me to update the Rasbperry Pi or make changes to the software.

Most of the tutorials on the internet for setting up a wireless access point (AP) are assuming that it will done with the connection to the internet. This is not the case for me, and so by some trial and error, and following a few different guides, I have finally found a working solution.

The first step was to understand the hardware that I had. Using the command "lsusb" lists the USB devices that are connected. By entering the command, then connecting the USB WiFi dongle, and entering the command again it is easy to see what has changed. For my dongle, I get the following information:

Bus 001 Device 005: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter


The identifying string is RTL8188CUS and googling this shows some issues with the driver when trying to connect it to the raspberry pi.

First of all, I got the dongle working as an access point with the correct driver. To do this, I followed the excellent tutorial by Dave Conroy. The tutorial can be found here: http://www.daveconroy.com/turn-your-raspberry-pi-into-a-wifi-hotspot-with-edimax-nano-usb-ew-7811un-rtl8188cus-chipset/

I already had the raspberry pi running correctly, so I started with the "Prerequsites" section. The first command to install two packages is as follows:

sudo apt-get install bridge-utils hostapd
With this command, both bridge-utils and hostapd were installed. I don't think bridge-utils was needed, but I left the command incase there are any changes made by this package that weren't immediately apparent.

The next set of commands were copied verbatim from Dave's Blog. He hosts a replacement hostapd binary which resolves the incompatibilities with the WiFi dongle chipset. This can be downloaded and installed with the following commands:

wget http://www.daveconroy.com/wp3/wp-content/uploads/2013/07/hostapd.zip
unzip hostapd.zip
sudo mv /usr/sbin/hostapd /usr/sbin/hostapd.bak
sudo mv hostapd /usr/sbin/hostapd.edimax
sudo ln -sf /usr/sbin/hostapd.edimax /usr/sbin/hostapd
sudo chown root.root /usr/sbin/hostapd
sudo chmod 755 /usr/sbin/hostapd

The above commands will replace the standard hostapd binaries with new updated ones from the zip file that are compatible with out WiFi dongle driver.

The section on "Bridging the Connections", I skipped entirely, as I want the ethernet and Wifi networks to be separate. I skipped to the section "Configuring Hostapd". Here to enter the file editor, enter the command:

sudo nano /etc/hostapd/hostapd.conf

Then there is some recommended entries for the file, however I modified this somewhat. My version of the file is as follows:

interface=wlan0
driver=rtl871xdrv
#bridge=br0
ssid=NETWORKNAME
channel=6
wmm_enabled=0
#wpa=1
#wpa_passphrase=ConroyPi
#wpa_key_mgmt=WPA-PSK
#wpa_pairwise=TKIP
#rsn_pairwise=CCMP
#auth_algs=1
#macaddr_acl=0
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0


The hash (#) character represents a comment for the entire line, and so the line is skipped over. I have commented out the section to do with security as I want the hotspot to work without authentication. This is also why I wanted to separate the two networks and not bridge them. The last two lines were added in from a separate tutorial, which I will link to shortly.

The next step was to reboot, and then test the configruation using the following command:

sudo hostapd -dd /etc/hostapd/hostapd.conf

Then I checked with a WiFi enabled device and found my network SSID. This allowed me to connect, however requesting a website failed - which for me was a success!

Now I started to Google further for how to make a captive portal, and found a guide on the website sirlagz.net, here: http://sirlagz.net/2013/08/23/how-to-captive-portal-on-the-raspberry-pi/ - This guide also has several previous steps on setting up the access point. So I went back to the access point guide and reviewed this to make sure I hadn't missed any prerequisits here also. This guide is linked here: http://sirlagz.net/2012/08/09/how-to-use-the-raspberry-pi-as-a-wireless-access-pointrouter-part-1/

Something that I hadn't done yet was to assign a static IP. To do this, enter the following command;

sudo nano /etc/network/interfaces

This opens the text editor for the network interfaces. Then further down the file, there should be an entry for wlan0. Change the entry so that the settings are as follows:

iface wlan0 inet static
address 10.0.0.1
netmask 255.255.255.0

My complete interfaces file is as follows:


# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpcd# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:source-directory /etc/network/interfaces.d
auto loiface lo inet loopback
iface eth0 inet manual
allow-hotplug wlan0iface wlan0 inet staticaddress 10.0.0.1netmask 255.255.255.0#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
allow-hotplug wlan1iface wlan1 inet manual    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf


Note once again, a hash at the beginning of the line indicates the line is commented. Next the hostapd file needs to be set. To do this, open the file with the following command:

/etc/default/hostapd

And find the line with the following text:

DAEMON_CONF=""


This needs to be modified so that it refers to the location of the .conf file, so it should appear as follows:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

Then the access point tutorial talks more  about changing the hostapd.conf file, but we did this earlier. Also there is some changes to the WiFi settings, but these are also okay. Finally we need to install dnsmasq. The tutorial I followed mentions that this is to handle the issuing of IP addresses.

To install the package, run the following command;

apt-get install dnsmasq

Then we need to edit the .conf configutation file. To open that use the command;

sudo nano /etc/dnsmasq.conf

This is a huge file, and we need to scroll right to the bottom. The keyboard shortcut ctrl+v scrolls down one page at a time, which is faster than the arrow keys going one line at a time. At the bottom add the following lines:

interface=wlan0
dhcp-range=10.0.0.2,10.0.0.250,255.255.255.0,12h
address=/#/10.0.0.1

For my file, it looked like everything else was commented out. It is a long file and I didn't look so closely, but if everything else is commented out this shouldn't actually need to be at the bottom of the file. Anyway, the line configures the wlan0 interface and sets the range of IPs that can be given out. In the original tutorial, this is a much smaller range, I expanded this to cover more IPs. The last line is taken from the final tutorial that I followed, which redirects all requests to 10.0.0.1. This is the IP address of the raspberry pi on the wlan0 interface, as set earlier on in the /etc/network/interfaces file, and must match this IP. So now after saving the file, any traffic on the wlan0 network should be redirected to the raspberry pi.

The final tutorial that I followed is also from sirlagz.net, and is linked here: http://sirlagz.net/2013/08/23/how-to-captive-portal-on-the-raspberry-pi/ and talks about setting up the captive portal. The only real change to be made was changing the last line of the dnsmasq.conf file, as done a few lines above.

Now the only remaining thing to do is to install a webserver. The server suggested in the sirlagz tutorial was lighttpd, which I have also used at the moment. To install this, use the following command:

apt-get install lighttpd

Finally I restarted everything for good measure. Now connecting to the wifi network and requesting a page, redirects to the Placeholder Page for lighttpd. Success! The location for my files that are served up by the webserver is:

/var/www/html/

Within this folder, is the location that the files need to go for the webserver.

Update: I had rebooted several times along the way, and thought that the above worked fine, but trying it the next day had problems, and no longer worked correctly. There are a couple of half related issues. Pinging google.com would resolev to my local ip of 10.0.0.1, but pinging 8.8.8.8 for example would fail completely. The problem with pinging ip addresses was related to the gateway not being setup correctly. To see this, enter the command "route -n". Here, to work correctly, there needs to be an entry in the "Desitnation" column with 0.0.0.0, and with your gateway in the "Gateway" column. This wasn't working for me, and so I can use the following command to add the gateway correctly:

sudo route add default gw 192.168.100.1 eth0

Where  my gateway IP is 192.168.100.1, and the interface is eth0. I haven't yet found a way to get this to work automatically. It would be possible to add this to a script without any problems, however I don't know how the gateway could be changed to the correct IP for the network.

The second problem was with DNS lookups. To fix this, I needed to add a couple of lines to the /etc/dnsmasq.conf file. I had thought that the dnsmasq captive portal only applied to the wlan0 interface, but this doesn't appear to be the case, and it overrides traffic from all interfaces. So I made two changes. The line:

address=/#/10.0.0.1

I changed to the following:

address=/pi/10.0.0.1

This now only redirects the domain "pi" to the local server, not all addresses. I also added the following two lines to the end of the file:

server=8.8.8.8
server=8.8.4.4

This uses the Google DNS servers for DNS lookups. After running both of these commands, it should be now possible to ping google.com, and to perform updates etc. So it appears that all the settings apply to both interfaces.

Update 2: After testing on another network, it seems that the problem with the default gateway being added only occurs on one network, that is perhaps configured incorrectly, and it isn't actually a problem with the setup on the raspberry pi. I found this out by reinstalling raspbian again and not following the above steps, and leaving all of the network connection settings as the default. Then it was still not possible to connect to the internet automatically. This is strange as it wasn't previously a problem, and I never used to have the problem where it was necessary to add the gateway. However it seems something in the network has changed, which was unrelated to what I had done, but I had falsely attributed it to the steps I had taken. So the "update" comments can be ignored.


No comments:

Post a Comment