Last active
January 10, 2023 00:47
-
-
Save mpeven/e6a3d762737071bf54cf7c51c92fca43 to your computer and use it in GitHub Desktop.
iOS captive portal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Captive portal setup | |
######################################################## | |
sudo apt-get update -qq | |
sudo apt-get install -qq dnsmasq vim hostapd ufw dnsutils netstat-nat conntrack nginx php5 php5-common php5-fpm | |
sudo mkdir /usr/share/nginx/html/portal | |
sudo useradd nginx | |
sudo chown nginx:www-data /usr/share/nginx/html/portal | |
sudo chmod 755 /usr/share/nginx/html/portal | |
######################################################## | |
############### Update network interfaces ############## | |
cat << EOF > /etc/network/interfaces | |
source-directory /etc/network/interfaces.d | |
auto lo | |
iface lo inet loopback | |
iface eth0 inet static | |
address 10.10.0.1 | |
netmask 255.255.255.0 | |
network 10.10.0.0 | |
allow-hotplug wlan1 | |
iface wlan1 inet manual | |
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf | |
auto wlan0 | |
allow-hotplug wlan0 | |
iface wlan0 inet static | |
address 192.168.5.1 | |
netmask 255.255.255.0 | |
network 192.168.5.0 | |
EOF | |
######################################################## | |
################## Setup hostapd ####################### | |
cat << EOF > /etc/hostapd/hostapd.conf | |
interface=wlan0 | |
driver=nl80211 | |
ssid=_wingnet-wifi_ | |
channel=9 | |
EOF | |
######################################################## | |
########## make hostapd use new conf file ############## | |
sudo sed -i 's;\#DAEMON_CONF="";DAEMON_CONF="/etc/hostapd/hostapd.conf";' /etc/default/hostapd | |
######################################################## | |
################ Setup dhcpd.conf ################### | |
sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.default | |
cat << EOF > /etc/dhcp/dhcpd.conf | |
default-lease-time 600; | |
max-lease-time 7200; | |
option subnet-mask 255.255.255.0; | |
option broadcast-address 192.168.5.255; | |
option routers 192.168.5.1; | |
option domain-name-servers 192.168.5.1; | |
option domain-name "localdomain"; | |
subnet 192.168.5.0 netmask 255.255.255.0 { | |
range 192.168.5.10 192.168.5.100; | |
} | |
EOF | |
######################################################## | |
######### setup isc-dhcp-server INTERFACE ############## | |
sudo sed -i 's;\INTERFACES="";INTERFACES="wlan0 eth0";' /etc/default/isc-dhcp-server | |
######################################################## | |
############## Setup dnsmasq.conf ##################### | |
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig | |
cat << EOF > /etc/dnsmasq.conf | |
address=/#/192.168.5.1 | |
listen-address=127.0.0.1,192.168.5.1 | |
port=53 | |
bind-interfaces # Bind to wifi interface | |
server=8.8.8.8 # Forward DNS requests to Google DNS | |
no-poll | |
bogus-priv # Never forward addresses in the non-routed address spaces. | |
neg-ttl=3600 | |
cache-size=1000 | |
dns-forward-max=150 | |
domain-needed # Don't forward short names | |
EOF | |
######################################################## | |
############### Setup dhclient.conf #################### | |
# This prevents the INTERNET connection to change our local DNS server | |
sed -i 's/domain-name, domain-name-servers, domain-search, host-name,/host-name,/' /etc/dhcp/dhclient.conf | |
######################################################## | |
######################## UFW ########################### | |
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf | |
sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" | |
sed -i 's/IPV6=yes/IPV6=no/' /etc/default/ufw | |
sed -i 's/DEFAULT_INPUT_POLICY="DROP"/DEFAULT_INPUT_POLICY="ACCEPT"/' /etc/default/ufw | |
sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw | |
sed -i 's/ENABLED=no/ENABLED=yes/' /etc/ufw/ufw.conf | |
sed -i 's;\#net/ipv4/ip_forward=1;net/ipv4/ip_forward=1;' /etc/ufw/sysctl.conf | |
cat >> /etc/ufw/before.rules << EOF | |
# NAT table rules | |
*nat | |
:POSTROUTING ACCEPT [0:0] | |
# Forward traffic through wlan1 - Change to match you out-interface | |
-A POSTROUTING -s 192.168.5.0/24 -o wlan1 -j MASQUERADE | |
# don't delete the 'COMMIT' line or these nat table rules won't | |
# be processed | |
COMMIT | |
EOF | |
######################################################## | |
################### Setup nginx ######################## | |
sudo cat << EOF > /etc/nginx/sites-available/hotspot.conf | |
server { | |
# Listening on IP Address. | |
# This is the website iptables redirects to | |
listen 80 default_server; | |
root /usr/share/nginx/html/portal/; | |
index hotspot.html index.php; | |
# For iOS | |
if (\$http_user_agent ~* (CaptiveNetworkSupport) ) { | |
return 302 http://hotspot.localnet/hotspot.html; | |
} | |
# For others | |
location / { | |
return 302 http://hotspot.localnet/; | |
} | |
} | |
upstream php { | |
#this should match value of "listen" directive in php-fpm pool | |
server unix:/tmp/php-fpm.sock; | |
server 127.0.0.1:9000; | |
} | |
server { | |
listen 80; | |
server_name hotspot.localnet; | |
root /usr/share/nginx/html/portal; | |
index index.html index.php; | |
# Pass all .php files onto a php-fpm/php-fcgi server. | |
location ~ [^/]\.php(/|\$) { | |
fastcgi_split_path_info ^(.+?\.php)(/.*)$; | |
if (!-f \$document_root\$fastcgi_script_name) { | |
return 404; | |
} | |
# This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default) | |
include fastcgi_params; | |
fastcgi_index index.php; | |
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; | |
fastcgi_pass php; | |
} | |
} | |
EOF | |
sudo rm /etc/nginx/sites-available/default | |
sudo rm /etc/nginx/sites-enabled/default | |
sudo ln -s /etc/nginx/sites-available/hotspot.conf /etc/nginx/sites-enabled/hotspot.conf | |
sudo systemctl reload nginx | |
######################################################## | |
######################################################## | |
sudo touch /usr/share/nginx/html/portal/index.php | |
sudo cat << EOF > /usr/share/nginx/html/portal/index.php | |
<!DOCTYPE html> | |
<?php | |
// Grant access if the Security code is accurate. | |
if ($_POST['security_code'] == "andrew-wippler-is-cool") { | |
// Grab the MAC address | |
$arp = "/usr/sbin/arp"; // Attempt to get the clients mac address | |
$mac = shell_exec("$arp -a ".$_SERVER['REMOTE_ADDR']); | |
preg_match('/..:..:..:..:..:../',$mac , $matches); | |
$mac2 = $matches[0]; | |
// Reconnect the device to the firewall | |
exec("sudo rmtrack " . $_SERVER['REMOTE_ADDR']); | |
$i = "sudo iptables -t mangle -A wlan0_Outgoing -m mac --mac-source ".$_GET['mac']." -j MARK --set-mark 2"; | |
exec($i); | |
sleep(5); | |
?> <html> | |
<head> | |
<title></title> | |
</head> | |
<body> | |
<h1>You are now free to browse the internet.</h1> | |
</body> </html> | |
<?php } else { | |
// this is what is seen when first viewing the page | |
?> | |
<html> | |
<head> | |
<title></title> | |
</head> | |
<body> | |
<h1>Authorization Required</h1> | |
<p>Before continuing, you must first agree to the <a href="#">Terms of Service</a> and be of the legal age to do that in your selective country or have Parental Consent. | |
</p> | |
<form method="post" action="index.php"> | |
<input type="hidden" name="security_code" value="andrew-wippler-is-cool" /> | |
<input type="checkbox" name="checkbox1" CHECKED /><label for="checkbox1">I Agree to the terms</label><br /> | |
<input type="submit" value="Connect" /> | |
</form> | |
</body> </html> | |
<?php } ?> | |
EOF | |
######################################################## | |
######################################################## | |
sudo touch /usr/share/nginx/html/portal/hotspot.html | |
sudo cat << EOF > /usr/share/nginx/html/portal/hotspot.html | |
<!-- | |
<?xml version="1.0" encoding="UTF-8"?> | |
<WISPAccessGatewayParam xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.wballiance.net/wispr_2_0.xsd"> | |
<Redirect> | |
<MessageType>100</MessageType> | |
<ResponseCode>0</ResponseCode> | |
<VersionHigh>2.0</VersionHigh> | |
<VersionLow>1.0</VersionLow> | |
<AccessProcedure>1.0</AccessProcedure> | |
<AccessLocation>Andrew Wippler is awesome</AccessLocation> | |
<LocationName>MyOpenAP</LocationName> | |
<LoginURL>http://hotspot.localnet/</LoginURL> | |
</Redirect> | |
</WISPAccessGatewayParam> | |
--> | |
EOF | |
######################################################## | |
############## Change what runs on boot ################ | |
sudo rm /etc/rc.local | |
sudo touch /etc/rc.local | |
sudo chmod +x /etc/rc.local | |
cat << EOF > /etc/rc.local | |
#!/bin/sh -e | |
sudo /etc/init.d/hostapd stop && sudo /etc/init.d/hostapd start | |
sudo /etc/init.d/dnsmasq stop && sudo /etc/init.d/dnsmasq start | |
sudo /etc/init.d/nginx stop && sudo /etc/init.d/nginx start | |
exit 0 | |
EOF | |
######################################################## | |
###################### Reboot ########################## | |
echo "press any key to reboot" | |
read reboot_key | |
sudo shutdown -r now | |
######################################################## |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hi, i have 2 questions:
1/ is it possible to update it to be working on Raspberry3 debian?
2/ is it possible to keep captive portal functionnal even when ethernet cable is unplugged (no internet connection)?