sudo apt-get update
sudo apt-get upgrade
sudo apt-get install hostapd
sudo apt-get install dnsmasq
sudo systemctl stop hostapd
sudo systemctl stop dnsmasq
sudo nano /etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.24.1/24
then
sudo systemctl daemon-reload && sudo systemctl restart dhcpcd
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo nano /etc/dnsmasq.conf
or
sudo cat << EOF > /etc/dnsmasq.conf
bogus-priv
server=/localnet/192.168.24.1
local=/localnet/
interface=wlan0
domain=localnet
dhcp-range=192.168.24.10,192.168.24.254,255.255.255.0,2h
EOF
sudo nano /etc/hostapd/hostapd.conf
or
sudo << EOF > /etc/hostapd/hostapd.conf
interface=wlan0
ssid=MyOpenAP
hw_mode=g
channel=6
auth_algs=1
wmm_enabled=0
EOF
sudo nano /etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"
sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1
or
sudo echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sudo apt-get install iptables-persistent conntrack nginx php php-common php-fpm
sudo nano /etc/hosts
192.168.24.1 hotspot.localnet
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
#Turn into root
sudo -i
#Flush all connections in the firewall
iptables -F
#Delete all chains in iptables
iptables -X
#wlan0 is our wireless card. Replace with your second NIC if doing it from a server.
#This will set up our structure
iptables -t mangle -N wlan0_Trusted
iptables -t mangle -N wlan0_Outgoing
iptables -t mangle -N wlan0_Incoming
iptables -t mangle -I PREROUTING 1 -i wlan0 -j wlan0_Outgoing
iptables -t mangle -I PREROUTING 1 -i wlan0 -j wlan0_Trusted
iptables -t mangle -I POSTROUTING 1 -o wlan0 -j wlan0_Incoming
iptables -t nat -N wlan0_Outgoing
iptables -t nat -N wlan0_Router
iptables -t nat -N wlan0_Internet
iptables -t nat -N wlan0_Global
iptables -t nat -N wlan0_Unknown
iptables -t nat -N wlan0_AuthServers
iptables -t nat -N wlan0_temp
iptables -t nat -A PREROUTING -i wlan0 -j wlan0_Outgoing
iptables -t nat -A wlan0_Outgoing -d 192.168.24.1 -j wlan0_Router
iptables -t nat -A wlan0_Router -j ACCEPT
iptables -t nat -A wlan0_Outgoing -j wlan0_Internet
iptables -t nat -A wlan0_Internet -m mark --mark 0x2 -j ACCEPT
iptables -t nat -A wlan0_Internet -j wlan0_Unknown
iptables -t nat -A wlan0_Unknown -j wlan0_AuthServers
iptables -t nat -A wlan0_Unknown -j wlan0_Global
iptables -t nat -A wlan0_Unknown -j wlan0_temp
#forward new requests to this destination
iptables -t nat -A wlan0_Unknown -p tcp --dport 80 -j DNAT --to-destination 192.168.24.1
iptables -t nat -A wlan0_Unknown -p tcp --dport 443 -j DNAT --to-destination 192.168.24.1
# attemp for vpn blocking
iptables -t nat -A wlan0_Unknown -p tcp --dport 1194 -j DNAT --to-destination 192.168.24.1
iptables -t nat -A wlan0_Unknown -p udp --dport 1194 -j DNAT --to-destination 192.168.24.1
iptables -t filter -N wlan0_Internet
iptables -t filter -N wlan0_AuthServers
iptables -t filter -N wlan0_Global
iptables -t filter -N wlan0_temp
iptables -t filter -N wlan0_Known
iptables -t filter -N wlan0_Unknown
iptables -t filter -I FORWARD -i wlan0 -j wlan0_Internet
iptables -t filter -A wlan0_Internet -m state --state INVALID -j DROP
iptables -t filter -A wlan0_Internet -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t filter -A wlan0_Internet -j wlan0_AuthServers
iptables -t filter -A wlan0_AuthServers -d 192.168.24.1 -j ACCEPT
iptables -t filter -A wlan0_Internet -j wlan0_Global
#allow access to my website :)
iptables -t filter -A wlan0_Global -d walledgardensite.com -j ACCEPT
#allow unrestricted access to packets marked with 0x2
iptables -t filter -A wlan0_Internet -m mark --mark 0x2 -j wlan0_Known
iptables -t filter -A wlan0_Known -d 0.0.0.0/0 -j ACCEPT
iptables -t filter -A wlan0_Internet -j wlan0_Unknown
# attemp for vpn blocking
iptables -A FORWARD -m state --state NEW,ESTABLISHED,RELATED -d wlan0_Unknown -j REJECT
iptables -A FORWARD -m state --state NEW,ESTABLISHED,RELATED -d wlan0_Internet -j REJECT
#allow access to DNS and DHCP
#This helps power users who have set their own DNS servers
iptables -t filter -A wlan0_Unknown -d 0.0.0.0/0 -p udp --dport 53 -j ACCEPT
iptables -t filter -A wlan0_Unknown -d 0.0.0.0/0 -p tcp --dport 53 -j ACCEPT
iptables -t filter -A wlan0_Unknown -d 0.0.0.0/0 -p udp --dport 67 -j ACCEPT
iptables -t filter -A wlan0_Unknown -d 0.0.0.0/0 -p tcp --dport 67 -j ACCEPT
iptables -t filter -A wlan0_Unknown -j REJECT --reject-with icmp-port-unreachable
#allow forwarding of requests from anywhere to eth0/WAN
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
#save our iptables
iptables-save > /etc/iptables/rules.v4
mkdir /usr/share/nginx/html/portal
chown www-data:www-data /usr/share/nginx/html/portal
chmod 755 /usr/share/nginx/html/portal
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;
# 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/php7.4-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.htm index.php;
location / {
try_files $uri $uri/ index.php;
}
#Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
}
EOF
ln -s /etc/nginx/sites-available/hotspot.conf /etc/nginx/sites-enabled/hotspot.conf
systemctl reload nginx
sudo nano /usr/share/nginx/html/portal/index.php
or
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 client's 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 ".$mac2." -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 nano /usr/share/nginx/html/portal/hotspot.html
or
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
sudo nano /usr/share/nginx/html/portal/kick.php
or
sudo cat << EOF > /usr/share/nginx/html/portal/kick.php
<?php
// get the user IP address from the query string
$ip = $_REQUEST['ip'];
// this is the path to the arp command used to get user MAC address
// from it's IP address in linux environment.
$arp = "/usr/sbin/arp";
// execute the arp command to get their mac address
$mac = shell_exec("sudo $arp -an " . $ip);
preg_match('/..:..:..:..:..:../',$mac , $matches);
$mac = @$matches[0];
// if MAC Address couldn't be identified.
if( $mac === NULL) {
echo "Error: Can't retrieve user's MAC address.";
exit;
}
print_r($matches);
// Delete it from iptables bypassing rules entry.
while( $chain = shell_exec("sudo iptables -t mangle -L | grep ".strtolower($mac) ) !== NULL ) {
echo exec("sudo iptables -D internet -t mangle -m mac --mac-source ".strtolower($mac)." -j RETURN");
}
// Why in this while loop?
// Users may have been logged through the portal several times.
// So they may have chances to have multiple bypassing rules entry in iptables firewall.
// remove their connection track.
echo exec("sudo rmtrack " . $ip); // remove their connection track if any
echo "Kickin' successful.";
?>
EOF
sudo chown -R www-data:www-data /usr/share/nginx/html/portal/
sudo nano /usr/bin/rmtrack
/usr/sbin/conntrack -L \
|grep $1 \
|grep ESTAB \
|grep 'dport=80' \
|awk \
"{ system(\"conntrack -D --orig-src $1 --orig-dst \" \
substr(\$6,5) \" -p tcp --orig-port-src \" substr(\$7,7) \" \
--orig-port-dst 80\"); }"
sudo chmod +x /usr/bin/rmtrack
sudo visudo
www-data ALL=NOPASSWD: /usr/sbin/arp
www-data ALL=NOPASSWD: /usr/bin/rmtrack [0-9]*.[0-9]*.[0-9]*.[0-9]*
www-data ALL=NOPASSWD: /sbin/iptables, /usr/bin/du
www-data ALL=NOPASSWD: /sbin/iptables -t mangle -L | grep ??\:??\:??\:??\:??\:??
www-data ALL=NOPASSWD: /sbin/iptables -t mangle -A wlan0_Outgoing -m mac --mac-source ??\:??\:??\:??\:??\:?? -j MARK --set-mark 2
www-data ALL=NOPASSWD: /sbin/iptables -t mangle -D wlan0_Outgoing -m mac --mac-source ??\:??\:??\:??\:??\:?? -j MARK --set-mark 2
sudo iptables -L -t mangle --line-numbers
sudo /usr/bin/getusr
sudo iptables -L -t mangle | GREP $1
sudo chmod +x /usr/bin/getusr
nginx -t
ip a
iptables -L
iptables -S
rfkill list all
sudo rfkill unblock all
sudo ip link set wlan0 up
sudo iface wlan0 up
then
sudo systemctl restart dnsmasq
sudo systemctl restart hostapd
- https://github.com/thgh/pilon
- https://thepi.io/how-to-use-your-raspberry-pi-as-a-wireless-access-point/
- https://andrewwippler.com/2016/03/11/wifi-captive-portal/
- https://wiki.andybev.com/doku.php?id=using_iptables_and_php_to_create_a_captive_portal&s[]=rmtrack
- https://projectzme.wordpress.com/2012/03/19/captive-portal-using-php-and-iptables-firewall-on-linux/
- https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/157-raspberry-pi-auto-wifi-hotspot-switch-internet
- https://making.pusher.com/per-ip-rate-limiting-with-iptables/
- https://github.com/nikosft/captive-portal/blob/master/captive_portal.py