Opennet Firmware
 Alle Dateien Funktionen Variablen Gruppen Seiten
service-relay.sh
gehe zur Dokumentation dieser Datei
1 ## @defgroup on-service-relay Dienst-Weiterleitungen
2 # Beginn der Doku-Gruppe
3 ## @{
4 
5 ## für die Kompatibilität mit Firmware vor v0.5
6 UGW_LOCAL_SERVICE_PORT_LEGACY=1600
7 DEFAULT_MESH_OPENVPN_PORT=1602
8 ## falls mehr als ein GW-Dienst weitergereicht wird, wird dieser Port und die folgenden verwendet
9 SERVICE_RELAY_LOCAL_RELAY_PORT_START=5100
10 
11 
12 # Pruefung ob ein lokaler Port bereits fuer einen ugw-Dienst weitergeleitet wird
13 _is_local_service_relay_port_unused() {
14  local port="$1"
15  local collisions
16  collisions=$(get_services | filter_services_by_value "local_relay_port" "$port")
17  [ -n "$collisions" ] && trap "" $GUARD_TRAPS && return 1
18  # keine Kollision entdeckt
19  return 0
20 }
21 
22 
23 # Liefere den Port zurueck, der einer Dienst-Weiterleitung lokal zugewiesen wurde.
24 # Falls noch kein Port definiert ist, dann waehle einen neuen Port.
25 # Parameter: config_name
26 pick_local_service_relay_port() {
27  trap "error_trap pick_local_service_relay_port '$*'" $GUARD_TRAPS
28  local service_name="$1"
29  local port
30  port=$(get_service_value "$service_name" "local_relay_port")
31  # falls unbelegt: suche einen unbenutzten lokalen Port
32  if [ -z "$port" ]; then
33  # fuer IGW-Verbindungen: belege zuerst den alten Standard-Port (fuer alte Clients)
34  if [ "$(get_service_value "$service_name" "service")" = "gw" ]; then
35  _is_local_service_relay_port_unused "$UGW_LOCAL_SERVICE_PORT_LEGACY" \
36  && port="$UGW_LOCAL_SERVICE_PORT_LEGACY"
37  true
38  fi
39  fi
40  if [ -z "$port" ]; then
41  port="$SERVICE_RELAY_LOCAL_RELAY_PORT_START"
42  until _is_local_service_relay_port_unused "$port"; do
43  : $((port++))
44  done
45  fi
46  set_service_value "$service_name" "local_relay_port" "$port"
47  echo "$port"
48 }
49 
50 
51 ## @fn update_relay_firewall_rules
52 ## @brief Erstelle die Liste aller Firewall-Regeln fuer Service-Relay-Weiterleitungen neu.
53 ## @details Diese Funktion wird als Teil des Firewall-Reload-Prozess und nach Service-Relay-Aenderungen
54 ## aufgerufen.
55 update_relay_firewall_rules() {
56  trap "error_trap update_relay_firewall_rules '$*'" $GUARD_TRAPS
57  local host
58  local port
59  local protocol
60  local target_ip
61  local main_ip
62  local dnat_chain="on_service_relay_dnat"
63  local parent_dnat_chain="prerouting_${ZONE_MESH}_rule"
64  local tos_chain="on_service_relay_tos"
65  local parent_tos_chain="PREROUTING"
66  main_ip=$(get_main_ip)
67  # neue Chains erzeugen
68  iptables -t nat --new-chain "$dnat_chain" 2>/dev/null || iptables -t nat --flush "$dnat_chain"
69  iptables -t mangle --new-chain "$tos_chain" 2>/dev/null || iptables -t mangle --flush "$tos_chain"
70  # Verweis auf die neue Chain erzeugen
71  iptables -t nat --check "$parent_dnat_chain" -j "$dnat_chain" 2>/dev/null \
72  || iptables -t nat --insert "$parent_dnat_chain" -j "$dnat_chain"
73  iptables -t mangle --check "$parent_tos_chain" -j "$tos_chain" 2>/dev/null \
74  || iptables -t mangle --insert "$parent_tos_chain" -j "$tos_chain"
75  # DNAT- und TOS-Chain fuellen
76  get_services | filter_relay_services | while read service; do
77  is_service_relay_possible "$service" || continue
78  host=$(get_service_value "$service" "host")
79  port=$(get_service_value "$service" "port")
80  protocol=$(get_service_value "$service" "protocol")
81  local_port=$(get_service_value "$service" "local_relay_port")
82  target_ip=$(query_dns "$host" | filter_routable_addresses | tail -n 1)
83  iptables -t nat -A "$dnat_chain" --destination "$main_ip" --protocol "$protocol" --dport "$local_port" \
84  -j DNAT --to-destination "${target_ip}:${port}"
85  # falls on-openvpn vorhanden ist, wollen wir vermeiden, dass mesh-Tunnel ueber den Internet-Tunnel laufen
86  [ -z "${TOS_NON_TUNNEL:-}" ] || iptables -t mangle -A "$tos_chain" --destination "$main_ip" \
87  --protocol "$protocol" --dport "$local_port" -j TOS --set-tos "$TOS_NON_TUNNEL"
88  done
89 
90 }
91 
92 
93 _get_service_relay_olsr_announcement_prefix() {
94  trap "error_trap _get_service_relay_olsr_announcement_prefix '$*'" $GUARD_TRAPS
95  local service_name="$1"
96  local main_ip
97  local service_type
98  local scheme
99  local host
100  local port
101  local protocol
102  main_ip=$(get_main_ip)
103  service_type=$(get_service_value "$service_name" "service")
104  # remove prefix
105  service_type="${service_type#$RELAYABLE_SERVICE_PREFIX}"
106  scheme=$(get_service_value "$service_name" "scheme")
107  host=$(get_service_value "$service_name" "host")
108  port=$(pick_local_service_relay_port "$service_name")
109  protocol=$(get_service_value "$service_name" "protocol")
110  # announce the service
111  echo "${scheme}://${main_ip}:${port}|${protocol}|${service_type}"
112 }
113 
114 
115 ## @fn get_service_relay_olsr_announcement()
116 ## @brief Ermittle den oder die OLSR-Nameservice-Announcements, die zu dem Dienst gehoeren.
117 get_service_relay_olsr_announcement() {
118  trap "error_trap get_service_relay_olsr_announcement '$*'" $GUARD_TRAPS
119  local service_name="$1"
120  local announce_unique
121  local uci_prefix
122  announce_unique=$(_get_service_relay_olsr_announcement_prefix "$service_name")
123  uci_prefix=$(get_and_enable_olsrd_library_uci_prefix "nameservice")
124  uci_get_list "${uci_prefix}.service" | awk '{ if ($1 == "'$announce_unique'") print $0; }'
125 }
126 
127 
128 ## @fn announce_olsr_service_relay()
129 ## @brief Verkuende das lokale Relay eines öffentlichen Dienstes inkl. Geschwindigkeitsdaten via olsr nameservice.
130 ## @param service_name Name des zu veröffentlichenden Diensts
131 ## @attention Anschließend muss die uci-Sektion 'olsrd' committed werden.
132 announce_olsr_service_relay() {
133  trap "error_trap announce_olsr_service_relay '$*'" $GUARD_TRAPS
134  local service_name="$1"
135  local service_unique
136  local service_details
137  service_unique=$(_get_service_relay_olsr_announcement_prefix "$service_name")
138  # das 'service_name'-Detail wird fuer die anschliessende Beraeumung (firewall-Regeln usw.) verwendet
139  # nur nicht-leere Attribute werden geschrieben
140  service_details=$(while read key value; do [ -z "$value" ] && continue; echo "$key:$value"; done <<EOF
141  public_host $(get_service_value "$service_name" "host")
142  upload $(get_service_value "$service_name" "wan_speed_upload")
143  download $(get_service_value "$service_name" "wan_speed_download")
144  ping $(get_service_value "$service_name" "wan_ping")
145 EOF
146 )
147  # Zeilenumbrueche durch Leerzeichen ersetzen, abschliessendes Leerzeichen entfernen
148  service_details=$(echo "$service_details" | tr '\n' ' ' | sed 's/ $//')
149  # loesche alte Dienst-Announcements mit demselben Prefix
150  local this_unique
151  local this_details
152  local uci_prefix
153  uci_prefix=$(get_and_enable_olsrd_library_uci_prefix "nameservice")
154  get_service_relay_olsr_announcement "$service_name" | while read this_unique this_details; do
155  # der Wert ist bereits korrekt - wir koennen abbrechen
156  [ "$this_details" = "$service_details" ] && break
157  # der Wert ist falsch: loeschen und am Ende neu hinzufuegen
158  msg_debug "Deleting outdated service-relay announcement: $service_unique $this_details"
159  uci_delete_list "${uci_prefix}.service" "$service_unique $this_details"
160  done
161  # falls keine Treffer gibt, fuegen wir ein neues Announcement hinzu
162  if [ -z "$(get_service_relay_olsr_announcement "$service_name")" ]; then
163  msg_debug "Adding new service-relay announcement: $service_unique $service_details"
164  uci_add_list "${uci_prefix}.service" "$service_unique $service_details"
165  fi
166 }
167 
168 
169 ## @fn get_olsr_relay_service_name_from_description()
170 ## @brief Ermittle den Dienstnamen, der zu einer olsr-Relay-Service-Definition gehoert.
171 get_olsr_relay_service_name_from_description() {
172  trap "error_trap get_olsr_relay_service_name_from_description '$*'" $GUARD_TRAPS
173  local service_description="$1"
174  local fields
175  local port
176  local service_type
177  fields=$(echo "$service_description" | parse_olsr_service_descriptions)
178  port=$(echo "$fields" | cut -f 3)
179  service_type=$(echo "$fields" | cut -f 6)
180  get_services "${RELAYABLE_SERVICE_PREFIX}$service_type" | filter_services_by_value "local_relay_port" "$port"
181 }
182 
183 
184 # olsr-Nameservice-Beschreibungen entfernen falls der dazugehoerige Dienst nicht mehr relay-tauglich ist
185 deannounce_unused_olsr_service_relays() {
186  # wir erwarten einen ausführbaren Testnamen
187  local test_for_activity="$1"
188  local service_description
189  local service_name
190  local uci_prefix
191  uci_prefix=$(get_and_enable_olsrd_library_uci_prefix "nameservice")
192  uci_get_list "${uci_prefix}.service" | while read service_description; do
193  # unbenutzte Eintraege entfernen
194  service_name=$(get_olsr_relay_service_name_from_description "$service_description")
195  [ -z "$service_name" ] && msg_info "Failed to parse olsr service description: $service_description" && continue
196  "$test_for_activity" "$service_name" && continue
197  uci_delete_list "${uci_prefix}.service" "$service_description"
198  done
199  return 0
200 }
201 
202 
203 ## @fn is_service_relay_possible()
204 ## @brief Pruefe ob ein Relay-Dienst aktiviert (nicht "disabled") ist und ob das WAN-Routing korrekt ist.
205 is_service_relay_possible() {
206  trap "error_trap is_service_relay_possible '$*'" $GUARD_TRAPS
207  local service_name="$1"
208  local enabled
209  local wan_routing
210  disabled=$(get_service_value "$service_name" "disabled" "false")
211  uci_is_true "$disabled" && trap "" $GUARD_TRAPS && return 1
212  wan_routing=$(get_service_value "$service_name" "wan_status" "false")
213  uci_is_false "$wan_routing" && trap "" $GUARD_TRAPS && return 1
214  return 0
215 }
216 
217 
218 ## @fn update_service_relay_status()
219 ## @brief Pruefe regelmaessig, ob Weiterleitungen für alle bekannten durchgereichten Diensten existieren.
220 ## @details Fehlende Weiterleitungen oder olsr-Announcements werden angelegt.
221 update_service_relay_status() {
222  trap "error_trap update_service_relay_status '$*'" $GUARD_TRAPS
223  local service_name
224  local wan_status
225  if is_on_module_installed_and_enabled "on-usergw"; then
226  get_services | filter_relay_services | while read service_name; do
227  # WAN-Routing pruefen und aktualisieren
228  is_service_routed_via_wan "$service_name" && wan_status="true" || wan_status="false"
229  set_service_value "$service_name" "wan_status" "$wan_status"
230  is_service_relay_possible "$service_name" || continue
231  announce_olsr_service_relay "$service_name"
232  done
233  update_mesh_gateway_firewall_rules
234  deannounce_unused_olsr_service_relays is_service_relay_possible
235  else
236  deannounce_unused_olsr_service_relays false
237  fi
238  apply_changes olsrd
239 }
240 
241 
242 ## @fn filter_relay_services()
243 ## @brief Filtere aus einer Reihe eingehender Dienste diejenigen heraus, die als Dienst-Relay fungieren.
244 ## @details Die Dienst-Namen werden über die Standardeingabe gelesen und an die Standardausgabe
245 ## weitergeleitet, falls es sich um einen Relay-Dienst handelt.
246 filter_relay_services() {
247  local service_name
248  while read service_name; do
249  [ -n "$(get_service_value "$service_name" "local_relay_port")" ] && echo "$service_name"
250  true
251  done
252 }
253 
254 # Ende der Doku-Gruppe
255 ## @}
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird...
Definition: services.sh:61
while read key value
Definition: core.sh:81
uci_add_list(uci_path, new_item)
Füge einen neuen Wert zu einer UCI-Liste hinzu und achte dabei auf Einmaligkeit.
Definition: uci.sh:10
local key
Definition: core.sh:81
filter_services_by_value(key, value)
Definition: services.sh:67
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
Definition: core.sh:15
uci_delete_list(uci_path, value)
Lösche ein Element einer UCI-Liste.
Definition: uci.sh:33
uci_get_list(uci_path)
Liefere alle einzelenen Elemente einer UCI-Liste zurück.
Definition: uci.sh:15
filter_routable_addresses()
Filtere aus einer Menge von Ziel-IPs diejenigen heraus, für die eine passende Routing-Regel existiert...
Definition: routing.sh:19
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
Definition: core.sh:9
get_service_value(key, default)
Auslesen eines Werts aus der Service-Datenbank.
Definition: services.sh:74
set eu grep root::etc shadow exit if which chpasswd dev null
Definition: on-password:12
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:136
done
Definition: core.sh:81
set eu for table in filter nat mangle
Definition: firewall:10
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
Definition: modules.sh:9