From 3e6ec895587b169bcddf59098cf48477d8c2799d Mon Sep 17 00:00:00 2001 From: Peter Steenbergen Date: Tue, 31 Dec 2019 16:59:43 +0100 Subject: [PATCH] MycroftOS: Mimic a captive portal to auto start a browser on wifi connect. --- buildroot-external/configs/rpi3_defconfig | 8 ++++++ .../package/wifi-ap/dnsmasq.service | 19 +++++++++++++ .../package/wifi-ap/iptables.service | 18 ++++++++++++ .../package/wifi-ap/nginx.service | 21 ++++++++++++++ buildroot-external/package/wifi-ap/wifi-ap.mk | 16 +++++++++++ .../rootfs-overlay/etc/dnsmasq.conf | 2 ++ .../rootfs-overlay/etc/iptables.rules | 13 +++++++++ .../rootfs-overlay/etc/nginx/nginx.conf | 28 +++++++++++++++++++ .../etc/systemd/network/wifi.network.ap | 2 ++ .../rootfs-overlay/etc/systemd/resolved.conf | 24 ++++++++++++++++ .../mycroft/wifisetup/templates/hotspot.html | 15 ++++++++++ .../usr/lib/systemd/scripts/iptables-flush | 18 ++++++++++++ 12 files changed, 184 insertions(+) create mode 100644 buildroot-external/package/wifi-ap/dnsmasq.service create mode 100644 buildroot-external/package/wifi-ap/iptables.service create mode 100644 buildroot-external/package/wifi-ap/nginx.service create mode 100644 buildroot-external/rootfs-overlay/etc/dnsmasq.conf create mode 100644 buildroot-external/rootfs-overlay/etc/iptables.rules create mode 100644 buildroot-external/rootfs-overlay/etc/nginx/nginx.conf create mode 100644 buildroot-external/rootfs-overlay/etc/systemd/resolved.conf create mode 100644 buildroot-external/rootfs-overlay/opt/mycroft/wifisetup/templates/hotspot.html create mode 100755 buildroot-external/rootfs-overlay/usr/lib/systemd/scripts/iptables-flush diff --git a/buildroot-external/configs/rpi3_defconfig b/buildroot-external/configs/rpi3_defconfig index e8afd190..370364a7 100644 --- a/buildroot-external/configs/rpi3_defconfig +++ b/buildroot-external/configs/rpi3_defconfig @@ -239,6 +239,7 @@ BR2_PACKAGE_C_ARES=y BR2_PACKAGE_LIBCURL=y BR2_PACKAGE_CURL=y BR2_PACKAGE_LIBHTTPPARSER=y +BR2_PACKAGE_LIBMICROHTTPD=y BR2_PACKAGE_LIBNDP=y BR2_PACKAGE_LIBTIRPC=y BR2_PACKAGE_NGHTTP2=y @@ -251,10 +252,17 @@ BR2_PACKAGE_PCRE_32=y BR2_PACKAGE_PCRE2_16=y BR2_PACKAGE_PCRE2_32=y BR2_PACKAGE_AVAHI=y +BR2_PACKAGE_AVAHI_DAEMON=y +BR2_PACKAGE_AVAHI_LIBDNSSD_COMPATIBILITY=y BR2_PACKAGE_CRDA=y +BR2_PACKAGE_DNSMASQ=y +# BR2_PACKAGE_DNSMASQ_TFTP is not set +# BR2_PACKAGE_DNSMASQ_DHCP is not set BR2_PACKAGE_IPTABLES=y BR2_PACKAGE_IW=y +BR2_PACKAGE_NGINX=y BR2_PACKAGE_NTP=y +# BR2_PACKAGE_NTP_NTPD is not set BR2_PACKAGE_NTP_NTPDATE=y BR2_PACKAGE_NTP_NTPTIME=y BR2_PACKAGE_OPENSSH=y diff --git a/buildroot-external/package/wifi-ap/dnsmasq.service b/buildroot-external/package/wifi-ap/dnsmasq.service new file mode 100644 index 00000000..24dffc80 --- /dev/null +++ b/buildroot-external/package/wifi-ap/dnsmasq.service @@ -0,0 +1,19 @@ +[Unit] +Description=Small DNS server to resolve everything to the AP interface. +BindsTo=sys-subsystem-net-devices-ap0.device +After=sys-subsystem-net-devices-ap0.device +Before=network.target +Wants=network.target + +# check existence of configuration file +ConditionPathExists= /etc/wpa_supplicant/wpa_supplicant-ap0.conf +ConditionPathExists=!/etc/wpa_supplicant/wpa_supplicant-wlan0.conf + +[Service] +ExecStart=/usr/sbin/dnsmasq -k --conf-file=/etc/dnsmasq.conf +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=sys-subsystem-net-devices-ap0.device diff --git a/buildroot-external/package/wifi-ap/iptables.service b/buildroot-external/package/wifi-ap/iptables.service new file mode 100644 index 00000000..339bc906 --- /dev/null +++ b/buildroot-external/package/wifi-ap/iptables.service @@ -0,0 +1,18 @@ +[Unit] +Description=Packet Filtering Framework +Before=network-pre.target +Wants=network-pre.target + +# check existence of configuration file +ConditionPathExists= /etc/wpa_supplicant/wpa_supplicant-ap0.conf +ConditionPathExists=!/etc/wpa_supplicant/wpa_supplicant-wlan0.conf + +[Service] +Type=oneshot +ExecStart=/sbin/iptables-restore /etc/iptables.rules +ExecReload=/sbin/iptables-restore /etc/iptables.rules +ExecStop=/usr/lib/systemd/scripts/iptables-flush +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/buildroot-external/package/wifi-ap/nginx.service b/buildroot-external/package/wifi-ap/nginx.service new file mode 100644 index 00000000..1b0f0681 --- /dev/null +++ b/buildroot-external/package/wifi-ap/nginx.service @@ -0,0 +1,21 @@ +[Unit] +Description=A high performance web server and a reverse proxy server +BindsTo=sys-subsystem-net-devices-ap0.device +After=sys-subsystem-net-devices-ap0.device syslog.target network.target + +# check existence of configuration file +ConditionPathExists= /etc/wpa_supplicant/wpa_supplicant-ap0.conf +ConditionPathExists=!/etc/wpa_supplicant/wpa_supplicant-wlan0.conf + +[Service] +Type=forking +PIDFile=/var/run/nginx.pid +ExecStartPre=/usr/bin/mkdir -p /var/log/nginx /var/tmp/nginx +ExecStartPre=/usr/sbin/nginx -t -q -g 'pid /var/run/nginx.pid; daemon on; master_process on;' +ExecStart=/usr/sbin/nginx -g 'pid /var/run/nginx.pid; daemon on; master_process on;' +ExecReload=/usr/sbin/nginx -g 'pid /var/run/nginx.pid; daemon on; master_process on;' -s reload +ExecStop=/usr/sbin/nginx -g 'pid /var/run/nginx.pid;' -s quit +PrivateDevices=yes + +[Install] +WantedBy=multi-user.target diff --git a/buildroot-external/package/wifi-ap/wifi-ap.mk b/buildroot-external/package/wifi-ap/wifi-ap.mk index a40ca8ee..2f9ea3ff 100644 --- a/buildroot-external/package/wifi-ap/wifi-ap.mk +++ b/buildroot-external/package/wifi-ap/wifi-ap.mk @@ -22,6 +22,10 @@ define WIFI_AP_INSTALL_TARGET_CMDS $(TARGET_DIR)/usr/lib/systemd/system/wifi-setup.service ln -fs ../../../../usr/lib/systemd/system/wifi-setup.service \ $(TARGET_DIR)/etc/systemd/system/sys-subsystem-net-devices-ap0.device.wants/wifi-setup.service + $(INSTALL) -D -m 644 $(@D)/dnsmasq.service \ + $(TARGET_DIR)/usr/lib/systemd/system/dnsmasq.service + ln -fs ../../../../usr/lib/systemd/system/dnsmasq.service \ + $(TARGET_DIR)/etc/systemd/system/sys-subsystem-net-devices-ap0.device.wants/dnsmasq.service $(INSTALL) -D -m 644 $(@D)/wireless-mode-ap.service \ $(TARGET_DIR)/usr/lib/systemd/system/wireless-mode-ap.service @@ -34,6 +38,18 @@ define WIFI_AP_INSTALL_TARGET_CMDS mkdir -p $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants ln -fs ../../../../usr/lib/systemd/system/wireless-mode-client.service \ $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants/wireless-mode-client.service + + $(INSTALL) -D -m 644 $(@D)/nginx.service \ + $(TARGET_DIR)/usr/lib/systemd/system/nginx.service + mkdir -p $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants + ln -fs ../../../../usr/lib/systemd/system/nginx.service \ + $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants/nginx.service + + $(INSTALL) -D -m 644 $(@D)/iptables.service \ + $(TARGET_DIR)/usr/lib/systemd/system/iptables.service + mkdir -p $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants + ln -fs ../../../../usr/lib/systemd/system/iptables.service \ + $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants/iptables.service endef $(eval $(generic-package)) diff --git a/buildroot-external/rootfs-overlay/etc/dnsmasq.conf b/buildroot-external/rootfs-overlay/etc/dnsmasq.conf new file mode 100644 index 00000000..56ebb632 --- /dev/null +++ b/buildroot-external/rootfs-overlay/etc/dnsmasq.conf @@ -0,0 +1,2 @@ +interface=ap0 +address=/#/172.16.127.1 diff --git a/buildroot-external/rootfs-overlay/etc/iptables.rules b/buildroot-external/rootfs-overlay/etc/iptables.rules new file mode 100644 index 00000000..a10b7f16 --- /dev/null +++ b/buildroot-external/rootfs-overlay/etc/iptables.rules @@ -0,0 +1,13 @@ +*nat +:PREROUTING ACCEPT [14:1672] +:INPUT ACCEPT [13:1640] +:OUTPUT ACCEPT [24:1440] +:POSTROUTING ACCEPT [24:1440] +-A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.16.127.1 +-A PREROUTING -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.16.127.1 +COMMIT +*filter +:INPUT ACCEPT [60540:12954317] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [56210:7390098] +COMMIT diff --git a/buildroot-external/rootfs-overlay/etc/nginx/nginx.conf b/buildroot-external/rootfs-overlay/etc/nginx/nginx.conf new file mode 100644 index 00000000..fe3a5ac9 --- /dev/null +++ b/buildroot-external/rootfs-overlay/etc/nginx/nginx.conf @@ -0,0 +1,28 @@ + +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + + server { + listen 80; + server_name MycroftOS; + root /opt/mycroft/wifisetup/templates; + + # For iOS + if ($http_user_agent ~* (CaptiveNetworkSupport) ) { + return 302 http://172.16.127.1:88/hotspot.html; + } + # For others + location / { + return 302 http://172.16.127.1:88/; + } + } +} diff --git a/buildroot-external/rootfs-overlay/etc/systemd/network/wifi.network.ap b/buildroot-external/rootfs-overlay/etc/systemd/network/wifi.network.ap index e08ed9c7..e8c7431e 100644 --- a/buildroot-external/rootfs-overlay/etc/systemd/network/wifi.network.ap +++ b/buildroot-external/rootfs-overlay/etc/systemd/network/wifi.network.ap @@ -3,3 +3,5 @@ Name=ap0 [Network] Address=172.16.127.1/28 DHCPServer=yes +[DHCPServer] +DNS=172.16.127.1 diff --git a/buildroot-external/rootfs-overlay/etc/systemd/resolved.conf b/buildroot-external/rootfs-overlay/etc/systemd/resolved.conf new file mode 100644 index 00000000..fb90a6d0 --- /dev/null +++ b/buildroot-external/rootfs-overlay/etc/systemd/resolved.conf @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See resolved.conf(5) for details + +[Resolve] +#DNS= +#FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844 +#Domains= +#LLMNR=yes +#MulticastDNS=yes +#DNSSEC=no +#DNSOverTLS=no +#Cache=yes +DNSStubListener=no +#ReadEtcHosts=yes diff --git a/buildroot-external/rootfs-overlay/opt/mycroft/wifisetup/templates/hotspot.html b/buildroot-external/rootfs-overlay/opt/mycroft/wifisetup/templates/hotspot.html new file mode 100644 index 00000000..a6ae476c --- /dev/null +++ b/buildroot-external/rootfs-overlay/opt/mycroft/wifisetup/templates/hotspot.html @@ -0,0 +1,15 @@ + diff --git a/buildroot-external/rootfs-overlay/usr/lib/systemd/scripts/iptables-flush b/buildroot-external/rootfs-overlay/usr/lib/systemd/scripts/iptables-flush new file mode 100755 index 00000000..e6fafe95 --- /dev/null +++ b/buildroot-external/rootfs-overlay/usr/lib/systemd/scripts/iptables-flush @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Usage: iptables-flush [6] +# + +iptables=ip$1tables +if ! type -p "$iptables"; then + echo "error: invalid argument" + exit 1 +fi + +while read -r table; do + tables+=("/var/lib/$iptables/empty-$table.rules") +done <"/proc/net/ip$1_tables_names" + +if (( ${#tables[*]} )); then + cat "${tables[@]}" | "$iptables-restore" +fi