1## @defgroup on-usergw UserGateway-Funktionen
2# Beginn der Doku-Gruppe
5# shellcheck disable=SC2034
6UGW_STATUS_FILE=/tmp/on-ugw_gateways.status
7ON_USERGW_DEFAULTS_FILE=/usr/share/opennet/usergw.defaults
8MESH_OPENVPN_CONFIG_TEMPLATE_FILE=/usr/share/opennet/openvpn-ugw.template
9UGW_SERVICES_LIST_URL=https:
10## auf den UGW-Servern ist via inetd der Dienst "discard" erreichbar
11SPEEDTEST_UPLOAD_PORT=discard
13## dieser Wert muss mit der VPN-Konfigurationsvorlage synchron gehalten werden
14# shellcheck disable=SC2034
15MESH_OPENVPN_DEVICE_PREFIX=tap
16# Die folgenden Attribute werden dauerhaft (im Flash) gespeichert. Häufige Änderungen sind also eher unerwünscht.
17# Gruende fuer ausgefallene/unintuitive Attribute:
18# local_relay_port: der lokale Port, der für eine Dienst-Weiterleitung verwendet wird - er sollte über reboots hinweg stabil sein
19# *status: eine Mesh-Verbindung soll nach dem Booten schnell wieder aufgebaut werden (ohne lange MTU-Tests)
20# Wir beachten den vorherigen Zustand der Variable, damit andere Module (z.B. on-usergw) diese
21# ebenfalls beeinflussen können.
22PERSISTENT_SERVICE_ATTRIBUTES=
"${PERSISTENT_SERVICE_ATTRIBUTES:-} local_relay_port status vpn_status wan_status mtu_status"
24SERVICES_LIST_URLS=
"${SERVICES_LIST_URLS:-} $UGW_SERVICES_LIST_URL"
27## @fn get_on_usergw_default()
28## @param key Schlüssel des gewünschten default-Werts.
29## @brief Hole default-Werte der UGW-Funktionalität der aktuellen Firmware.
30## @details Die default-Werte werden nicht von der Konfigurationsverwaltung uci verwaltet.
31## Somit sind nach jedem Upgrade imer die neuesten Standard-Werte verfuegbar.
37## @fn has_mesh_openvpn_credentials()
38## @brief Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
39## @returns Liefert "wahr", falls Schlüssel und Zertifikat vorhanden sind oder
40## falls in irgendeiner Form Unklarheit besteht.
43 trap
"" EXIT &&
return 1
47## @fn verify_mesh_gateways()
48## @brief Durchlaufe die Liste aller Mesh-Gateway-Dienste und aktualisiere deren Status.
49## @see run_cyclic_service_tests
51 local max_fail_attempts
52 local test_period_minutes
59## @fn is_mesh_gateway_usable()
60## @param service_name zu prüfender Dienst
61## @brief Prüfe ob der Dienst alle notwendigen Tests besteht.
62## @details Ein Test dauert bis zu 5 Minuten. Falls bereits eine VPN-Verbindung besteht, wird der MTU-Test übersprungen.
64 trap
'error_trap is_mesh_gateway_usable "$*"' EXIT
65 local service_name=
"$1"
74 # Ping-Zeit aktualisieren
76 [ -z
"$failed" ] && ping_time=
$(
get_ping_time "$(get_service_value "$service_name
" "host
")")
79 if [ -n
"$failed" ]; then
90 if [ -n
"$failed" ]; then
91 for key in
"mtu_msg" "mtu_out_wanted" "mtu_out_real" "mtu_in_wanted" "mtu_in_real" "mtu_timestamp" "mtu_status";
do
95 if [ -z
"$(get_openvpn_service_state "$service_name
")" ]; then
96 # es läuft aktuell keine Verbindung - wir können testen
99 msg_debug "MTU test result ($service_name): $mtu_result"
101 uci_is_true
"$(get_service_value "$service_name
" "mtu_status
" "false")" || failed=1
103 # Aktuell läuft eine Verbindung: ein MTU-Test würde diese unterbrechen (was zu
104 # wechselseitiger Trennung führen würde). Wir behalten daher das alte mtu-Ergebnis bei.
105 # Ein Abbruch einer Verbindung erfolgt also lediglich, wenn die VPN-Verbindung komplett
106 # nicht mehr nutzbar ist.
110 [ -z
"$failed" ] &&
return 0
111 trap
"" EXIT &&
return 1
115## @fn update_relayed_server_speed_estimation()
116## @brief Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend die Attribute des Diensts.
117## @param service_name der Name des Diensts
118## @details Auf der Gegenseite wird die Datei '.big' fuer den Download via http erwartet.
120 trap
'error_trap update_relayed_server_speed_estimation "$*"' EXIT
121 local service_name=
"$1"
128 # keine Zahlen? Keine Aktualisierung ...
129 [ -z
"$download_speed" ] && [ -z
"$upload_speed" ] &&
return
130 # gleitende Mittelwerte: vorherigen Wert einfliessen lassen
131 # Falls keine vorherigen Werte vorliegen, dann werden die aktuellen verwendet.
134 prev_download=
$(
get_service_value "$service_name" "wan_speed_download" "${download_speed:-0}")
135 prev_upload=
$(
get_service_value "$service_name" "wan_speed_upload" "${upload_speed:-0}")
136 set_service_value "$service_name" "wan_speed_download" "$(( (3 * download_speed + prev_download) / 4 ))"
137 set_service_value "$service_name" "wan_speed_upload" "$(( (3 * upload_speed + prev_upload) / 4 ))"
139 announce_olsr_service_relay
"$service_name"
143## @fn update_mesh_gateway_mtu_state()
144## @brief Falls auf dem Weg zwischen Router und öffentlichem Gateway ein MTU-Problem existiert, dann werden die Daten nur bruchstückhaft fließen, auch wenn alle anderen Symptome (z.B. Ping) dies nicht festellten. Daher müssen wir auch den MTU-Pfad auswerten lassen.
145## @param service_name der Name des Diensts
146## @returns Es erfolgt keine Ausgabe - als Seiteneffekt wird der MTU-Status des Diensts verändert.
147## @details Als Eingabestrom wird die Ausgabe von 'openvpn_get_mtu' erwartet.
149 trap
'error_trap update_mesh_gateway_mtu_state "$*"' EXIT
150 local service_name=
"$1"
162 msg_debug "starting update_mesh_gateway_mtu_state for '$host'"
163 msg_debug "update_mesh_gateway_mtu_state will take around 5 minutes per gateway"
166 out_wanted=
$(echo "$mtu_result" | cut -f 1)
167 out_real=
$(echo "$mtu_result" | cut -f 2)
168 in_wanted=
$(echo "$mtu_result" | cut -f 3)
169 in_real=
$(echo "$mtu_result" | cut -f 4)
170 status_output=
$(echo "$mtu_result" | cut -f 5)
172 if [ -z "$mtu_result" ]; then
174 state_label="unknown"
175 elif [ "$out_wanted" -le "$out_real" ] && [ "$in_wanted" -le "$in_real" ]; then
180 state_label="failure"
191 [ -n "$status_output" ] &&
msg_debug "mtu [$state_label]: $status_output"
196## @fn sync_mesh_openvpn_connection_processes()
197## @brief Erzeuge openvpn-Konfigurationen für die als nutzbar markierten Dienste und entferne
198## die Konfigurationen von unbrauchbaren Dienste. Dabei wird auch die maximale Anzahl von
199## mesh-OpenVPN-Verbindungen beachtet.
203 local max_connections
205 # diese Festlegung ist recht willkürlich: auf Geräten mit nur 32 MB scheinen wir jedenfalls nahe der Speichergrenze zu arbeiten
206 [
"$(get_memory_size)" -gt 32 ] && max_connections=5 || max_connections=1
211 if [
"$conn_count" -lt
"$max_connections" ] \
212 && uci_is_true
"$(get_service_value "$service_name
" "status
" "false")" \
213 && uci_is_false
"$(get_service_value "$service_name
" "disabled
" "false")"; then
215 conn_count=
$((conn_count + 1))
220 apply_changes openvpn
224# Messung des durchschnittlichen Verkehrs ueber ein Netzwerkinterface innerhalb einer gewaehlten Zeitspanne.
225# Parameter: physisches Netzwerkinterface (z.B. eth0)
226# Parameter: Anzahl von Sekunden der Messung
227# Ergebnis (tab-separiert):
229# (empfangene|gesendete KBits/s)
230_get_device_traffic() {
233 local sys_path=
"/sys/class/net/$device"
234 [ ! -
d "$sys_path" ] &&
msg_error "Failed to find '$sys_path' for '_get_device_traffic'" &&
return 0
235 # Ausgabe einer Zeile mit vier Zahlen: start_rx start_tx end_rx end_tx
236 # Die sed-Filterung am Ende sorgt dafür, dass negative Zahlen (bei zwischenzeitlicher
237 # Interface-Neukonfiguration) durch eine Null ersetzt werden.
239 cat
"$sys_path/statistics/rx_bytes"
240 cat
"$sys_path/statistics/tx_bytes"
242 cat
"$sys_path/statistics/rx_bytes"
243 cat
"$sys_path/statistics/tx_bytes"
244 } | tr
'\n' ' ' | awk
'{ print int((8 * ($3-$1)) / 1024 / '"$seconds"' + 0.5) "\t" int((8 * ($4-$2)) / 1024 / '"$seconds"' + 0.5) }' \
245 | sed
's/\(-[[:digit:]]\+\)/0/g'
249## @fn measure_download_speed()
250## @param host Gegenstelle für den Geschwindigkeitstest.
251## @brief Pruefe Bandbreite durch kurzen Download-Datenverkehr
256 wget -q -O /dev/
null "http://$host/.big" &
259 [ ! -
d "/proc/$pid" ] &&
return
260 _get_device_traffic
"$target_dev" "$SPEEDTEST_SECONDS" | cut -f 1
261 kill
"$pid" 2>/dev/
null ||
true
265## @fn measure_upload_speed()
266## @param host Gegenstelle für den Geschwindigkeitstest.
267## @brief Pruefe Bandbreite durch kurzen Upload-Datenverkehr
272 nc
"$host" "$SPEEDTEST_UPLOAD_PORT" </dev/zero >/dev/
null 2>&1 &
275 [ ! -
d "/proc/$pid" ] &&
return
276 _get_device_traffic
"$target_dev" "$SPEEDTEST_SECONDS" | cut -f 2
277 kill
"$pid" 2>/dev/
null ||
true
281# Liefere die aktiven VPN-Verbindungen (mit Mesh-Hubs) zurueck.
282# Diese Funktion bracht recht viel Zeit.
283get_active_ugw_connections() {
285 [
"$(get_openvpn_service_state "$one_service
")" !=
"active" ] || echo
"$one_service"
290## @fn iptables_by_target_family()
291## @brief Rufe "iptables" oder "ip6tables" (abhängig von einer Ziel-IP) mit den gegebenen Parametern aus.
292## @param target die Ziel-IP anhand derer die Protokollfamilie (inet oder inet6) ermittelt wird
293## @param ... alle weiteren Parameter werden direkt an ip(6)tables uebergeben
298 is_ipv4 "$target" && command=
"iptables" || command=
"ip6tables"
303## @fn disable_on_usergw()
304## @brief Alle mesh-Verbindungen trennen.
309 if [ -n
"$(get_openvpn_service_state "$service_name
")" ]; then
314 [
"$changed" =
"0" ] || apply_changes
"openvpn"
318## @fn fix_wan_route_if_missing()
319## @brief Prüfe, ob die default-Route trotz aktivem WAN-Interface fehlt. In diesem Fall füge sie
320## mit "ifup wan" wieder hinzu.
321## @details Die Ursache für die fehlende default-Route ist unklar.
323 trap
'error_trap fix_wan_route_if_missing "$*"' EXIT
325 # default route exists? Nothing to fix ...
326 ip route show | grep -q ^
default &&
return 0
328 # tolerante Shell-Interpretation fuer OpenWrt-Code
330 # shellcheck source=openwrt/package/base-files/files/lib/functions/network.sh
331 . /lib/functions/network.sh
333 network_find_wan wan_interface
334 if [ -n
"$wan_interface" ] && network_is_up
"$wan_interface"; then
336 ifup
"$wan_interface" ||
true
343## @fn update_on_usergw_status()
344## @brief Baue Verbindungen auf oder trenne sie - je nach Modul-Status.
346 trap
'error_trap update_on_usergw_status "$*"' EXIT
349 # ohne Zertifikat ist nicht mehr zu tun
359# Ende der Doku-Gruppe
set eu case $1 in system dhcp network wireless firewall reload_config true
_get_file_dict_value(key)
Auslesen eines Werts aus einem Schlüssel/Wert-Eingabestrom.
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
add_banner_event(event, timestamp)
Füge ein Ereignis zum dauerhaften Ereignisprotokoll (/etc/banner) hinzu.
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
get_ping_time(target, duration)
Ermittle die Latenz eines Ping-Pakets auf dem Weg zu einem Ziel.
has_mesh_openvpn_credentials()
Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
update_mesh_gateway_mtu_state()
Falls auf dem Weg zwischen Router und öffentlichem Gateway ein MTU-Problem existiert,...
update_on_usergw_status()
Baue Verbindungen auf oder trenne sie - je nach Modul-Status.
get_on_usergw_default(key)
Hole default-Werte der UGW-Funktionalität der aktuellen Firmware.
fix_wan_route_if_missing()
Prüfe, ob die default-Route trotz aktivem WAN-Interface fehlt. In diesem Fall füge sie mit "ifup wan"...
measure_upload_speed(host)
Pruefe Bandbreite durch kurzen Upload-Datenverkehr.
measure_download_speed(host)
Pruefe Bandbreite durch kurzen Download-Datenverkehr.
is_mesh_gateway_usable(service_name)
Prüfe ob der Dienst alle notwendigen Tests besteht.
verify_mesh_gateways()
Durchlaufe die Liste aller Mesh-Gateway-Dienste und aktualisiere deren Status.
disable_on_usergw()
Alle mesh-Verbindungen trennen.
iptables_by_target_family()
Rufe "iptables" oder "ip6tables" (abhängig von einer Ziel-IP, target) mit den gegebenen Parametern au...
update_relayed_server_speed_estimation(service_name)
Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend ...
sync_mesh_openvpn_connection_processes()
Erzeuge openvpn-Konfigurationen für die als nutzbar markierten Dienste und entferne die Konfiguration...
openvpn_get_mtu()
Ermittle die MTU auf dem Weg zum Anbieter des Diensts.
has_openvpn_credentials_by_template(template_file)
Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
disable_openvpn_service(service_name)
Löschung einer openvpn-Verbindung.
verify_vpn_connection(service_name, key, cert)
Prüfe einen VPN-Verbindungsaufbau.
get_openvpn_service_state(service_name)
Prüfe ob eine openvpn-Verbindung besteht bzw. im Aufbau ist.
enable_openvpn_service()
Erzeuge eine funktionierende openvpn-Konfiguration (Datei + UCI, service_name).
get_target_route_interface(target)
Ermittle das Netzwerkinterface, über den der Verkehr zu einem Ziel laufen würde.
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
sort_services_by_priority()
Sortiere den eingegebenen Strom von Dienstnamen und gib eine nach der Priorität sortierte Liste.
run_cyclic_service_tests(test_function)
Durchlaufe alle via STDIN angegebenen Dienste bis mindestens ein Test erfolgreich ist.
is_service_routed_via_wan(service_name)
Pruefe ob der Verkehr zum Anbieter des Diensts über ein WAN-Interface verlaufen würde.
set_service_value()
Setzen eines oder mehrerer Werte fuer einen Dienst. Je nach Schluesselname wird der Inhalt in die per...
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird,...
get_service_value(key, default)
Auslesen eines Werts aus der Service-Datenbank.
filter_services_by_value(key, value)
if[-d "/etc/on-firewall.d/"]
set eu grep root::etc shadow exit if command v chpasswd dev null
set eu on function print_services services log for dir in etc on services d var on services volatile d