Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 10 additions & 27 deletions tailscale/rootfs/etc/NetworkManager/dispatcher.d/protect-subnets
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,19 @@
export LOG_FD
# The shebang 'with-contenv-merge' above is identical with 'with-contenv', but doesn't clear the current environment containing the dispatcher variables

# Redirect outputs to the log (&2 is already set up as pipe by s6)
exec 1>&2
if [[ "${LOG_FD:-}" =~ ^[0-9]+$ ]]; then
eval "exec ${LOG_FD}>&1" || true
fi
readonly NM_DISPATCHER_LISTENER_QUEUE=/run/nm-dispatcher-listener-queue

function halt-app() {
bashio::log.error "Failed to protect subnet routes. Halting app to prevent network loss."
echo -n 1 > /run/s6-linux-init-container-results/exitcode
exec /run/s6/basedir/bin/halt
}
# Redirect outputs to the log (though &2 is already set up as pipe by s6)
exec &> /proc/1/fd/1
bashio::log.reinitialize_output

case "${NM_DISPATCHER_ACTION}" in
up|down)
bashio::log.info "Handling Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}"
unprotect-subnet-routes
if ! protect-subnet-routes; then
# Better stop app than risking losing all network connections
halt-app
fi
;;
dhcp4-change|dhcp6-change)
# Do anything only when the addresses are really changed
if [[ "$(unprotect-subnet-routes test)" != "$(protect-subnet-routes test)" ]]; then
bashio::log.info "Handling Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}"
unprotect-subnet-routes
if ! protect-subnet-routes tested; then
# Better stop app than risking losing all network connections
halt-app
fi
up|down|dhcp4-change|dhcp6-change)
bashio::log.debug "Received Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}"
if ! echo "${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}" > "${NM_DISPATCHER_LISTENER_QUEUE}"; then
bashio::log.fatal "Failed to send nm-dispatcher action to listener. Halting app to prevent network loss."
echo -n 1 > /run/s6-linux-init-container-results/exitcode
exec /run/s6/basedir/bin/halt
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.
;;
connectivity-change)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/etc/s6-overlay/s6-rc.d/init-protect-subnets/finish
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Remove subnet protection
# ==============================================================================

unprotect-subnet-routes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Prevent local subnets to be routed toward the tailnet
# ==============================================================================

protect-subnet-routes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
oneshot
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/etc/s6-overlay/s6-rc.d/init-protect-subnets/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Take down the S6 supervision tree when nm-dispatcher-listener fails
# ==============================================================================
readonly exit_code_container=$(</run/s6-linux-init-container-results/exitcode)
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
readonly service="nm-dispatcher-listener"

readonly NM_DISPATCHER_LISTENER_QUEUE=/run/nm-dispatcher-listener-queue

exec 4>&-
rm -rf "${NM_DISPATCHER_LISTENER_QUEUE}"

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_signal}" -ne 15 && "${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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3
52 changes: 52 additions & 0 deletions tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Runs the nm-dispatcher-listener service
# ==============================================================================

readonly NM_DISPATCHER_LISTENER_QUEUE=/run/nm-dispatcher-listener-queue

declare action
declare subnet_routes_to_unprotect
declare subnet_routes_to_protect

mkfifo "${NM_DISPATCHER_LISTENER_QUEUE}"

# Pin it to prevent closing it by other processes
exec 4<>"${NM_DISPATCHER_LISTENER_QUEUE}"
Comment thread
lmagyar marked this conversation as resolved.

# We need to delay the starting of the dependent services until listener queue is created
echo "" >&3
exec 3>&-

while IFS= read -r -u 4 action
do
case "${action}" in
*up|*down)
bashio::log.info "Handling Network Manager action ${action}"
unprotect-subnet-routes
bashio::try protect-subnet-routes
if bashio::try.failed; then
bashio::exit.nok "Failed to protect subnet routes. Halting app to prevent network loss."
fi
;;
*dhcp4-change|*dhcp6-change)
# Do anything only when the addresses are really changed
subnet_routes_to_unprotect="$(unprotect-subnet-routes test)"
subnet_routes_to_protect="$(protect-subnet-routes test)"
if ! bashio::var.equals "${subnet_routes_to_unprotect}" "${subnet_routes_to_protect}"; then
bashio::log.info "Handling Network Manager action ${action}"
unprotect-subnet-routes
bashio::try protect-subnet-routes tested
if bashio::try.failed; then
bashio::exit.nok "Failed to protect subnet routes. Halting app to prevent network loss."
fi
fi
;;
*)
bashio::exit.nok "Unknown Network Manager action ${action}"
;;
esac
done
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
longrun
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Take down the S6 supervision tree when protect-subnets fails
# Take down the S6 supervision tree when nm-dispatcher fails
# ==============================================================================
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
readonly service="nm-dispatcher"

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
if [[ "${exit_code_signal}" -ne 15 && "${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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
export LOG_FD
# ==============================================================================
# Home Assistant Community App: Tailscale
# Prevent local subnets to be routed toward the tailnet
# Runs the nm-dispatcher service
# ==============================================================================

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
1 change: 1 addition & 0 deletions tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
longrun
Original file line number Diff line number Diff line change
@@ -1 +1 @@
longrun
bundle
Loading