1 ## @defgroup on-usergw UserGateway-Funktionen 2 # Beginn der Doku-Gruppe 5 # shellcheck disable=SC2034 6 UGW_STATUS_FILE=/tmp/on-ugw_gateways.status
7 ON_USERGW_DEFAULTS_FILE=/usr/share/opennet/usergw.defaults
8 MESH_OPENVPN_CONFIG_TEMPLATE_FILE=/usr/share/opennet/openvpn-ugw.template
9 UGW_SERVICES_LIST_URL=https:
10 ## auf den UGW-Servern ist via inetd der Dienst "discard" erreichbar 11 SPEEDTEST_UPLOAD_PORT=discard
13 ## dieser Wert muss mit der VPN-Konfigurationsvorlage synchron gehalten werden 14 # shellcheck disable=SC2034 15 MESH_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. 22 PERSISTENT_SERVICE_ATTRIBUTES=
"${PERSISTENT_SERVICE_ATTRIBUTES:-} local_relay_port status vpn_status wan_status mtu_status" 24 SERVICES_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" 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" 190 msg_debug "mtu [$state_label]: update_mesh_gateway_mtu_state for '$host' done" 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 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.
283 get_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 update_mesh_gateway_firewall_rules() 304 ## @brief markiere alle lokal erzeugten Pakete, die an einen mesh-Gateway-Dienst adressiert sind 305 ## @details Diese Markierung ermöglicht die Filterung (throw) der Pakete für mesh-Gateways in der 306 ## Nutzer-Tunnel-Routingtabelle. 312 local chain=
"on_tos_mesh_vpn" 313 # Chain erzeugen oder leeren (falls sie bereits existiert) 314 iptables -t
mangle --
new-chain
"$chain" 2>/dev/
null || iptables -t
mangle --flush
"$chain" 315 ip6tables -t
mangle --
new-chain
"$chain" 2>/dev/
null || ip6tables -t
mangle --flush
"$chain" 316 # falls es keinen Tunnel-Anbieter gibt, ist nichts zu tun 317 [ -z
"${TOS_NON_TUNNEL:-}" ] &&
return 0
318 # Regeln fuer jeden mesh-Gateway aufstellen 324 # unaufloesbare Hostnamen ignorieren 325 [ -z
"$target_ip" ] &&
continue 327 --destination
"$target_ip" --protocol
"$protocol" --dport
"$port" \
328 -j TOS --
set-tos
"$TOS_NON_TUNNEL" 334 ## @fn disable_on_usergw() 335 ## @brief Alle mesh-Verbindungen trennen. 340 if [ -n
"$(get_openvpn_service_state "$service_name
")" ]; then
345 [
"$changed" =
"0" ] || apply_changes
"openvpn" 349 ## @fn fix_wan_route_if_missing() 350 ## @brief Prüfe, ob die default-Route trotz aktivem WAN-Interface fehlt. In diesem Fall füge sie 351 ## mit "ifup wan" wieder hinzu. 352 ## @details Die Ursache für die fehlende default-Route ist unklar. 354 trap
'error_trap fix_wan_route_if_missing "$*"' EXIT
356 # default route exists? Nothing to fix ... 357 ip route show | grep -q ^
default &&
return 0
359 # tolerante Shell-Interpretation fuer OpenWrt-Code 361 # shellcheck source=openwrt/package/base-files/files/lib/functions/network.sh 362 . /lib/functions/network.sh
364 network_find_wan wan_interface
365 if [ -n
"$wan_interface" ] && network_is_up
"$wan_interface"; then
367 ifup
"$wan_interface" ||
true 375 ## @brief Baue Verbindungen auf oder trenne sie - je nach Modul-Status. 377 trap
'error_trap update_on_usergw_status "$*"' EXIT
381 # ohne Zertifikat ist nicht mehr zu tun 391 # Ende der Doku-Gruppe measure_upload_speed(host)
Pruefe Bandbreite durch kurzen Upload-Datenverkehr.
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird...
measure_download_speed(host)
Pruefe Bandbreite durch kurzen Download-Datenverkehr.
openvpn_get_mtu()
Ermittle die MTU auf dem Weg zum Anbieter des Diensts.
add_banner_event(event, timestamp)
Füge ein Ereignis zum dauerhaften Ereignisprotokoll (/etc/banner) hinzu.
update_relayed_server_speed_estimation(service_name)
Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend ...
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
is_mesh_gateway_usable(service_name)
Prüfe ob der Dienst alle notwendigen Tests besteht.
sync_mesh_openvpn_connection_processes()
Erzeuge openvpn-Konfigurationen für die als nutzbar markierten Dienste und entferne die Konfiguration...
set_service_value()
Setzen eines oder mehrerer Werte fuer einen Dienst. Je nach Schluesselname wird der Inhalt in die per...
update_on_usergw_status()
Baue Verbindungen auf oder trenne sie - je nach Modul-Status.
_get_file_dict_value(key)
Auslesen eines Werts aus einem Schlüssel/Wert-Eingabestrom.
run_cyclic_service_tests(test_function)
Durchlaufe alle via STDIN angegebenen Dienste bis mindestens ein Test erfolgreich ist...
iptables_by_target_family()
Rufe "iptables" oder "ip6tables" (abhängig von einer Ziel-IP, target) mit den gegebenen Parametern au...
update_mesh_gateway_mtu_state()
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, service_name) dies nicht festellten. Daher müssen wir auch den MTU-Pfad auswerten lassen.
sort_services_by_priority()
Sortiere den eingegebenen Strom von Dienstnamen und gib eine nach der Priorität sortierte Liste...
filter_services_by_value(key, value)
set eu grep root::etc shadow exit if command v chpasswd dev null
disable_on_usergw()
Alle mesh-Verbindungen trennen.
has_mesh_openvpn_credentials()
Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
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).
filter_routable_addresses()
Filtere aus einer Menge von Ziel-IPs diejenigen heraus, für die eine passende Routing-Regel existiert...
get_on_usergw_default(key)
Hole default-Werte der UGW-Funktionalität der aktuellen Firmware.
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
set eu on function print_services services log for dir in etc on services d var on services volatile d
get_service_value(key, default)
Auslesen eines Werts aus der Service-Datenbank.
verify_vpn_connection(service_name, key, cert)
Prüfe einen VPN-Verbindungsaufbau.
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
is_service_routed_via_wan(service_name)
Pruefe ob der Verkehr zum Anbieter des Diensts über ein WAN-Interface verlaufen würde.
get_ping_time(target, duration)
Ermittle die Latenz eines Ping-Pakets auf dem Weg zu einem Ziel.
get_target_route_interface(target)
Ermittle das Netzwerkinterface, über den der Verkehr zu einem Ziel laufen würde.
verify_mesh_gateways()
Durchlaufe die Liste aller Mesh-Gateway-Dienste und aktualisiere deren Status.
set eu for table in filter nat mangle
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.
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
update_mesh_gateway_firewall_rules()
markiere alle lokal erzeugten Pakete, die an einen mesh-Gateway-Dienst adressiert sind ...
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"...