mirror of
https://github.com/YunoHost-Apps/hotspot_ynh.git
synced 2024-09-03 19:25:53 +02:00
[wip] Captive portal
This commit is contained in:
parent
e8eddb26dd
commit
5c01597490
10 changed files with 202 additions and 0 deletions
13
conf/captiveportal_fakedns.service
Normal file
13
conf/captiveportal_fakedns.service
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[Unit]
|
||||||
|
Description=YunoHost Wifi Captive Portal
|
||||||
|
Requires=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User=root
|
||||||
|
ExecStart=/usr/local/bin/captiveportal_fakedns
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -123,6 +123,20 @@ name = "Configuration"
|
||||||
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
||||||
pattern.error = "Not an ip"
|
pattern.error = "Not an ip"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal__1]
|
||||||
|
ask = "Captive portal"
|
||||||
|
type = "boolean"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__1"
|
||||||
|
help = "Activate the captive portal mode"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal_url__1]
|
||||||
|
ask = "Local captive portal URL"
|
||||||
|
type = "string"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__1 && captive_portal__1"
|
||||||
|
help = "Local URL on which redirect onto when the user mac address is not yet allowed"
|
||||||
|
|
||||||
[main.hotspot2]
|
[main.hotspot2]
|
||||||
name = "Hotspot 2"
|
name = "Hotspot 2"
|
||||||
visible = "! no_antenna && multissid >= 2"
|
visible = "! no_antenna && multissid >= 2"
|
||||||
|
@ -183,6 +197,20 @@ name = "Configuration"
|
||||||
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
||||||
pattern.error = "Not an ip"
|
pattern.error = "Not an ip"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal__2]
|
||||||
|
ask = "Captive portal"
|
||||||
|
type = "boolean"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__2"
|
||||||
|
help = "Activate the captive portal mode"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal_url__2]
|
||||||
|
ask = "Local captive portal URL"
|
||||||
|
type = "string"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__2 && captive_portal__2"
|
||||||
|
help = "Local URL on which redirect onto when the user mac address is not yet allowed"
|
||||||
|
|
||||||
[main.hotspot3]
|
[main.hotspot3]
|
||||||
name = "Hotspot 3"
|
name = "Hotspot 3"
|
||||||
visible = "! no_antenna && multissid >= 3"
|
visible = "! no_antenna && multissid >= 3"
|
||||||
|
@ -243,3 +271,17 @@ name = "Configuration"
|
||||||
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
|
||||||
pattern.error = "Not an ip"
|
pattern.error = "Not an ip"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal__3]
|
||||||
|
ask = "Captive portal"
|
||||||
|
type = "boolean"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__3"
|
||||||
|
help = "Activate the captive portal mode"
|
||||||
|
|
||||||
|
[main.hotspot1.captive_portal_url__3]
|
||||||
|
ask = "Local captive portal URL"
|
||||||
|
type = "string"
|
||||||
|
bind = "array_settings()"
|
||||||
|
visible = "advanced__3 && captive_portal__3"
|
||||||
|
help = "Local URL on which redirect onto when the user mac address is not yet allowed"
|
||||||
|
|
||||||
|
|
68
hooks/post_iptables_rules
Normal file
68
hooks/post_iptables_rules
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
multissid=$(grep multissid /etc/yunohost/apps/hotspot/settings.yml | cut -d: -f2 | sed "s/[ ']//g")
|
||||||
|
interface=$(grep wifi_device /etc/yunohost/apps/hotspot/settings.yml | cut -d: -f2 | sed "s/[ ']//g")
|
||||||
|
IFS='|' read -a captive_portal <<< "$(grep captive_portal /etc/yunohost/apps/hotspot/settings.yml | grep -v captive_portal_url | cut -d: -f2 | sed "s/[ ']//g")"
|
||||||
|
IFS='|' read -a ipv4 <<< "$(grep ip4_nat_prefix /etc/yunohost/apps/hotspot/settings.yml | cut -d: -f2 | sed "s/[ ']//g")"
|
||||||
|
IFS='|' read -a ipv6 <<< "$(grep ip6_net /etc/yunohost/apps/hotspot/settings.yml | cut -d: -f2 | sed "s/[ ']//g")"
|
||||||
|
|
||||||
|
iptables -w -N hotspot_fwd
|
||||||
|
ip6tables -w -N hotspot_fwd
|
||||||
|
for (( j=0; j<multissid; j++ ));
|
||||||
|
do
|
||||||
|
if [[ "${captive_portal[$j]}" != "1" ]]
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
for iptables_cmd in iptables ip6tables;
|
||||||
|
do
|
||||||
|
if [[ "${iptables_cmd}" == "iptables" ]]; then
|
||||||
|
ipv4=${ipv4[$j]}
|
||||||
|
if [[ "${ipv4}" == "" ]]
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
ip=$ipv4.1
|
||||||
|
subnet=$ipv4.0/24
|
||||||
|
mac_adresses=$(grep "$ipv4" /etc/hotspot/allowed.csv | cut -d, -f3)
|
||||||
|
else
|
||||||
|
ipv6=${ipv6[$j]}
|
||||||
|
if [[ "${ipv6}" == "" ]]
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
ip=$ipv6::1
|
||||||
|
subnet=$ipv6::1
|
||||||
|
mac_adresses=$(grep "$ipv6" /etc/hotspot/allowed.csv | cut -d, -f3)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allow to request 4253 port
|
||||||
|
$iptables_cmd -w -A INPUT -i $interface -m udp -p udp --dport 4253 -j ACCEPT
|
||||||
|
|
||||||
|
# Drop all packets going on external internet
|
||||||
|
$iptables_cmd -w -A hotspot_fwd -s $subnet -j DROP
|
||||||
|
|
||||||
|
# Force to use the fakeDNS
|
||||||
|
$iptables_cmd -w -A PREROUTING -i $interface -s $subnet -p udp --dport 53 -j DNAT --to-destination $ip:4253
|
||||||
|
|
||||||
|
# Make things working with DoH
|
||||||
|
# Warning: this rules to ssupport DoH let info in nginx logs on which website the user try to access...
|
||||||
|
# Only activating 80 and not 443 reduces a bit the issues.
|
||||||
|
# A better approach could be to list all ips used by domains dedicated to captive portal detection.
|
||||||
|
$iptables_cmd -w -A PREROUTING -i $interface -s $subnet -p tcp --dport 80 -j DNAT --to-destination $ip:80
|
||||||
|
#$iptables_cmd -w -A PREROUTING -i $interface -s $subnet -p tcp --dport 443 -j DNAT --to-destination $ip:443
|
||||||
|
|
||||||
|
# Maybe needed, maybe not (i din't need this when vpn is activated)
|
||||||
|
#$iptables_cmd -t nat -A POSTROUTING -o $interface -j MASQUERADE
|
||||||
|
|
||||||
|
# Allow specific mac adress to use external internet
|
||||||
|
for mac in ${mac_adresses}; do
|
||||||
|
$iptables_cmd -w -I hotspot_fwd 1 -s $subnet -m mac --mac-source $mac -j ACCEPT
|
||||||
|
$iptables_cmd -t nat -w -I PREROUTING 1 -i $interface -s $subnet -m mac --mac-source $mac -j ACCEPT
|
||||||
|
done
|
||||||
|
|
||||||
|
$iptables_cmd -w -I FORWARD 1 -i $interface -j hotspot_fwd
|
||||||
|
done
|
||||||
|
done
|
||||||
|
exit 0
|
|
@ -49,6 +49,8 @@ ynh_backup --src_path="/etc/dnsmasq.dhcpd/dhcpdv6.conf.tpl"
|
||||||
ynh_backup --src_path="/etc/dnsmasq.dhcpd/dhcpdv4.conf.tpl"
|
ynh_backup --src_path="/etc/dnsmasq.dhcpd/dhcpdv4.conf.tpl"
|
||||||
|
|
||||||
ynh_backup --src_path="/usr/local/bin/$service_name"
|
ynh_backup --src_path="/usr/local/bin/$service_name"
|
||||||
|
ynh_backup --src_path="/usr/local/bin/captiveportal_fakedns"
|
||||||
|
ynh_backup --src_path="/usr/local/bin/captiveportal_allow"
|
||||||
|
|
||||||
ynh_backup --src_path="/etc/init.d/hostapd"
|
ynh_backup --src_path="/etc/init.d/hostapd"
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ ynh_backup --src_path="/etc/init.d/hostapd"
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
||||||
ynh_backup --src_path="/etc/systemd/system/$service_name.service"
|
ynh_backup --src_path="/etc/systemd/system/$service_name.service"
|
||||||
|
ynh_backup --src_path="/etc/systemd/system/captiveportal_fakedns.service"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# END OF SCRIPT
|
# END OF SCRIPT
|
||||||
|
|
|
@ -210,6 +210,15 @@ ynh_app_config_apply() {
|
||||||
|
|
||||||
_ynh_app_config_apply
|
_ynh_app_config_apply
|
||||||
|
|
||||||
|
# Activate captive portal or not
|
||||||
|
captive_portal=$(ynh_app_setting_get --app=$app --key=captive_portal)
|
||||||
|
if [[ "$captive_portal" =~ 1 ]]
|
||||||
|
then
|
||||||
|
ynh_systemd_action --service_name=captiveportal_fakedns --action="start" --log_path=systemd
|
||||||
|
else
|
||||||
|
ynh_systemd_action --service_name=captiveportal_fakedns --action="stop" --log_path=systemd
|
||||||
|
fi
|
||||||
|
|
||||||
# Start vpn client
|
# Start vpn client
|
||||||
ynh_print_info --message="Starting hotspot service if needed"
|
ynh_print_info --message="Starting hotspot service if needed"
|
||||||
/usr/local/bin/ynh-hotspot start
|
/usr/local/bin/ynh-hotspot start
|
||||||
|
|
|
@ -143,6 +143,8 @@ ynh_app_setting_set --app=$app --key=ip6_firewall --value=1
|
||||||
ynh_app_setting_set --app=$app --key=ip6_net --value="${ip6_net}"
|
ynh_app_setting_set --app=$app --key=ip6_net --value="${ip6_net}"
|
||||||
ynh_app_setting_set --app=$app --key=dns --value="10.0.242.1"
|
ynh_app_setting_set --app=$app --key=dns --value="10.0.242.1"
|
||||||
ynh_app_setting_set --app=$app --key=ip4_nat_prefix --value=10.0.242
|
ynh_app_setting_set --app=$app --key=ip4_nat_prefix --value=10.0.242
|
||||||
|
ynh_app_setting_set --app=$app --key=captive_portal --value=0
|
||||||
|
ynh_app_setting_set --app=$app --key=captive_portal_url --value=""
|
||||||
|
|
||||||
if [[ -z $wifi_device ]]; then
|
if [[ -z $wifi_device ]]; then
|
||||||
ynh_app_setting_set --app=$app --key=service_enabled --value=0
|
ynh_app_setting_set --app=$app --key=service_enabled --value=0
|
||||||
|
@ -157,6 +159,9 @@ ynh_script_progression --message="Copying configuration files..."
|
||||||
|
|
||||||
mkdir -pm 0755 /etc/dnsmasq.dhcpd/
|
mkdir -pm 0755 /etc/dnsmasq.dhcpd/
|
||||||
chown root: /etc/dnsmasq.dhcpd/
|
chown root: /etc/dnsmasq.dhcpd/
|
||||||
|
mkdir -pm 0755 /etc/hotspot/
|
||||||
|
touch /etc/hotspot/allowed.csv
|
||||||
|
chown -R root: /etc/hotspot/
|
||||||
|
|
||||||
install -b -o root -g root -m 0644 ../conf/hostapd.*.conf /etc/hostapd/
|
install -b -o root -g root -m 0644 ../conf/hostapd.*.conf /etc/hostapd/
|
||||||
install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv6.conf.tpl /etc/dnsmasq.dhcpd/dhcpdv6.conf.tpl
|
install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv6.conf.tpl /etc/dnsmasq.dhcpd/dhcpdv6.conf.tpl
|
||||||
|
@ -164,6 +169,8 @@ install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv4.conf.tpl /etc/dnsmasq
|
||||||
|
|
||||||
# Copy init script
|
# Copy init script
|
||||||
install -o root -g root -m 0755 ../conf/$service_name /usr/local/bin/
|
install -o root -g root -m 0755 ../conf/$service_name /usr/local/bin/
|
||||||
|
install -o root -g root -m 0755 ../conf/captiveportal_fakedns /usr/local/bin/
|
||||||
|
install -o root -g root -m 0755 ../conf/captiveportal_allow /usr/local/bin/
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# CONFIGURE HOSTAPD
|
# CONFIGURE HOSTAPD
|
||||||
|
@ -193,6 +200,7 @@ ynh_script_progression --message="Configuring a systemd service..."
|
||||||
|
|
||||||
# Create a dedicated systemd config
|
# Create a dedicated systemd config
|
||||||
ynh_add_systemd_config --service=$service_name
|
ynh_add_systemd_config --service=$service_name
|
||||||
|
ynh_add_systemd_config --service=captiveportal_fakedns --template=captiveportal_fakedns
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# INTEGRATE SERVICE IN YUNOHOST
|
# INTEGRATE SERVICE IN YUNOHOST
|
||||||
|
@ -200,6 +208,7 @@ ynh_add_systemd_config --service=$service_name
|
||||||
ynh_script_progression --message="Integrating service in YunoHost..."
|
ynh_script_progression --message="Integrating service in YunoHost..."
|
||||||
|
|
||||||
yunohost service add $service_name --description "Creates a Wi-Fi access point" --test_status "systemctl is-active hostapd"
|
yunohost service add $service_name --description "Creates a Wi-Fi access point" --test_status "systemctl is-active hostapd"
|
||||||
|
yunohost service add captiveportal_fakedns --description "Captive portal dns service" --test_status "systemctl is-active captiveportal_fakedns"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# START SYSTEMD SERVICE
|
# START SYSTEMD SERVICE
|
||||||
|
|
|
@ -32,6 +32,12 @@ then
|
||||||
yunohost service stop $service_name
|
yunohost service stop $service_name
|
||||||
yunohost service remove $service_name
|
yunohost service remove $service_name
|
||||||
fi
|
fi
|
||||||
|
if yunohost service status captiveportal_fakedns >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
ynh_script_progression --message="Removing $app captiveportal_fakedns service"
|
||||||
|
yunohost service stop captiveportal_fakedns
|
||||||
|
yunohost service remove captiveportal_fakedns
|
||||||
|
fi
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# STOP AND REMOVE SERVICE
|
# STOP AND REMOVE SERVICE
|
||||||
|
@ -40,6 +46,7 @@ ynh_script_progression --message="Stopping and removing the systemd service..."
|
||||||
|
|
||||||
# Remove the dedicated systemd config
|
# Remove the dedicated systemd config
|
||||||
ynh_remove_systemd_config --service=$service_name
|
ynh_remove_systemd_config --service=$service_name
|
||||||
|
ynh_remove_systemd_config --service=captiveportal_fakedns
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# REMOVE DEPENDENCIES
|
# REMOVE DEPENDENCIES
|
||||||
|
@ -56,6 +63,9 @@ ynh_script_progression --message="Removing app main directory..."
|
||||||
|
|
||||||
# Remove the app directory securely
|
# Remove the app directory securely
|
||||||
ynh_secure_remove --file="/usr/local/bin/$service_name"
|
ynh_secure_remove --file="/usr/local/bin/$service_name"
|
||||||
|
ynh_secure_remove --file="/usr/local/bin/captiveportal_fakedns"
|
||||||
|
ynh_secure_remove --file="/usr/local/bin/captiveportal_allow"
|
||||||
|
ynh_secure_remove --file="/etc/hotspot"
|
||||||
|
|
||||||
for FILE in $(ls /tmp/.ynh-hotspot-* 2>/dev/null)
|
for FILE in $(ls /tmp/.ynh-hotspot-* 2>/dev/null)
|
||||||
do
|
do
|
||||||
|
|
11
sources/captiveportal_allow
Normal file
11
sources/captiveportal_allow
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
date=$(date +"%Y-%m-%d %T")
|
||||||
|
ip=$1
|
||||||
|
mac=$(arp -a $ip | cut -d" " -f4 | head -n1)
|
||||||
|
interface=$(grep wifi_device /etc/yunohost/apps/hotspot/settings.yml | cut -d: -f2 | sed "s/[ ']//g")
|
||||||
|
if ! grep $mac /etc/hotspot/allowed.csv ; then
|
||||||
|
echo "$date,$ip,$mac" >> /etc/hotspot/allowed.csv
|
||||||
|
iptables -w -I hotspot_fwd 1 -s $ip -m mac --mac-source $mac -j ACCEPT
|
||||||
|
iptables -t nat -w -I PREROUTING 1 -i $interface -s $ip -m mac --mac-source $mac -j ACCEPT
|
||||||
|
fi
|
35
sources/captiveportal_fakedns
Normal file
35
sources/captiveportal_fakedns
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Net::DNS::Nameserver;
|
||||||
|
|
||||||
|
my $ip4_addr = shift @ARGV;
|
||||||
|
|
||||||
|
sub reply_handler {
|
||||||
|
my ($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_;
|
||||||
|
my ($rcode, @ans, @auth, @add);
|
||||||
|
|
||||||
|
if($qtype eq "A") {
|
||||||
|
my ($ttl, $rdata) = (1, $ip4_addr);
|
||||||
|
my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata");
|
||||||
|
push @ans, $rr;
|
||||||
|
$rcode = "NOERROR";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$rcode = "NXDOMAIN";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
my $ns = new Net::DNS::Nameserver(
|
||||||
|
LocalPort => 4253,
|
||||||
|
LocalAddr => $ip4_addr,
|
||||||
|
ReplyHandler => \&reply_handler,
|
||||||
|
Verbose => 0
|
||||||
|
) || die "Couldn't create fake nameserver object.\n";
|
||||||
|
|
||||||
|
$ns->main_loop;
|
||||||
|
|
||||||
|
exit 0;
|
2
sources/index.php
Normal file
2
sources/index.php
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?php
|
||||||
|
`/usr/local/bin/captiveportal_allow $_SERVER['REMOTE_ADDR']`;
|
Loading…
Add table
Reference in a new issue