Opennet Firmware
on-usergw.sh
gehe zur Dokumentation dieser Datei
1## @defgroup on-usergw UserGateway-Funktionen
2# Beginn der Doku-Gruppe
3## @{
4
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://services.opennet-initiative.de/ugw-services.csv
10## auf den UGW-Servern ist via inetd der Dienst "discard" erreichbar
11SPEEDTEST_UPLOAD_PORT=discard
12SPEEDTEST_SECONDS=20
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"
23
24SERVICES_LIST_URLS="${SERVICES_LIST_URLS:-} $UGW_SERVICES_LIST_URL"
25
26
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.
33 _get_file_dict_value "$1" "$ON_USERGW_DEFAULTS_FILE"
34}
36
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.
42 has_openvpn_credentials_by_template "$MESH_OPENVPN_CONFIG_TEMPLATE_FILE" && return 0
43 trap "" EXIT && return 1
45
46
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
53 max_fail_attempts=$(get_on_usergw_default "test_max_fail_attempts")
54 test_period_minutes=$(get_on_usergw_default "test_period_minutes")
55 get_services "mesh" | run_cyclic_service_tests "is_mesh_gateway_usable" "$test_period_minutes" "$max_fail_attempts"
57
58
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"
66 local failed=
67 # WAN-Routing
68 if is_service_routed_via_wan "$service_name"; then
69 set_service_value "$service_name" "wan_status" "true"
70 else
71 failed=1
72 set_service_value "$service_name" "wan_status" "false"
73 fi
74 # Ping-Zeit aktualisieren
75 local ping_time=
76 [ -z "$failed" ] && ping_time=$(get_ping_time "$(get_service_value "$service_name" "host")")
77 set_service_value "$service_name" "wan_ping" "$ping_time"
78 # VPN-Verbindung
79 if [ -n "$failed" ]; then
80 set_service_value "$service_name" "vpn_status" ""
81 else
82 if verify_vpn_connection "$service_name"; then
83 set_service_value "$service_name" "vpn_status" "true"
84 else
85 failed=1
86 set_service_value "$service_name" "vpn_status" "false"
87 fi
88 fi
89 # MTU-Pruefung
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
92 set_service_value "$service_name" "$key" ""
93 done
94 else
95 if [ -z "$(get_openvpn_service_state "$service_name")" ]; then
96 # es läuft aktuell keine Verbindung - wir können testen
97 local mtu_result
98 mtu_result=$(openvpn_get_mtu "$service_name")
99 msg_debug "MTU test result ($service_name): $mtu_result"
100 echo "$mtu_result" | update_mesh_gateway_mtu_state "$service_name"
101 uci_is_true "$(get_service_value "$service_name" "mtu_status" "false")" || failed=1
102 else
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.
107 true
108 fi
109 fi
110 [ -z "$failed" ] && return 0
111 trap "" EXIT && return 1
112}
113
114
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"
122 local host
123 local download_speed
124 local upload_speed
125 host=$(get_service_value "$service_name" "host")
126 download_speed=$(measure_download_speed "$host")
127 upload_speed=$(measure_upload_speed "$host")
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.
132 local prev_download
133 local prev_upload
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 ))"
138 set_service_value "$service_name" "wan_speed_timestamp" "$(get_uptime_minutes)"
139 announce_olsr_service_relay "$service_name"
140}
141
142
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"
151 local host
152 local state
153 local mtu_result
154 local out_wanted
155 local out_real
156 local in_wanted
157 local in_real
158 local status_output
159
160 host=$(get_service_value "$service_name" "host")
161
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"
164
165 mtu_result=$(cat -)
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)
171
172 if [ -z "$mtu_result" ]; then
173 state=""
174 state_label="unknown"
175 elif [ "$out_wanted" -le "$out_real" ] && [ "$in_wanted" -le "$in_real" ]; then
176 state="true"
177 state_label="OK"
178 else
179 state="false"
180 state_label="failure"
181 fi
182
183 set_service_value "$service_name" "mtu_msg" "$status_output"
184 set_service_value "$service_name" "mtu_out_wanted" "$out_wanted"
185 set_service_value "$service_name" "mtu_out_real" "$out_real"
186 set_service_value "$service_name" "mtu_in_wanted" "$in_wanted"
187 set_service_value "$service_name" "mtu_in_real" "$in_real"
188 set_service_value "$service_name" "mtu_status" "$state"
189
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"
192 true
193}
194
195
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.
201 local service_name
202 local conn_count=0
203 local max_connections
204 local service_state
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
207 for service_name in $(get_services "mesh" \
208 | filter_services_by_value "scheme" "openvpn" \
210 service_state=$(get_openvpn_service_state "$service_name")
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
214 [ -z "$service_state" ] && enable_openvpn_service "$service_name"
215 conn_count=$((conn_count + 1))
216 else
217 [ -z "$service_state" ] || disable_openvpn_service "$service_name"
218 fi
219 done
220 apply_changes openvpn
221}
222
223
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):
228# RX TX
229# (empfangene|gesendete KBits/s)
230_get_device_traffic() {
231 local device="$1"
232 local seconds="$2"
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.
238 {
239 cat "$sys_path/statistics/rx_bytes"
240 cat "$sys_path/statistics/tx_bytes"
241 sleep "$seconds"
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'
246}
247
248
249## @fn measure_download_speed()
250## @param host Gegenstelle für den Geschwindigkeitstest.
251## @brief Pruefe Bandbreite durch kurzen Download-Datenverkehr
253 local host="$1"
254 local target_dev
255 target_dev=$(get_target_route_interface "$host")
256 wget -q -O /dev/null "http://$host/.big" &
257 local pid="$!"
258 sleep 3
259 [ ! -d "/proc/$pid" ] && return
260 _get_device_traffic "$target_dev" "$SPEEDTEST_SECONDS" | cut -f 1
261 kill "$pid" 2>/dev/null || true
262}
263
264
265## @fn measure_upload_speed()
266## @param host Gegenstelle für den Geschwindigkeitstest.
267## @brief Pruefe Bandbreite durch kurzen Upload-Datenverkehr
269 local host="$1"
270 local target_dev
271 target_dev=$(get_target_route_interface "$host")
272 nc "$host" "$SPEEDTEST_UPLOAD_PORT" </dev/zero >/dev/null 2>&1 &
273 local pid="$!"
274 sleep 3
275 [ ! -d "/proc/$pid" ] && return
276 _get_device_traffic "$target_dev" "$SPEEDTEST_SECONDS" | cut -f 2
277 kill "$pid" 2>/dev/null || true
278}
279
280
281# Liefere die aktiven VPN-Verbindungen (mit Mesh-Hubs) zurueck.
282# Diese Funktion bracht recht viel Zeit.
283get_active_ugw_connections() {
284 for one_service in $(get_services "mesh"); do
285 [ "$(get_openvpn_service_state "$one_service")" != "active" ] || echo "$one_service"
286 done
287}
288
289
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
295 local target="$1"
296 shift
297 local command
298 is_ipv4 "$target" && command="iptables" || command="ip6tables"
299 "$command" "$@"
300}
301
302
303## @fn disable_on_usergw()
304## @brief Alle mesh-Verbindungen trennen.
306 local service_name
307 local changed=0
308 for service_name in $(get_services "mesh" | filter_services_by_value "scheme" "openvpn"); do
309 if [ -n "$(get_openvpn_service_state "$service_name")" ]; then
310 disable_openvpn_service "$service_name"
311 changed=1
312 fi
313 done
314 [ "$changed" = "0" ] || apply_changes "openvpn"
315}
316
317
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
324 local wan_interface
325 # default route exists? Nothing to fix ...
326 ip route show | grep -q ^default && return 0
327 (
328 # tolerante Shell-Interpretation fuer OpenWrt-Code
329 set +eu
330 # shellcheck source=openwrt/package/base-files/files/lib/functions/network.sh
331 . /lib/functions/network.sh
332 wan_interface=
333 network_find_wan wan_interface
334 if [ -n "$wan_interface" ] && network_is_up "$wan_interface"; then
335 add_banner_event "Missing default route - reinitialize '$wan_interface'"
336 ifup "$wan_interface" || true
337 fi
338 set -eu
339 )
340}
341
342
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
347 if is_on_module_installed_and_enabled "on-usergw"; then
349 # ohne Zertifikat ist nicht mehr zu tun
353 fi
354 else
356 fi
357}
358
359# Ende der Doku-Gruppe
360## @}
set eu case $1 in system dhcp network wireless firewall reload_config true
Definition: 100-on-core:8
_get_file_dict_value(key)
Auslesen eines Werts aus einem Schlüssel/Wert-Eingabestrom.
Definition: core.sh:85
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
Definition: core.sh:9
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
Definition: core.sh:22
key
Definition: core.sh:85
shift
Definition: core.sh:85
done
Definition: core.sh:85
add_banner_event(event, timestamp)
Füge ein Ereignis zum dauerhaften Ereignisprotokoll (/etc/banner) hinzu.
Definition: core.sh:68
is_on_module_installed_and_enabled(module)
Pruefe ob ein Opennet-Modul sowohl installiert, als auch aktiviert ist.
Definition: modules.sh:9
get_ping_time(target, duration)
Ermittle die Latenz eines Ping-Pakets auf dem Weg zu einem Ziel.
Definition: network.sh:14
has_mesh_openvpn_credentials()
Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
Definition: on-usergw.sh:15
update_mesh_gateway_mtu_state()
Falls auf dem Weg zwischen Router und öffentlichem Gateway ein MTU-Problem existiert,...
Definition: on-usergw.sh:35
update_on_usergw_status()
Baue Verbindungen auf oder trenne sie - je nach Modul-Status.
Definition: on-usergw.sh:64
get_on_usergw_default(key)
Hole default-Werte der UGW-Funktionalität der aktuellen Firmware.
Definition: on-usergw.sh:10
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"...
Definition: on-usergw.sh:61
measure_upload_speed(host)
Pruefe Bandbreite durch kurzen Upload-Datenverkehr.
Definition: on-usergw.sh:48
measure_download_speed(host)
Pruefe Bandbreite durch kurzen Download-Datenverkehr.
Definition: on-usergw.sh:44
is_mesh_gateway_usable(service_name)
Prüfe ob der Dienst alle notwendigen Tests besteht.
Definition: on-usergw.sh:24
verify_mesh_gateways()
Durchlaufe die Liste aller Mesh-Gateway-Dienste und aktualisiere deren Status.
Definition: on-usergw.sh:19
disable_on_usergw()
Alle mesh-Verbindungen trennen.
Definition: on-usergw.sh:56
iptables_by_target_family()
Rufe "iptables" oder "ip6tables" (abhängig von einer Ziel-IP, target) mit den gegebenen Parametern au...
Definition: on-usergw.sh:53
update_relayed_server_speed_estimation(service_name)
Schätze die Upload- und Download-Geschwindigkeit zu dem Dienstanbieter ab. Aktualisiere anschließend ...
Definition: on-usergw.sh:29
sync_mesh_openvpn_connection_processes()
Erzeuge openvpn-Konfigurationen für die als nutzbar markierten Dienste und entferne die Konfiguration...
Definition: on-usergw.sh:40
openvpn_get_mtu()
Ermittle die MTU auf dem Weg zum Anbieter des Diensts.
Definition: openvpn.sh:72
has_openvpn_credentials_by_template(template_file)
Prüft, ob der Nutzer bereits einen Schlüssel und ein Zertifikat angelegt hat.
Definition: openvpn.sh:54
disable_openvpn_service(service_name)
Löschung einer openvpn-Verbindung.
Definition: openvpn.sh:19
verify_vpn_connection(service_name, key, cert)
Prüfe einen VPN-Verbindungsaufbau.
Definition: openvpn.sh:43
get_openvpn_service_state(service_name)
Prüfe ob eine openvpn-Verbindung besteht bzw. im Aufbau ist.
Definition: openvpn.sh:25
enable_openvpn_service()
Erzeuge eine funktionierende openvpn-Konfiguration (Datei + UCI, service_name).
Definition: openvpn.sh:9
get_target_route_interface(target)
Ermittle das Netzwerkinterface, über den der Verkehr zu einem Ziel laufen würde.
Definition: routing.sh:25
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
Definition: routing.sh:8
sort_services_by_priority()
Sortiere den eingegebenen Strom von Dienstnamen und gib eine nach der Priorität sortierte Liste.
Definition: services.sh:37
run_cyclic_service_tests(test_function)
Durchlaufe alle via STDIN angegebenen Dienste bis mindestens ein Test erfolgreich ist.
Definition: services.sh:177
is_service_routed_via_wan(service_name)
Pruefe ob der Verkehr zum Anbieter des Diensts über ein WAN-Interface verlaufen würde.
Definition: services.sh:148
set_service_value()
Setzen eines oder mehrerer Werte fuer einen Dienst. Je nach Schluesselname wird der Inhalt in die per...
Definition: services.sh:79
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird,...
Definition: services.sh:68
get_service_value(key, default)
Auslesen eines Werts aus der Service-Datenbank.
Definition: services.sh:86
filter_services_by_value(key, value)
Definition: services.sh:74
if[-d "/etc/on-firewall.d/"]
set eu grep root::etc shadow exit if command v chpasswd dev null
Definition: on-password:12
set eu on function print_services services log for dir in etc on services d var on services volatile d
Definition: services:13