diff --git a/tailscale-proxy/3proxy.cfg b/tailscale-proxy/3proxy.cfg index 191fe24..825cd71 100644 --- a/tailscale-proxy/3proxy.cfg +++ b/tailscale-proxy/3proxy.cfg @@ -1,8 +1,47 @@ +# Unified LAN proxy for the tekhnohim Tailscale exit-node egress. +# +# One 3proxy instance serves BOTH an HTTP proxy (:3128) and a SOCKS5 proxy +# (:1080), each chained to the Tailscale userspace SOCKS5 (ts-proxy:1055) so +# clients exit the internet as the Hetzner exit-node IP (89.167.72.79). +# TCP only (Tailscale userspace SOCKS5 has no UDP ASSOCIATE -> no QUIC/HTTP3). +# +# Access model (LAN free, outside password): +# * LAN 192.168.0.0/22 -> authorised by source IP, NO password. +# * everyone else -> must authenticate (external clients arriving via +# the router port-forward keep their public source +# IP, so they fall through to the password rule). +# The username/password lives in a host-only file (0600, NOT in git), mounted +# separately and pulled in with the include below - same pattern as ts.env. + nserver 127.0.0.11 nscache 65536 timeouts 1 5 30 60 180 1800 15 60 log -auth iponly + +# Account(s) for external, password-authenticated access (host-only secret): +include /etc/3proxy/3proxy.secret + +# iponly authorises the LAN by address; strong forces login for the rest. +auth iponly strong + +# Safety guard: never treat the router's own address as a trusted LAN client. +# If the port-forward ever SNATs external traffic to the gateway IP, this rule +# makes the proxy fail CLOSED (external denied) instead of becoming an open +# proxy. Verify after opening the port: an unauthenticated external client +# must be refused. +deny * 192.168.0.1 + +# LAN clients: allowed by source IP, no password. Egress via the Tailscale +# userspace SOCKS5 (a `parent` binds to the `allow` line directly above it). allow * 192.168.0.0/22 parent 1000 socks5 ts-proxy 1055 + +# External clients: must present the configured account, same egress. +allow thproxy +parent 1000 socks5 ts-proxy 1055 + +# Anything else: denied. +deny * + +proxy -p3128 -a -i0.0.0.0 socks -p1080 -i0.0.0.0 diff --git a/tailscale-proxy/docker-compose.yaml b/tailscale-proxy/docker-compose.yaml index f100c77..ba5096d 100644 --- a/tailscale-proxy/docker-compose.yaml +++ b/tailscale-proxy/docker-compose.yaml @@ -15,13 +15,20 @@ services: volumes: ["/mnt/containers/tailscale-proxy/state:/var/lib/tailscale:z"] networks: [proxynet] - tinyproxy: - image: vimagick/tinyproxy:latest + # Unified 3proxy front: HTTP proxy (:3128) + SOCKS5 (:1080), LAN passwordless + # and external password-authenticated. Replaces the former tinyproxy HTTP + # container (tinyproxy cannot do per-source-IP conditional auth). + proxy: + image: ghcr.io/3proxy/3proxy:latest container_name: ts-lan-proxy restart: unless-stopped depends_on: [ts-proxy] - volumes: ["/mnt/containers/tailscale-proxy/tinyproxy.conf:/etc/tinyproxy/tinyproxy.conf:ro,z"] - ports: ["192.168.0.35:3128:3128"] + volumes: + - "/mnt/containers/tailscale-proxy/3proxy.cfg:/etc/3proxy/3proxy.cfg:ro,z" + - "/mnt/containers/tailscale-proxy/3proxy.secret:/etc/3proxy/3proxy.secret:ro,z" + ports: + - "192.168.0.35:3128:3128" + - "192.168.0.35:1080:1080" logging: driver: syslog options: @@ -30,21 +37,6 @@ services: tag: tailscale-proxy networks: [proxynet] - socks5: - image: ghcr.io/3proxy/3proxy:latest - container_name: ts-lan-socks5 - restart: unless-stopped - depends_on: [ts-proxy] - volumes: ["/mnt/containers/tailscale-proxy/3proxy.cfg:/etc/3proxy/3proxy.cfg:ro,z"] - ports: ["192.168.0.35:1080:1080"] - logging: - driver: syslog - options: - syslog-address: "udp://192.168.0.35:514" - syslog-format: rfc3164 - tag: tailscale-socks5 - networks: [proxynet] - networks: proxynet: name: tailscale-proxynet diff --git a/tailscale-proxy/tinyproxy.conf b/tailscale-proxy/tinyproxy.conf deleted file mode 100644 index 021c996..0000000 --- a/tailscale-proxy/tinyproxy.conf +++ /dev/null @@ -1,7 +0,0 @@ -Port 3128 -Listen 0.0.0.0 -Allow 192.168.0.0/22 -DisableViaHeader Yes -Timeout 600 -LogLevel Info -upstream socks5 ts-proxy:1055