Probably works

This commit is contained in:
nick committed 2026-10-16 17:27:45 -07:00
1 parent d36e7a484a
commit b31faa5935
10 files changed
+222 -31

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
{{ ansible_managed | comment }}
table inet wgrelay
delete table inet wgrelay
table inet wgrelay {
chain input {
type filter hook input priority 0; policy accept;
ct state established,related accept
ct state invalid drop
# --- traffic arriving over the tunnel -------------------------------
# Ping across the tunnel is useful for debugging and harmless.
iifname "{{ wg_interface }}" icmp type echo-request accept
iifname "{{ wg_interface }}" icmpv6 type echo-request accept
{% for r in relays if r.direction == 'inbound' %}
# {{ r.name }}: only {{ r.source_allow }} may reach this listener
iifname "{{ wg_interface }}" ip saddr {{ r.source_allow }} tcp dport {{ r.listen_port }} accept
{% endfor %}
# Anything else off the tunnel is not ours. This is the rule that
# makes "one port, one host" true rather than aspirational.
iifname "{{ wg_interface }}" counter drop
# --- LAN-facing relay listeners -------------------------------------
{% for r in relays if r.direction == 'outbound' %}
iifname != "{{ wg_interface }}" ip saddr {{ r.source_allow }} tcp dport {{ r.listen_port }} accept
tcp dport {{ r.listen_port }} counter drop
{% endfor %}
}
chain forward {
type filter hook forward priority 0; policy drop;
# Nothing is routed through this box, by design. Combined with
# net.ipv4.ip_forward=0 this is belt and braces.
counter
}
}
+39
View File
@@ -0,0 +1,39 @@
{{ ansible_managed | comment }}
[Unit]
Description=Relay {{ item.name }} ({{ item.listen_address }}:{{ item.listen_port }} -> {{ item.target }})
After=network-online.target wg-quick@{{ wg_interface }}.service
Wants=network-online.target
{% if item.direction == 'inbound' %}
# Inbound listeners bind to the tunnel address, which doesn't exist until
# wg-quick has brought the interface up.
BindsTo=wg-quick@{{ wg_interface }}.service
{% endif %}
[Service]
Type=simple
ExecStart=/usr/bin/socat -d \
TCP-LISTEN:{{ item.listen_port }},bind={{ item.listen_address }},fork,reuseaddr,keepalive,keepidle=60,keepintvl=10,keepcnt=5 \
TCP:{{ item.target }},keepalive,keepidle=60,keepintvl=10,keepcnt=5
# Bind may fail for a few seconds after boot while wg0 settles; just retry.
Restart=always
RestartSec=5
# socat needs no privileges beyond binding a high port.
User={{ socat_user }}
Group={{ socat_group }}
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_INET AF_INET6
RestrictNamespaces=yes
MemoryDenyWriteExecute=yes
CapabilityBoundingSet=
[Install]
WantedBy=multi-user.target
+24
View File
@@ -0,0 +1,24 @@
{{ ansible_managed | comment }}
# Relay tunnel. This box forwards nothing; see the sysctl and nftables
# tasks in wg-relay.yml.
[Interface]
Address = {{ wg_address }}
ListenPort = {{ wg_listen_port }}
MTU = {{ wg_mtu }}
PrivateKey = {{ wg_relay_effective_private_key }}
{% for peer in wg_peers %}
# {{ peer.name }}
[Peer]
PublicKey = {{ peer.public_key }}
AllowedIPs = {{ peer.allowed_ips }}
{% if peer.endpoint is defined and peer.endpoint %}
Endpoint = {{ peer.endpoint }}
{% endif %}
{% if peer.preshared_key is defined and peer.preshared_key %}
PresharedKey = {{ peer.preshared_key }}
{% endif %}
PersistentKeepalive = {{ peer.keepalive | default(25) }}
{% endfor %}