androidapache2raspberry-pi3dnsmasqcaptiveportal

Captive Portal for Android Phone did not pop up


I used hostapd, dnsmasq and apache2 for implementing the wifi-hotspot with captive portal on my Raspberry Pi 3B+, before I implement this project, I have never get in touch with wifi networks. Hence I search a lot of post on how to implement one.

Below is the configuration I used:

/etc/apache/apache.conf:

# Apple
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} ^CaptiveNetworkSupport(.*)$ [NC]
RewriteCond %{HTTP_HOST} !^192.168.0.200$
RewriteRule ^(.*)$ http://192.168.0.200/index.html [L,R=302]

# Android
RedirectMatch 302 /generate_204 http://192.168.0.200/index.html

# All
RewriteCond %{REQUEST_URI} !=/index.html
RewriteRule ^(.*)$ http://192.168.0.200/index.html [L]

# 404 Redirect
ErrorDocument 404 http://192.168.0.200/index.html

/etc/dnsmasq.conf:

interface=wlan0
dhcp-range=192.168.0.201,192.168.0.210,255.255.255.0,24h
address=/#/192.168.0.200

I used Sony H4133, HUAWEI RNE-22, Redmi Note3, Samsung Galaxy S8+, Samsung Galaxy Tab S to test the portal. Only the Sony one work like a charm. Tab S can pop up a notification but when I click on it, it send me to google.com but not my portal. While others didn't even show the pop up.

I checked the access.log and find that the /generate_204 indeed 302 redirect to my page and return a 200 code. According to my research, any code return other than 204 should show up the pop up, but why it is not the case here?

access.log:

192.168.0.204 - - [04/Jan/2020:12:20:10 +0800] "GET /index.html HTTP/1.1" 200 899 "-" "MQ 3.3.8/3.0 (Android 6.0.1) Xiaomi Redmi Note 3"
192.168.0.204 - - [04/Jan/2020:12:20:11 +0800] "GET /generate_204 HTTP/1.1" 302 561 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:15 +0800] "POST /getconfig HTTP/1.1" 302 531 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:15 +0800] "GET /index.html HTTP/1.1" 200 862 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:15 +0800] "POST /mistats/v2 HTTP/1.1" 302 531 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:15 +0800] "GET /index.html HTTP/1.1" 200 862 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:20 +0800] "POST /mistats/v2 HTTP/1.1" 302 531 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"
192.168.0.204 - - [04/Jan/2020:12:20:20 +0800] "GET /index.html HTTP/1.1" 200 862 "-" "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Redmi Note 3 MIUI/V10.2.1.0.MHOMIXM)"



192.168.0.205 - - [04/Jan/2020:12:23:31 +0800] "GET /generate_204 HTTP/1.1" 302 570 "-" "Dalvik/2.1.0 (Linux; U; Android 8.0.0; RNE-L22 Build/HUAWEIRNE-L22)"
192.168.0.205 - - [04/Jan/2020:12:23:31 +0800] "GET /generate_204 HTTP/1.1" 302 560 "-" "Dalvik/2.1.0 (Linux; U; Android 8.0.0; RNE-L22 Build/HUAWEIRNE-L22)"
192.168.0.205 - - [04/Jan/2020:12:23:31 +0800] "GET /generate_204 HTTP/1.1" 302 560 "-" "Dalvik/2.1.0 (Linux; U; Android 8.0.0; RNE-L22 Build/HUAWEIRNE-L22)"
192.168.0.205 - - [04/Jan/2020:12:23:44 +0800] "GET /generate_204 HTTP/1.1" 302 570 "-" "Dalvik/2.1.0 (Linux; U; Android 8.0.0; RNE-L22 Build/HUAWEIRNE-L22)"
192.168.0.205 - - [04/Jan/2020:12:23:56 +0800] "GET /generate_204 HTTP/1.1" 302 570 "-" "Dalvik/2.1.0 (Linux; U; Android 8.0.0; RNE-L22 Build/HUAWEIRNE-L22)"

Solution

  • apache.conf is your problem. Config Apache2 in another way.
    Every operating system has its own different way of detecting Internet access.

    The mechanism is this basically:

    GET/POST http://x.com/bar.html
    If bar.html == [expected content] > Open Internet
    If bar.html != [expected content] > Captive Portal
    If bar.html[status] != SUCCESS > No Network  
    

    Each device, also Android different manufactures, behaves differently. For example, look at this list:

    xperia z5:
    connectivitycheck.gstatic.com:80
    clients3.google.com:80
    ---------------------
    galaxy j3 2016:
    172.217.21.14:80    connectivitycheck.android.com
    ---------------------
    galaxy j7 2015:
    172.16.98.10:80
    connectivitycheck.gstatic.com:80
    ---------------------
    galaxy note4:
    nothing!
    ---------------------
    ios 11:
    captive.apple.com/hotspot-detect.html
    ---------------------
    windows 10:
    www.msftconnecttest.com
    

    I suggest make another apache config file for each device/manufacture.


    Create a directory for android in apache

    cd /var/www/html/
    sudo mkdir android 
    

    Create a simple index.html file that is going to appear on the splash page of the android device.

    Create android.conf in nano (or your favorite text editor) and copy the following code to create a "redirection rule" for Android devices.

    sudo nano /etc/apache2/sites-enabled/android.conf  
    

    Put these lines:

    <VirtualHost *:80>
    
        Servername connectivitycheck.gstatic.com
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/android
    
        RedirectMatch 302 /generate_204 /index.html
    
        ErrorLog ${APACHE_LOG_DIR}/android_error.log
        CustomLog ${APACHE_LOG_DIR}/android_access.log combined
    
    </VirtualHost>
    

    Save file and exit.

    Done. Follow the procedure for other devices. Also, check this link out to get more information.