Opennet Firmware
 Alle Dateien Funktionen Variablen Gruppen Seiten
on-captive-portal.sh
gehe zur Dokumentation dieser Datei
1 ## @defgroup captive_portal Captive Portal
2 ## @brief Funktionen für den Umgang mit der Captive-Portal-Software für offene WLAN-Knoten
3 # Beginn der Doku-Gruppe
4 ## @{
5 
6 
7 ZONE_FREE=on_free
8 NETWORK_FREE=on_free
9 ## @var Quelldatei für Standardwerte des Hotspot-Pakets
10 ON_CAPTIVE_PORTAL_DEFAULTS_FILE=/usr/share/opennet/captive-portal.defaults
11 
12 
13 ## @fn configure_free_network()
14 ## @brief Erzeuge das free-Netzwerk-Interface, falls es noch nicht existiert.
16  local uci_prefix="network.$NETWORK_FREE"
17  # es wurde bereits einmalig konfiguriert
18  if [ -z "$(uci_get "$uci_prefix")" ]; then
19  uci set "${uci_prefix}=interface"
20  uci set "${uci_prefix}.ifname=none"
21  uci set "${uci_prefix}.proto=static"
22  uci set "${uci_prefix}.ipaddr=$(get_on_captive_portal_default free_ipaddress)"
23  uci set "${uci_prefix}.netmask=$(get_on_captive_portal_default free_netmask)"
24  # wir aktivieren das Interface manuell via hotplug
25  uci set "${uci_prefix}.auto=0"
26  apply_changes network
27  fi
28  # konfiguriere DHCP
29  uci_prefix=$(find_first_uci_section "dhcp" "dhcp" "interface=$NETWORK_FREE")
30  # beenden, falls vorhanden
31  if [ -z "$uci_prefix" ]; then
32  # DHCP-Einstellungen fuer dieses Interface festlegen
33  uci_prefix="dhcp.$(uci add "dhcp" "dhcp")"
34  uci set "${uci_prefix}.interface=$NETWORK_FREE"
35  uci set "${uci_prefix}.start=10"
36  uci set "${uci_prefix}.limit=240"
37  uci set "${uci_prefix}.leasetime=30m"
38  apply_changes dhcp
39  fi
40 }
41 
42 
43 ## @fn captive_portal_get_or_create_config()
44 ## @brief Liefere die uci-captive-Portal-Konfigurationssektion zurück.
45 ## @details Typischerweise ist dies so etwas wie nodogsplash.cfgXXXX. Falls die uci-Sektion noch
46 ## nicht existieren sollte, dann wird sie erzeugt und zurückgeliefert.
48  trap "error_trap captive_portal_get_or_create_config '$*'" $GUARD_TRAPS
49  local uci_prefix
50  uci_prefix=$(find_first_uci_section "nodogsplash" "instance" "network=$NETWORK_FREE")
51  # gefunden? Zurueckliefern ...
52  if [ -z "$uci_prefix" ]; then
53  # neu mit grundlegenden Einstellungen anlegen
54  # Detail-Konfiguration findet via uci-defaults nur einmalig statt (damit der Nutzer sie überschreiben kann)
55  uci_prefix="nodogsplash.$(uci add "nodogsplash" "instance")"
56  # wir aktivieren den Dienst generell - der Nutzer muss dem Device aktiv ein Gerät hinzufügen, um es zu aktivieren
57  uci set "${uci_prefix}.enabled=1"
58  uci set "${uci_prefix}.network=$NETWORK_FREE"
59  uci set "${uci_prefix}.gatewayname=$(get_on_captive_portal_default "node_name")"
60  uci set "${uci_prefix}.redirecturl=$(get_on_captive_portal_default "portal_url")"
61  uci set "${uci_prefix}.maxclients=250"
62  # kein Zwischen-Klick, keine lokale Webseite
63  uci set "${uci_prefix}.authenticateimmediately=1"
64  # Wir definieren keine "authenticated"-Regeln: nodogsplash verwendet "RETURN", falls
65  # diese Liste leer ist. Dies ist wünschenswert, auf dass wir mit unserer firewall-
66  # Einstellung der free-Zone den gewünschten Verkehrsfluss regeln können. Typischerweise
67  # ist hier lediglich eine free->on_openvpn-Zonenregel erforderlich.
68  # Demgegenüber ist es für den "users-to-router"-Verkehr praktischer, die einfachen
69  # nodogsplash-Einstellungen zu verwenden. Dadurch vermeiden wir die Verwaltung
70  # separater firewall-Regeln.
71  # ssh/web (nur fuer Debugging)
72  #uci add_list "${uci_prefix}.users_to_router=allow tcp port 22"
73  #uci add_list "${uci_prefix}.users_to_router=allow tcp port 443"
74  # DNS
75  uci add_list "${uci_prefix}.users_to_router=allow tcp port 53"
76  uci add_list "${uci_prefix}.users_to_router=allow udp port 53"
77  # DHCP
78  uci add_list "${uci_prefix}.users_to_router=allow udp port 67"
79  # jeglichen Verkehr ohne Interaktion zulassen
80  # (lediglich der erste Zugriff auf Port 80 wird auf die Portalseite umgelenkt)
81  uci set "${uci_prefix}.policy_preauthenticated_users=passthrough"
82  # erstmal nur speichern - um die Anwendung kuemmert sich jemand anders
83  uci commit nodogsplash
84  fi
85  echo -n "$uci_prefix"
86 }
87 
88 
89 ## @fn get_on_captive_portal_default()
90 ## @param key Name des Schlüssels
91 ## @brief Liefere einen der default-Werte der aktuellen Firmware zurück (Paket on-captive-portal).
92 ## @details Die default-Werte werden nicht von der Konfigurationsverwaltung uci verwaltet.
93 ## Somit sind nach jedem Upgrade imer die neuesten Standard-Werte verfügbar.
95  local key="$1"
96  _get_file_dict_value "$key" "$ON_CAPTIVE_PORTAL_DEFAULTS_FILE"
97 }
98 
99 
100 ## @fn captive_portal_set_property()
101 ## @brief Setze ein Attribut der Captive-Portal-Funktion
102 ## @param key Eins der Captive-Portal-Attribute: name / url
103 ## @param value Der gewünschte neue Inhalt des Attributs
104 ## @attention Anschließend ist 'apply_changes on-captive-portal' aufzurufen, um die Änderungen wirksam werden zu lassen.
106  local key="$1"
107  local value="$2"
108  local uci_attribute
109  uci_attribute=$(_captive_portal_get_mapped_attribute "$key")
110  # ein Fehler ist aufgetreten - die obige subshell verdeckt ihn jedoch
111  [ -z "$uci_attribute" ] && return 1
112  local uci_prefix
114  uci set "${uci_prefix}.${uci_attribute}=$value"
115 }
116 
117 
118 ## @fn captive_portal_get_property()
119 ## @brief Hole ein Attribut der Captive-Portal-Funktion
120 ## @param key Eins der Captive-Portal-Attribute: name / url
122  local key="$1"
123  local uci_attribute
124  uci_attribute=$(_captive_portal_get_mapped_attribute "$key")
125  # ein Fehler ist aufgetreten - die obige subshell verdeckt ihn jedoch
126  [ -z "$uci_attribute" ] && return 1
127  local uci_prefix
129  uci_get "${uci_prefix}.${uci_attribute}"
130 }
131 
132 
133 ## @fn _captive_portal_get_mapped_attribute()
134 ## @brief Liefere den UCI-Attribut-Namen für eine Captive-Portal-Eigenschaft zurück.
135 ## @param attribute Eins der Captive-Portal-Attribute: name / url
136 ## @details Dies ist lediglich eine Abstraktionsschicht.
138  local attribute="$1"
139  if [ "$attribute" = "name" ]; then
140  echo -n "gatewayname"
141  elif [ "$attribute" = "url" ]; then
142  echo -n "redirecturl"
143  else
144  msg_error "unknown captive portal attribute mapping requested: $attribute"
145  return 1
146  fi
147 }
148 
149 
150 ## @fn captive_portal_restart()
151 ## @brief Führe einen Neustart der Captive-Portal-Software mit minimalen Seiteneffekten durch.
152 ## @details Aktuelle Verbindungen bleiben nach Möglichkeit erhalten.
154  trap "error_trap captive_portal_restart '$*'" $GUARD_TRAPS
155  # alte Clients-Liste sichern; keine Fehlerausgabe bei gestopptem Prozess
156  local clients
157  clients=$(ndsctl clients 2>/dev/null | grep "^ip=" | cut -f 2 -d =)
158  # Prozess neustarten (reload legt wohl keine iptables-Regeln an)
159  /etc/init.d/nodogsplash restart >/dev/null
160  # kurz warten, damit der Dienst startet
161  sleep 1
162  # kein laufender Prozess? Keine Wiederherstellung von Clients ...
163  [ -z "$(pidof nodogsplash)" ] && return 0
164  # Client-Liste wiederherstellen
165  local ip
166  echo "$clients" | while read ip; do
167  [ -z "$ip" ] && continue
168  ndsctl auth "$ip"
169  done
170 }
171 
172 
173 ## @fn captive_portal_reload()
174 ## @brief Neukonfiguration der Captive-Portal-Software, falls Änderungen aufgetreten sind.
175 ## @details Bestehende Verbindungen bleiben erhalten.
177  /etc/init.d/nodogsplash reload >/dev/null
178 }
179 
180 
181 ## @fn captive_portal_has_devices()
182 ## @brief Prüfe, ob dem Captive Portal mindestens ein physisches Netzwerk-Gerät zugeordnet ist.
183 ## @details Sobald ein Netzwerk-Gerät konfiguriert ist, gilt der Captive-Portal-Dienst als aktiv.
185  [ -n "$(get_subdevices_of_interface "$NETWORK_FREE")" ] && return 0
186  trap "" $GUARD_TRAPS && return 1
187 }
188 
189 
190 ## @fn captive_portail_repair_empty_network_bridge()
191 ## @brief Reduziere Konstruktionen wie beispielsweise "bridge(None, wlan0)" zu "wlan0".
192 ## @details Brücken mit "none"-Elementen verwirren das nodogsplash-Start-Skript.
194  local uci_prefix="network.${NETWORK_FREE}"
195  local sub_devices=$(get_subdevices_of_interface "$NETWORK_FREE")
196  if [ "$(uci_get "${uci_prefix}.type")" = "bridge" -a "$(uci_get "${uci_prefix}.ifname")" = "none" ]; then
197  # verdaechtig: Bruecke mit "none"-Device
198  if [ -n "$sub_devices" ]; then
199  # wifi-Device is konfiguriert - Bruecke und "none" kann entfernt werden
200  uci_delete "${uci_prefix}.type"
201  uci_delete "${uci_prefix}.ifname"
202  else
203  # nichts ist konfiguriert - erstmal nur die Bruecke entfernen
204  uci_delete "${uci_prefix}.type"
205  fi
206  apply_changes network
207  fi
208 }
209 
210 
211 update_captive_portal_status() {
212  if is_on_module_installed_and_enabled "on-captive-portal"; then
214  else
215  disable_captive_portal
216  fi
217 }
218 
219 
220 disable_captive_portal() {
221  # free-Interface ist aktive - es gibt jedoch keinen Tunnel
222  ifdown "$NETWORK_FREE"
223  # reload fuehrt zum sanften Stoppen
225  true
226 }
227 
228 
229 ## @fn sync_captive_portal_state_with_mig_connections()
230 ## @brief Synchronisiere den Zustand (up/down) des free-Interface mit dem des VPN-Tunnel-Interface.
231 ## @details Diese Funktion wird nach Statusänderungen des VPN-Interface, sowie innerhalb eines
232 ## regelmäßigen cronjobs ausgeführt.
234  trap "error_trap sync_captive_portal_state_with_mig_connections '$*'" $GUARD_TRAPS
235  # eventuelle defekte/verwirrende Netzwerk-Konfiguration korrigieren
237  # Abbruch, falls keine Netzwerk-Interfaces zugeordnet wurden
238  captive_portal_has_devices || return 0
239  local mig_active
240  local address
241  local device_active=
242  mig_active=$(get_active_mig_connections)
243  if is_interface_up "$NETWORK_FREE"; then
244  # Pruefe ob mindestens eine IPv4-Adresse konfiguriert ist.
245  # (aus unbekannten Gruenden kann es vorkommen, dass die IPv4-Adresse spontan wegfaellt)
246  for address in $(get_current_addresses_of_network "$NETWORK_FREE"); do
247  is_ipv4 "$address" && device_active=1 && break
248  true
249  done
250  fi
251  if [ -n "$device_active" -a -z "$mig_active" ]; then
252  disable_captive_portal
253  elif [ -z "$device_active" -a -n "$mig_active" ]; then
254  # kein aktives free-Interface, aber ein aktiver Tunnel
255  ifup "$NETWORK_FREE"
256  fi
257  # warte auf das Netzwerk-Interface
258  sleep 3
259  # Portalsoftware neu laden, falls das Interface aktiv ist, jedoch kein Prozess laeuft
260  [ -n "$mig_active" ] && ! is_captive_portal_running && captive_portal_reload
261  true
262 }
263 
264 
265 ## @fn is_captive_portal_running()
266 ## @brief Prüfe ob der Captive-Portal-Dienst läuft.
268  [ -n "$(pgrep "^/usr/bin/nodogsplash$")" ] && return 0
269  trap "" $GUARD_TRAPS && return 1
270 }
271 
272 
273 ## @fn get_captive_portal_client_count()
274 ## @brief Ermittle die Anzahl der verbundenen Clients.
276  local count=0
277  is_captive_portal_running && count=$(ndsctl clients | head -1)
278  echo -n "$count"
279 }
280 
281 
283 ## @brief Zeilenweise aller aktuellen Clients inklusive ihrer relevanten Kenngrößen.
284 ## @details In jeder Zeile wird ein Client beschrieben, wobei die folgenden Detailinformationen durch Tabulatoren getrennt sind:
285 ## * IP-Adresse
286 ## * MAC-Adresse
287 ## * Zeitpunkt des Verbindungsaufbaus (seit epoch)
288 ## * Zeitpunkt der letzten Aktivität (seit epoch)
289 ## * Download-Verkehrsvolumen (kByte)
290 ## * Upload-Verkehrsvolumen (kByte)
292  trap "error_trap get_captive_portal_clients '$*'" $GUARD_TRAPS
293  local line
294  local key
295  local value
296  local ip_address=
297  local mac_address=
298  local connection_timestamp=
299  local activity_timestamp=
300  local traffic_download=
301  local traffic_upload=
302  # erzwinge eine leere Zeile am Ende fuer die finale Ausgabe des letzten Clients
303  (ndsctl clients; echo) | while read line; do
304  key=$(echo "$line" | cut -f 1 -d =)
305  value=$(echo "$line" | cut -f 2- -d =)
306  [ "$key" = "ip" ] && ip_address="$value"
307  [ "$key" = "mac" ] && mac_address="$value"
308  [ "$key" = "added" ] && connection_timestamp="$value"
309  [ "$key" = "active" ] && activity_timestamp="$value"
310  [ "$key" = "downloaded" ] && traffic_download="$value"
311  [ "$key" = "uploaded" ] && traffic_upload="$value"
312  if [ -z "$key" -a -n "$ip_address" ]; then
313  # leere Eingabezeile trennt Clients: Ausgabe des vorherigen Clients
314  printf "%s\t%s\t%s\t%s\t%s\t%s\n" \
315  "$ip_address" "$mac_address" "$connection_timestamp" \
316  "$activity_timestamp" "$traffic_download" "$traffic_upload"
317  ip_address=
318  mac_address=
319  connection_timestamp=
320  activity_timestamp=
321  traffic_download=
322  traffic_upload=
323  fi
324  done
325 }
326 
327 # Ende der Doku-Gruppe
328 ## @}
uci_delete(uci_path)
Lösche ein UCI-Element.
Definition: uci.sh:38
get_captive_portal_clients()
Zeilenweise aller aktuellen Clients inklusive ihrer relevanten Kenngrößen.
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
Definition: routing.sh:8
sync_captive_portal_state_with_mig_connections()
Synchronisiere den Zustand (up/down) des free-Interface mit dem des VPN-Tunnel-Interface.
while read key value
Definition: core.sh:81
_captive_portal_get_mapped_attribute(attribute)
Liefere den UCI-Attribut-Namen für eine Captive-Portal-Eigenschaft zurück.
local key
Definition: core.sh:81
_get_file_dict_value(key)
Auslesen eines Werts aus einem Schlüssel/Wert-Eingabestrom.
Definition: core.sh:81
captive_portal_get_or_create_config()
Liefere die uci-captive-Portal-Konfigurationssektion zurück.
captive_portal_get_property(key)
Hole ein Attribut der Captive-Portal-Funktion.
captive_portal_reload()
Neukonfiguration der Captive-Portal-Software, falls Änderungen aufgetreten sind.
is_interface_up(interface)
Prüfe ob ein logisches Netzwerk-Interface aktiv ist.
Definition: network.sh:65
get_on_captive_portal_default(key)
Liefere einen der default-Werte der aktuellen Firmware zurück (Paket on-captive-portal).
get_subdevices_of_interface()
Ermittle die physischen Netzwerk-Geräte (bis auf wifi), die zu einem logischen Netzwerk-Interface geh...
Definition: network.sh:35
get_current_addresses_of_network()
Liefere die IP-Adressen eines logischen Interface inkl. Praefix-Laenge (z.B. 172.16.0.1/24, network).
Definition: network.sh:19
captive_portal_has_devices()
Prüfe, ob dem Captive Portal mindestens ein physisches Netzwerk-Gerät zugeordnet ist.
configure_free_network()
Erzeuge das free-Netzwerk-Interface, falls es noch nicht existiert.
set eu on function print_services services log for dir in etc on services d var on services volatile d
Definition: services:13
is_captive_portal_running()
Prüfe ob der Captive-Portal-Dienst läuft.
get_active_mig_connections()
Liefere die aktiven VPN-Verbindungen (mit Mesh-Internet-Gateways) zurück.
Definition: on-openvpn.sh:33
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
Definition: core.sh:22
captive_portal_set_property(key, value)
Setze ein Attribut der Captive-Portal-Funktion.
set eu grep root::etc shadow exit if which chpasswd dev null
Definition: on-password:12
captive_portal_restart()
Führe einen Neustart der Captive-Portal-Software mit minimalen Seiteneffekten durch.
get_captive_portal_client_count()
Ermittle die Anzahl der verbundenen Clients.
done
Definition: core.sh:81
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
Definition: modules.sh:9
captive_portail_repair_empty_network_bridge()
Reduziere Konstruktionen wie beispielsweise "bridge(None, wlan0)" zu "wlan0".