relay: bind the host LAN IP, admit the podman bridge subnet only
169.254.1.2 is not a local address on this host (netavark runs its bridges in aardvark-dns' netns), so the relay cannot bind it — and a loopback bind refuses container traffic. Probe-socket proof: a host socket on 192.168.0.143:18094 answers the container's 169.254.1.2:18094 dial while the LAN IP refuses from the container. The relay binds 192.168.0.143:18093 and the deployer installs an iptables INPUT pair (ACCEPT 10.89.0.0/16, DROP rest) so the unauthenticated endpoint stays off the LAN.
This commit is contained in:
@@ -231,17 +231,24 @@ install_signal_relay() {
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable signal-relay.service
|
||||
systemctl --user restart signal-relay.service
|
||||
# The relay binds the host's LAN IP (the one address a bridge container
|
||||
# can reach as host.containers.internal), so keep the unauthenticated
|
||||
# endpoint off the rest of the LAN: admit the podman bridge subnet
|
||||
# only. Idempotent: -C before -I.
|
||||
run_privileged iptables -C INPUT -p tcp --dport 18093 -s 10.89.0.0/16 -j ACCEPT 2>/dev/null \
|
||||
|| run_privileged iptables -I INPUT -p tcp --dport 18093 -s 10.89.0.0/16 -j ACCEPT
|
||||
run_privileged iptables -C INPUT -p tcp --dport 18093 -j DROP 2>/dev/null \
|
||||
|| run_privileged iptables -I INPUT -p tcp --dport 18093 -j DROP
|
||||
# The interpreter needs a moment to bind after restart; a one-shot curl
|
||||
# raced the socket on 2026-09-17 and failed a healthy deploy. The relay
|
||||
# binds 169.254.1.2 (host.containers.internal), not loopback.
|
||||
# raced the socket on 2026-09-17 and failed a healthy deploy.
|
||||
local i
|
||||
for i in $(seq 1 15); do
|
||||
if curl -fsS -m 5 http://169.254.1.2:18093/health >/dev/null; then
|
||||
if curl -fsS -m 5 http://192.168.0.143:18093/health >/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "signal-relay is not answering on 169.254.1.2:18093" >&2
|
||||
echo "signal-relay is not answering on 192.168.0.143:18093" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
+17
-11
@@ -1,9 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Alertmanager-to-Signal relay for the homelab (Dankclaw).
|
||||
Listens on 169.254.1.2:18093 — the host side of host.containers.internal,
|
||||
the only address a bridge container can use to reach a host-local process —
|
||||
receives Alertmanager's webhook payload, formats
|
||||
existing account on this host. Runs as a systemd user unit
|
||||
Listens on 192.168.0.143:18093 (the host's LAN IP) and receives
|
||||
Alertmanager's webhook payload from the container as
|
||||
host.containers.internal:18093 — netavark delivers that address to the
|
||||
host's LAN IP, which is the one bind a bridge container can reach (a
|
||||
loopback bind refuses it, and 169.254.1.2 is not a local address here).
|
||||
The group is formatted into a short message and handed to signal-cli under
|
||||
the existing account on this host. Runs as a systemd user unit
|
||||
(scripts/signal-relay.service); logs go to the journal.
|
||||
|
||||
The phone number and account name are numbers, not credentials — the
|
||||
@@ -20,13 +23,16 @@ import sys
|
||||
import time
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
|
||||
# 169.254.1.2 is the host endpoint of host.containers.internal: a socket
|
||||
# bound to 127.0.0.1 refuses container traffic that arrives via the podman
|
||||
# bridge (measured 2026-09-17: "dial tcp 169.254.1.2:18093: connection
|
||||
# refused"). The address is link-local to the podman bridge — not on any
|
||||
# LAN interface, not on loopback, reachable only from this host's
|
||||
# containers.
|
||||
LISTEN_ADDR = ("169.254.1.2", 18093)
|
||||
# The bind address is the one detail this design gets wrong twice
|
||||
# (2026-09-17): a loopback bind refuses container traffic ("dial tcp
|
||||
# 169.254.1.2:18093: connection refused"), and 169.254.1.2 itself is not a
|
||||
# local address on this host ("Cannot assign requested address") — netavark
|
||||
# runs the bridges in aardvark-dns' netns, not the host's. Traffic that
|
||||
# arrives as 169.254.1.2 lands on the host's LAN IP, so bind THAT. The
|
||||
# deployer installs an iptables INPUT rule that admits 18093/tcp from the
|
||||
# podman bridge subnet (10.89.0.0/16) only, keeping the unauthenticated
|
||||
# endpoint off the rest of the LAN.
|
||||
LISTEN_ADDR = ("192.168.0.143", 18093)
|
||||
SIGNAL_CLI = "/usr/local/bin/signal-cli"
|
||||
SIGNAL_ACCOUNT = "318311"
|
||||
SIGNAL_TO = "+12062476336"
|
||||
|
||||
Reference in New Issue
Block a user