From c749dd35f83dbec6150809110cecdfd6d41f609b Mon Sep 17 00:00:00 2001 From: Keith Whyte Date: Mon, 21 Aug 2023 03:43:20 +0200 Subject: [PATCH] Wifi Captive Portal An implementation of a simple Captive Portal that allows access to an IP network via forwarding on the same machine running the GSM core network. A Wifi AP could be connected to the ethernet port specified in the hiera as wifi_if (default eth3) Any Wifi AP can be used, and configured as desired. In the future, maybe a RADIUS based solution could supercede this. --- .../files/systemd/dnsmasq-wifi.service | 11 ++ modules/rhizo_base/manifests/init.pp | 18 +++ modules/rhizo_base/manifests/wifi.pp | 107 ++++++++++++++++++ .../rhizo_base/templates/config_values.py.erb | 4 +- modules/rhizo_base/templates/dnsmasq.conf.erb | 9 ++ modules/rhizo_base/templates/portal.conf.erb | 22 ++++ 6 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 modules/rhizo_base/files/systemd/dnsmasq-wifi.service create mode 100644 modules/rhizo_base/manifests/wifi.pp create mode 100644 modules/rhizo_base/templates/dnsmasq.conf.erb create mode 100644 modules/rhizo_base/templates/portal.conf.erb diff --git a/modules/rhizo_base/files/systemd/dnsmasq-wifi.service b/modules/rhizo_base/files/systemd/dnsmasq-wifi.service new file mode 100644 index 0000000..b6ad37c --- /dev/null +++ b/modules/rhizo_base/files/systemd/dnsmasq-wifi.service @@ -0,0 +1,11 @@ +[Unit] +Description=DNSMASQ for Wifi-Portal + +[Service] +Type=simple +Restart=always +ExecStart=/usr/sbin/dnsmasq -C /etc/dnsmasq.wifi.conf +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/modules/rhizo_base/manifests/init.pp b/modules/rhizo_base/manifests/init.pp index 6787c76..ba92a37 100644 --- a/modules/rhizo_base/manifests/init.pp +++ b/modules/rhizo_base/manifests/init.pp @@ -76,6 +76,10 @@ class rhizo_base { $bsc_ip_address = hiera('rhizo::bsc_ip_address', '172.16.0.1') $vpn_ip_address = hiera('rhizo::vpn_ip_address') $wan_ip_address = hiera('rhizo::wan_ip_address') + $wifi_ip_address = hiera('rhizo::wifi_ip_address', '172.24.0.1') + $wifi_net = hiera('rhizo::wifi_net', '172.24.0.0/16') + $wifi_dhcp_range = hiera('rhizo::wifi_dhcp_range', '172.24.0.1,172.24.100.254') + $wifi_dns = hiera('rhizo::wifi_dns', '1.1.1.1') $sip_central_ip_address = hiera('rhizo::sip_central_ip_address') $webphone_prefix = hiera('rhizo::webphone_prefix', '[]') $latency_check_address = hiera('rhizo::latency_check_address','1.1.1.1') @@ -87,6 +91,8 @@ class rhizo_base { $stats_disk = hiera('rhizo::stats_disk','sda1') $stats_if = hiera('rhizo::stats_if','eth0') + $wifi_if = hiera('rhizo::wifi_if','eth3') + $has_wifi = hiera('rhizo::has_wifi', 0) # SITE settings # rate type can be "call" or "min" @@ -200,6 +206,13 @@ class rhizo_base { if $has_vsat == 1 { include rhizo_base::sems } + if $has_wifi == 1 { + Firewall { + require => undef, + } + class { 'firewall': } + include rhizo_base::wifi + } sysctl { 'net.ipv4.ip_forward': value => '1' @@ -333,6 +346,11 @@ schedule { 'never': $rsched = "never" } + service { 'apache2': + require => [ Package['apache2'], Vcsrepo['/var/rhizomatica'] ], + ensure => running, + } + vcsrepo { '/var/rhizomatica': schedule => $rsched, ensure => latest, diff --git a/modules/rhizo_base/manifests/wifi.pp b/modules/rhizo_base/manifests/wifi.pp new file mode 100644 index 0000000..c87ed44 --- /dev/null +++ b/modules/rhizo_base/manifests/wifi.pp @@ -0,0 +1,107 @@ +# wifi.pp +# +# A basic Wifi service with +# captive portal and authentication via SMS OTP. +# +# + +class rhizo_base::wifi { + + $pub_if = $rhizo_base::stats_if + $wifi_if = $rhizo_base::wifi_if + $wifi_ip = $rhizo_base::wifi_ip_address + $wifi_net = $rhizo_base::wifi_net + $wifi_dhcp_range = $rhizo_base::wifi_dhcp_range + $wifi_dns = $rhizo_base::wifi_dns + + file { '/etc/dnsmasq.wifi.conf': + content => template('rhizo_base/dnsmasq.conf.erb'), + notify => Service['dnsmasq-wifi'] + } + + file { '/lib/systemd/system/dnsmasq-wifi.service': + ensure => present, + source => 'puppet:///modules/rhizo_base/systemd/dnsmasq-wifi.service', + } + + service { 'dnsmasq-wifi': + provider => 'systemd', + enable => true, + ensure => 'running' + } + + python::pip { 'python-iptables': + schedule => 'onceweek', + ensure => '1.0.1', + pkgname => 'python-iptables', + } + + file { '/etc/apache2/sites-available/001-portal.conf': + content => template('rhizo_base/portal.conf.erb'), + require => Package['apache2'] + } + ->file { '/etc/apache2/sites-enabled/001-portal.conf': + ensure => link, + target => '../sites-available/001-portal.conf', + require => Package['apache2'], + notify => Service['apache2'] + } + + firewall { '000 accept DHCP (udp port 67)': + proto => 'udp', + iniface => $wifi_if, + dport => [53, 67], + action => 'accept', + } + ->firewall { '001 accept WWW Portal': + proto => 'tcp', + iniface => $wifi_if, + dport => 81, + action => 'accept', + } + ->firewall { '002 accept ICMP': + proto => 'icmp', + iniface => $wifi_if, + destination => $wifi_ip, + action => 'accept', + } + ->firewall { '003 drop mark 10': + iniface => $wifi_if, + match_mark => 0xa, + action => 'drop', + } + + firewall { '005 accept related established': + chain => 'FORWARD', + proto => 'all', + iniface => $pub_if, + state => ['RELATED', 'ESTABLISHED'], + action => 'accept', + } + ->firewall { '006 drop mark 10': + chain => 'FORWARD', + iniface => $wifi_if, + match_mark => 0xa, + action => 'drop', + } + + firewall { '020 redirect to portal': + table => 'nat', + chain => 'PREROUTING', + proto => 'tcp', + dport => 80, + iniface => $wifi_if, + match_mark => 0xa, + jump => 'DNAT', + todest => "$wifi_ip:81" + } + + firewall { '021 nat masq from Wifi': + table => 'nat', + chain => 'POSTROUTING', + source => $wifi_net, + outiface => $pub_if, + jump => 'MASQUERADE' + } + +} diff --git a/modules/rhizo_base/templates/config_values.py.erb b/modules/rhizo_base/templates/config_values.py.erb index 302d752..f8b8942 100644 --- a/modules/rhizo_base/templates/config_values.py.erb +++ b/modules/rhizo_base/templates/config_values.py.erb @@ -26,7 +26,7 @@ pgsql_db = '<%= @pgsql_db %>' pgsql_user = '<%= @pgsql_user %>' pgsql_pwd = '<%= @pgsql_pwd %>' pgsql_host = '<%= @pgsql_host %>' -db_revision = 16 +db_revision = 18 # SITE site_name = "<%= @site_name %>" @@ -42,6 +42,8 @@ mncc_ip_address = "<%= @mncc_ip_address %>" sip_central_ip_address = <%= @sip_central_ip_address %> webphone_prefix = <%= @webphone_prefix %> has_vsat = <%= @has_vsat %> +has_wifi = <%= @has_wifi %> +wifi_if = "<%= @wifi_if %>" site_routing = [ <%= @site_routing %> diff --git a/modules/rhizo_base/templates/dnsmasq.conf.erb b/modules/rhizo_base/templates/dnsmasq.conf.erb new file mode 100644 index 0000000..02f5b24 --- /dev/null +++ b/modules/rhizo_base/templates/dnsmasq.conf.erb @@ -0,0 +1,9 @@ +keep-in-foreground +interface=<%= @wifi_if %> +listen-address=<%= @wifi_ip %> +port=54 +no-resolv +dhcp-range=<%= @wifi_dhcp_range %> +dhcp-option-force=114,http://<%= @wifi_ip %> +dhcp-option-force=6,<%= @wifi_dns %> +dhcp-leasefile=/var/lib/misc/dnsmasq-wifi.leases diff --git a/modules/rhizo_base/templates/portal.conf.erb b/modules/rhizo_base/templates/portal.conf.erb new file mode 100644 index 0000000..5b8efe2 --- /dev/null +++ b/modules/rhizo_base/templates/portal.conf.erb @@ -0,0 +1,22 @@ + + + RewriteEngine on + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^.*$ http://<%= @wifi_ip %>/index.php [R] + Require all granted + + + +:81> + #ServerName www.example.com + + ServerAdmin webmaster@localhost + DocumentRoot /var/rhizomatica/portal + + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/portal_error.log + CustomLog ${APACHE_LOG_DIR}/portal_access.log combined + +