-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
246 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
tailscale/rootfs/etc/NetworkManager/dispatcher.d/connectivity-change
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/bash | ||
# DO NOT use #!/command/with-contenv bashio, because that won't set the environment variables | ||
|
||
if [[ "$NM_DISPATCHER_ACTION" == "connectivity-change" ]]; then | ||
if [[ "$CONNECTIVITY_STATE" == "FULL" ]]; then | ||
if ! protect-subnet-routes; then | ||
# Better stop add-on than risking losing all network connections | ||
echo -n 1 > /run/s6-linux-init-container-results/exitcode | ||
exec /run/s6/basedir/bin/halt | ||
fi | ||
else # UNKNOWN, NONE, PORTAL, LIMITED | ||
unprotect-subnet-routes | ||
fi | ||
fi |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
29 changes: 29 additions & 0 deletions
29
tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/finish
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/command/with-contenv bashio | ||
# shellcheck shell=bash | ||
# ============================================================================== | ||
# Home Assistant Community Add-on: Tailscale | ||
# Take down the S6 supervision tree when protect-subnets fails | ||
# ============================================================================== | ||
declare exit_code | ||
readonly exit_code_container=$(</run/s6-linux-init-container-results/exitcode) | ||
readonly exit_code_service="${1}" | ||
readonly exit_code_signal="${2}" | ||
readonly service="protect-subnets" | ||
|
||
unprotect-subnet-routes | ||
|
||
bashio::log.info \ | ||
"Service ${service} exited with code ${exit_code_service}" \ | ||
"(by signal ${exit_code_signal})" | ||
|
||
if [[ "${exit_code_service}" -eq 256 ]]; then | ||
if [[ "${exit_code_container}" -eq 0 ]]; then | ||
echo $((128 + $exit_code_signal)) > /run/s6-linux-init-container-results/exitcode | ||
fi | ||
[[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt | ||
elif [[ "${exit_code_service}" -ne 0 ]]; then | ||
if [[ "${exit_code_container}" -eq 0 ]]; then | ||
echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode | ||
fi | ||
exec /run/s6/basedir/bin/halt | ||
fi |
12 changes: 12 additions & 0 deletions
12
tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/command/with-contenv bashio | ||
# shellcheck shell=bash | ||
# ============================================================================== | ||
# Home Assistant Community Add-on: Tailscale | ||
# Prevent local subnets to be routed toward the tailnet | ||
# ============================================================================== | ||
|
||
protect-subnet-routes | ||
|
||
# runs scripts in /etc/NetworkManager/dispatcher.d | ||
# --debug is used to prevent logging to syslog (HA cli) | ||
exec /usr/libexec/nm-dispatcher --persist --debug > /dev/null |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
longrun |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#!/command/with-contenv bashio | ||
# shellcheck shell=bash | ||
# ============================================================================== | ||
# In case of non userspace networking, | ||
# add local subnets to ip rules with higher priority than Tailscale's routing | ||
# ============================================================================== | ||
|
||
declare -a routes=() | ||
declare route family | ||
declare ipv4_multiple_tables_enabled | ||
declare ipv6_multiple_tables_enabled | ||
declare protected_routes=0 | ||
declare response | ||
declare wait_counter=0 | ||
|
||
if bashio::config.false "userspace_networking"; then | ||
ipv4_multiple_tables_enabled=$(zcat /proc/config.gz | { grep -Ec '^CONFIG_IP_MULTIPLE_TABLES=y$' || true ;}) | ||
ipv6_multiple_tables_enabled=$(zcat /proc/config.gz | { grep -Ec '^CONFIG_IPV6_MULTIPLE_TABLES=y$' || true ;}) | ||
|
||
# If it is called after network configuration is changed, we need to drop cached network info | ||
bashio::cache.flush_all | ||
# It is possible to get "ERROR: Got unexpected response from the API: System is not ready with state: setup" | ||
# So we wait a little | ||
while ! bashio::api.supervisor GET "/addons/self/options/config" false &> /dev/null; do | ||
if (( wait_counter++ == 15 )); then | ||
bashio::log.error "Supervisor is unreachable" | ||
bashio::exit.nok | ||
fi | ||
bashio::log.info "Waiting for the supervisor to be ready..." | ||
sleep 2 | ||
done | ||
if (( wait_counter != 0 )); then | ||
bashio::log.info "Supervisor is ready" | ||
fi | ||
|
||
readarray -t routes < <(subnet-routes) | ||
if (( 0 < ${#routes[@]} )); then | ||
bashio::log.info "Adding advertised local subnets to ip rules with higher priority than Tailscale's routing," | ||
bashio::log.info "to prevent routing advertised local subnets if the same subnet is routed within your tailnet." | ||
fi | ||
for route in "${routes[@]}"; do | ||
if [[ "${route}" =~ .*:.* ]]; then | ||
if (( 0 == ${ipv6_multiple_tables_enabled} )); then | ||
bashio::log.warning " IPv6 multiple routing tables are not enabled, skip adding route ${route} to ip rules" | ||
continue | ||
fi | ||
family="-6" | ||
else | ||
if (( 0 == ${ipv4_multiple_tables_enabled} )); then | ||
bashio::log.warning " IPv4 multiple routing tables are not enabled, skip adding route ${route} to ip rules" | ||
continue | ||
fi | ||
family="-4" | ||
fi | ||
bashio::log.info " Adding route ${route} to ip rules" | ||
if ! response=$(ip "${family}" rule add to "${route}" priority 5000 table main 2>&1); then | ||
if [[ "${response}" != "RTNETLINK answers: File exists" ]]; then | ||
echo "${response}" | ||
bashio::exit.nok | ||
else | ||
bashio::log.notice " Route ${route} is already added to ip rules" | ||
fi | ||
fi | ||
(( protected_routes+=1 )) | ||
done | ||
if (( 0 < ${#routes[@]} && 0 == ${protected_routes} )); then | ||
bashio::log.error "Can't protect any subnets" | ||
bashio::exit.nok | ||
fi | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#!/command/with-contenv bashio | ||
# shellcheck shell=bash | ||
# ============================================================================== | ||
# Print possible subnet routes to stdout | ||
# ============================================================================== | ||
declare interface | ||
declare -a addresses=() | ||
declare -a routes=() | ||
declare ipinfo | ||
declare response | ||
|
||
function appendarray() { | ||
local -n array=${1} | ||
readarray -t -O "${#array[@]}" array | ||
} | ||
|
||
if bashio::cache.exists 'subnet-routes'; then | ||
readarray -t routes < <(bashio::cache.get 'subnet-routes') | ||
printf -v response "%s" "${routes[@]/%/$'\n'}" | ||
else | ||
# Find interfaces and matching addresses from which we can extract routes to be advertised | ||
for interface in $(bashio::network.interfaces); do | ||
appendarray addresses < <(bashio::network.ipv4_address "${interface}") | ||
appendarray addresses < <(bashio::network.ipv6_address "${interface}") | ||
done | ||
|
||
# Extract routes to be advertised | ||
for address in "${addresses[@]}"; do | ||
if bashio::var.has_value "${address}"; then | ||
# Skip local link addresses | ||
if [[ "${address:0:6}" == "fe80::" ]] || [[ "${address:0:8}" == "169.254." ]]; | ||
then | ||
continue | ||
fi | ||
|
||
# Skip if forwarding for the address family is disabled | ||
if [[ "${address}" =~ .*:.* ]]; | ||
then | ||
[[ $(</proc/sys/net/ipv6/conf/all/forwarding) -eq 0 ]] && continue | ||
else | ||
[[ $(</proc/sys/net/ipv4/ip_forward) -eq 0 ]] && continue | ||
fi | ||
|
||
ipinfo="$(/usr/bin/ipcalc --json "${address}")" | ||
routes+=("$(bashio::jq "${ipinfo}" '.NETWORK + "/" + .PREFIX')") | ||
fi | ||
done | ||
|
||
# Remove duplicate entries | ||
readarray -t routes < <(printf "%s" "${routes[@]/%/$'\n'}" | sort -u) | ||
|
||
printf -v response "%s" "${routes[@]/%/$'\n'}" | ||
bashio::cache.set 'subnet-routes' "${response}" | ||
fi | ||
|
||
printf "%s" "${response}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/command/with-contenv bashio | ||
# shellcheck shell=bash | ||
# ============================================================================== | ||
# In case of non userspace networking, | ||
# remove local subnets from ip rules | ||
# ============================================================================== | ||
|
||
declare -a routes=() | ||
declare route family | ||
|
||
if bashio::config.false "userspace_networking"; then | ||
readarray -t routes < <( \ | ||
{ ip -4 rule list; ip -6 rule list; } \ | ||
| { grep -E '^5000:' || true ;} \ | ||
| sed -nr 's/^\d+:\s+from all to ([^\s]+) lookup main$/\1/p') | ||
for route in "${routes[@]}"; do | ||
bashio::log.info "Removing route ${route} from ip rules" | ||
if [[ "${route}" =~ .*:.* ]]; then | ||
family="-6" | ||
else | ||
family="-4" | ||
fi | ||
ip "${family}" rule del to "${route}" | ||
done | ||
fi |