1 ## @defgroup on-usergw UserGateway-Funktionen
2 # Beginn der Doku-Gruppe
5 UGW_STATUS_FILE=/tmp/on-ugw_gateways.status
6 ON_USERGW_DEFAULTS_FILE=/usr/share/opennet/usergw.defaults
7 MESH_OPENVPN_CONFIG_TEMPLATE_FILE=/usr/share/opennet/openvpn-ugw.template
8 TRUSTED_SERVICES_URL=https:
9 ## eine beliebige Portnummer, auf der wir keinen udp-Dienst vermuten
10 SPEEDTEST_UPLOAD_PORT=29418
12 ## dieser Wert muss mit der VPN-Konfigurationsvorlage synchron gehalten werden
13 MESH_OPENVPN_DEVICE_PREFIX=tap
14 # Namenspräfix für weiterzuleitende Dienste
15 RELAYABLE_SERVICE_PREFIX=
"proxy-"
16 UPDATE_TRUSTED_SERVICES_PERIOD_MINUTES=360
19 ## @fn get_on_usergw_default()
20 ## @param key Schlüssel des gewünschten default-Werts.
21 ## @brief Hole default-Werte der UGW-Funktionalität der aktuellen Firmware.
22 ## @details Die default-Werte werden nicht von der Konfigurationsverwaltung uci verwaltet.
23 ## Somit sind nach jedem Upgrade imer die neuesten Standard-Werte verfuegbar.
29 ## @fn has_mesh_openvpn_credentials()
30 ## @brief Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
31 ## @returns Liefert "wahr", falls Schlüssel und Zertifikat vorhanden sind oder
32 ## falls in irgendeiner Form Unklarheit besteht.
35 trap
"" $GUARD_TRAPS &&
return 1
39 ## @fn verify_mesh_gateways()
40 ## @brief Durchlaufe die Liste aller Mesh-Gateway-Dienste und aktualisiere deren Status.
41 ## @see run_cyclic_service_tests
43 local max_fail_attempts
44 local test_period_minutes
51 ## @fn is_mesh_gateway_usable()
52 ## @param service_name zu prüfender Dienst
53 ## @brief Prüfe ob der Dienst alle notwendigen Tests besteht.
54 ## @details Ein Test dauert bis zu 5 Minuten. Falls bereits eine VPN-Verbindung besteht, wird der MTU-Test übersprungen.
56 trap
"error_trap is_mesh_gateway_usable '$*'" $GUARD_TRAPS
57 local service_name=
"$1"
61 set_service_value
"$service_name" "wan_status" "true"
64 set_service_value
"$service_name" "wan_status" "false"
66 # Ping-Zeit aktualisieren
68 [ -z
"$failed" ] && ping_time=$(
get_ping_time "$(get_service_value "$service_name
" "host
")")
69 set_service_value
"$service_name" "wan_ping" "$ping_time"
71 if [ -n
"$failed" ]; then
72 set_service_value
"$service_name" "vpn_status" ""
76 set_service_value
"$service_name" "vpn_status" "true"
79 set_service_value
"$service_name" "vpn_status" "false"
83 if [ -n
"$failed" ]; then
84 for key in
"mtu_msg" "mtu_out_wanted" "mtu_out_real" "mtu_in_wanted" "mtu_in_real" "mtu_timestamp" "mtu_status";
do
85 set_service_value
"$service_name" "$key" ""
88 if [ -z
"$(get_openvpn_service_state "$service_name
")" ]; then
89 # es läuft aktuell keine Verbindung - wir können testen
92 msg_debug "MTU test result ($service_name): $mtu_result"
94 uci_is_true
"$(get_service_value "$service_name
" "mtu_status
" "false")" || failed=1
96 # Aktuell läuft eine Verbindung: ein MTU-Test würde diese unterbrechen (was zu
97 # wechselseitiger Trennung führen würde). Wir behalten daher das alte mtu-Ergebnis bei.
98 # Ein Abbruch einer Verbindung erfolgt also lediglich, wenn die VPN-Verbindung komplett
99 # nicht mehr nutzbar ist.
103 [ -z
"$failed" ] &&
return 0
104 trap
"" $GUARD_TRAPS &&
return 1
108 ## @fn update_trusted_service_list()
109 ## @brief Hole die vertrauenswürdigen Dienste von signierten Opennet-Quellen.
110 ## @details Diese Dienste führen beispielsweise auf UGW-APs zur Konfiguration von Portweiterleitungen
111 ## ins Internet. Daher sind sie nur aus vertrauenswürdiger Quelle zu akzeptieren (oder manuell).
124 url_list=$(https_request_opennet
"$TRUSTED_SERVICES_URL")
125 # leeres Ergebnis? Noch keine Internet-Verbindung? Keine Aktualisierung, keine Beraeumung ...
126 [ -z
"$url_list" ] &&
return
127 echo
"$url_list" | grep -v
"^#" | sed
's/\t\+/\t/g' |
while read line;
do
128 service_type=$(echo
"$line" | cut -f 1)
129 # falls der Dienst-Typ mit
"proxy-" beginnt, soll er weitergeleitet werden
130 if [
"${service_type#$RELAYABLE_SERVICE_PREFIX}" =
"$service_type" ]; then
136 # entferne das Praefix
138 scheme=$(echo
"$line" | cut -f 2)
139 host=$(echo
"$line" | cut -f 3)
140 port=$(echo
"$line" | cut -f 4)
141 protocol=$(echo
"$line" | cut -f 5)
142 priority=$(echo
"$line" | cut -f 6)
143 details=$(echo
"$line" | cut -f 7-)
144 service_name=$(
notify_service "$service_type" "$scheme" "$host" "$port" "$protocol" "/" "trusted" "$details")
145 set_service_value
"$service_name" "priority" "$priority"
146 [ -n
"$is_proxy" ] && pick_local_service_relay_port
"$service_name" >/dev/
null
149 # veraltete Dienste entfernen
151 min_timestamp=$(($(get_uptime_minutes) - $(get_on_core_default
"trusted_service_expire_minutes")))
152 # falls die uptime kleiner ist als die Verfallszeit, dann ist ein Test sinnfrei
153 if [
"$min_timestamp" -gt 0 ]; then
156 |
while read service_name;
do
158 # der Service ist zu lange nicht aktualisiert worden
159 [
"$timestamp" -lt
"$min_timestamp" ] && delete_service
"$service_name"
163 # aktualisiere DNS- und NTP-Dienste
164 apply_changes on-core
169 ## @brief Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend die Attribute des Diensts.
170 ## @param service_name der Name des Diensts
171 ## @details Auf der Gegenseite wird die Datei '.10megabyte' fuer den Download via http erwartet.
173 trap
"error_trap update_public_gateway_speed_estimation '$*'" $GUARD_TRAPS
174 local service_name=
"$1"
181 # keine Zahlen? Keine Aktualisierung ...
182 [ -z
"$download_speed" ] && [ -z
"$upload_speed" ] &&
return
183 # gleitende Mittelwerte: vorherigen Wert einfliessen lassen
184 # Falls keine vorherigen Werte vorliegen, dann werden die aktuellen verwendet.
187 prev_download=$(
get_service_detail "$service_name" "wan_speed_download" "${download_speed:-0}")
188 prev_upload=$(
get_service_detail "$service_name" "wan_speed_upload" "${upload_speed:-0}")
189 set_service_detail "$service_name" "wan_speed_download" "$(( (3 * download_speed + prev_download) / 4 ))"
190 set_service_detail "$service_name" "wan_speed_upload" "$(( (3 * download_speed + prev_upload) / 4 ))"
191 set_service_value
"$service_name" "wan_speed_timestamp" "$(get_uptime_minutes)"
196 ## @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.
197 ## @param service_name der Name des Diensts
198 ## @returns Es erfolgt keine Ausgabe - als Seiteneffekt wird der MTU-Status des Diensts verändert.
199 ## @details Als Eingabestrom wird die Ausgabe von 'openvpn_get_mtu' erwartet.
201 trap
"error_trap update_mesh_gateway_mtu_state '$*'" $GUARD_TRAPS
202 local service_name=
"$1"
214 msg_debug "starting update_mesh_gateway_mtu_state for '$host'"
215 msg_debug "update_mesh_gateway_mtu_state will take around 5 minutes per gateway"
218 out_wanted=$(echo
"$mtu_result" | cut -f 1)
219 out_real=$(echo
"$mtu_result" | cut -f 2)
220 in_wanted=$(echo
"$mtu_result" | cut -f 3)
221 in_real=$(echo
"$mtu_result" | cut -f 4)
222 status_output=$(echo
"$mtu_result" | cut -f 5)
224 if [ -z
"$mtu_result" ]; then
226 state_label=
"unknown"
227 elif [
"$out_wanted" -le
"$out_real" ] && [
"$in_wanted" -le
"$in_real" ]; then
232 state_label=
"failure"
235 set_service_value
"$service_name" "mtu_msg" "$status_output"
236 set_service_value
"$service_name" "mtu_out_wanted" "$out_wanted"
237 set_service_value
"$service_name" "mtu_out_real" "$out_real"
238 set_service_value
"$service_name" "mtu_in_wanted" "$in_wanted"
239 set_service_value
"$service_name" "mtu_in_real" "$in_real"
240 set_service_value
"$service_name" "mtu_status" "$state"
242 msg_debug "mtu [$state_label]: update_mesh_gateway_mtu_state for '$host' done"
243 [ -n
"$status_output" ] &&
msg_debug "mtu [$state_label]: $status_output"
248 ## @fn sync_mesh_openvpn_connection_processes()
249 ## @brief Erzeuge openvpn-Konfigurationen für die als nutzbar markierten Dienste und entferne
250 ## die Konfigurationen von unbrauchbaren Dienste. Dabei wird auch die maximale Anzahl von
251 ## mesh-OpenVPN-Verbindungen beachtet.
255 local max_connections
257 # diese Festlegung ist recht willkürlich: auf Geräten mit nur 32 MB scheinen wir jedenfalls nahe der Speichergrenze zu arbeiten
258 [
"$(get_memory_size)" -gt 32 ] && max_connections=3 || max_connections=1
262 |
while read service_name;
do
264 if [
"$conn_count" -lt
"$max_connections" ] \
265 && uci_is_true
"$(get_service_value "$service_name
" "status
" "false")" \
266 && uci_is_false
"$(get_service_value "$service_name
" "disabled
" "false")"; then
274 apply_changes openvpn
278 # Messung des durchschnittlichen Verkehrs ueber ein Netzwerkinterface innerhalb einer gewaehlten Zeitspanne.
279 # Parameter: physisches Netzwerkinterface (z.B. eth0)
280 # Parameter: Anzahl von Sekunden der Messung
281 # Ergebnis (tab-separiert):
283 # (empfangene|gesendete KBits/s)
284 _get_device_traffic() {
287 local sys_path=
"/sys/class/net/$device"
288 [ ! -
d "$sys_path" ] &&
msg_error "Failed to find '$sys_path' for '_get_device_traffic'" &&
return 0
290 cat
"$sys_path/statistics/rx_bytes"
291 cat
"$sys_path/statistics/tx_bytes"
293 cat
"$sys_path/statistics/rx_bytes"
294 cat
"$sys_path/statistics/tx_bytes"
295 } | tr
'\n' ' ' | awk
'{ print int((8 * ($3-$1)) / 1024 / '$seconds
' + 0.5) "\t" int((8 * ($4-$2)) / 1024 / '$seconds
' + 0.5) }'
299 ## @fn measure_download_speed()
300 ## @param host Gegenstelle für den Geschwindigkeitstest.
301 ## @brief Pruefe Bandbreite durch kurzen Download-Datenverkehr
306 wget -q -O /dev/
null "http://$host/.big" &
309 [ ! -
d "/proc/$pid" ] &&
return
310 _get_device_traffic
"$target_dev" "$SPEEDTEST_SECONDS" | cut -f 1
311 kill
"$pid" 2>/dev/
null ||
true
316 ## @param host Gegenstelle für den Geschwindigkeitstest.
317 ## @brief Pruefe Bandbreite durch kurzen Upload-Datenverkehr
322 # UDP-Verkehr laesst sich auch ohne einen laufenden Dienst auf der Gegenseite erzeugen
323 nc -u
"$host" "$SPEEDTEST_UPLOAD_PORT" </dev/zero >/dev/
null 2>&1 &
326 [ ! -
d "/proc/$pid" ] &&
return
327 _get_device_traffic
"$target_dev" "$SPEEDTEST_SECONDS" | cut -f 2
328 kill
"$pid" 2>/dev/
null ||
true
332 # Liefere die aktiven VPN-Verbindungen (mit Mesh-Hubs) zurueck.
333 # Diese Funktion bracht recht viel Zeit.
334 get_active_ugw_connections() {
336 [
"$(get_openvpn_service_state "$one_service
")" =
"active" ] && echo
"$one_service" ||
true
341 ## update_mesh_gateway_firewall_rules()
342 ## @brief markiere alle lokal erzeugten Pakete, die an einen mesh-Gateway-Dienst adressiert sind
343 ## @details Diese Markierung ermöglicht die Filterung (throw) der Pakete für mesh-Gateways in der
344 ## Nutzer-Tunnel-Routingtabelle.
345 update_mesh_gateway_firewall_rules() {
350 local chain=
"on_tos_mesh_vpn"
351 # Chain erzeugen oder leeren (falls sie bereits existiert)
352 iptables -t
mangle --
new-chain
"$chain" 2>/dev/
null || iptables -t
mangle --flush
"$chain"
353 # falls es keinen Tunnel-Anbieter gibt, ist nichts zu tun
354 [ -z
"${TOS_NON_TUNNEL:-}" ] &&
return 0
355 # Regeln fuer jeden mesh-Gateway aufstellen
361 # unaufloesbare Hostnamen ignorieren
362 [ -z
"$target_ip" ] &&
continue
363 iptables -t
mangle --insert
"$chain" --destination
"$host" --protocol
"$protocol" --dport
"$port" \
364 -j TOS --set-tos
"$TOS_NON_TUNNEL"
369 ## @fn disable_on_usergw()
370 ## @brief Alle mesh-Verbindungen trennen.
376 |
while read service_name;
do
380 done | grep -q . && apply_changes openvpn
386 ## @brief Ermittle ob mindestens ein Zeitstempel für einen "trusted" Dienst vorhanden ist, der nicht älter
387 ## als die vorgegebene Aktualisierungsperiode ist.
388 ## @returns Wahr, falls kein Diest mit aktuellem Zeitstempel gefunden wurde.
390 trap
"error_trap is_trusted_service_list_outdated '$*'" $GUARD_TRAPS
391 local most_recent_timestamp
396 # kein Zeitstempel -> dies gilt als
"veraltet"
397 [ -z
"$most_recent_timestamp" ] &&
return 0
398 # der aktuellste Zeitstempel ist zu alt
399 is_timestamp_older_minutes
"$most_recent_timestamp" "$UPDATE_TRUSTED_SERVICES_PERIOD_MINUTES" &&
return 0
400 trap
"" $GUARD_TRAPS &&
return 1
405 ## @brief Baue Verbindungen auf oder trenne sie - je nach Modul-Status.
409 update_mesh_gateway_firewall_rules
410 # ohne Zertifikat ist nicht mehr zu tun
420 # 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.
notify_service()
Aktualisiere den Zeitstempel und die Entfernung (etx) eines Dienstes.
openvpn_get_mtu()
Ermittle die MTU auf dem Weg zum Anbieter des Diensts.
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...
update_public_gateway_speed_estimation(service_name)
Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend ...
pipe_service_attribute(key, default)
Liefere zu einer Reihe von Diensten ein gewähltes Attribut dieser Dienste zurück. ...
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...
prepare_openvpn_service(Name)
Erzeuge oder aktualisiere einen OpenVPN-Dienst.
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)
disable_on_usergw()
markiere alle lokal erzeugten Pakete, die an einen mesh-Gateway-Dienst adressiert sind ...
set_service_detail(service_name, key, value)
Setze den Wert eines Schlüssel-Wert-Paars im "details"-Attribut eines Diensts.
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.
update_trusted_service_list()
Hole die vertrauenswürdigen Dienste von signierten Opennet-Quellen.
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.
get_service_detail(service_name, key, default)
Ermittle den Wert eines Schlüssel-Wert-Paars im "details"-Attribut eines Diensts. ...
set eu grep root::etc shadow exit if which chpasswd dev null
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_trusted_service_list_outdated()
Ermittle ob mindestens ein Zeitstempel für einen "trusted" Dienst vorhanden ist, der nicht älter als ...
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.