mirror of
https://github.com/wweir/sower.git
synced 2026-10-20 00:15:34 +00:00
7.1 KiB
7.1 KiB
Architecture
System Boundary
sower is the client-side transparent proxy entrypoint. It exposes local DNS, HTTP, HTTPS, and SOCKS5 listeners, applies rule-based routing, and forwards proxied traffic to an upstream transport.
sowerd is the server-side TLS ingress. It exposes 80/tcp and 443/tcp, terminates TLS, detects the upstream transport protocol, and relays traffic to the requested target or configured fake site.
Layer Responsibilities
cmd/sower
- Process bootstrap
- Config loading and validation
- Local listener lifecycle and graceful shutdown
- Rule file loading
- Upstream proxy dialing
cmd/sowerd
- Process bootstrap
- Interactive self-install mode dispatch
- Config loading and validation
- TLS and HTTP server lifecycle
- Graceful shutdown
config
- Runtime configuration schema
- Input validation rules
- Embedded default
sowerdinstall config template
internal/install
- Interactive systemd installation flow for
sowerd - Binary copy/update and service file generation
- Default config and fake site directory bootstrap
router
- Domain and CIDR rule matching
- Direct/proxy/block routing decisions
- DNS query handling and upstream selection
transport/sower
- Sower transport frame encode/decode
transport/trojan
- Trojan transport frame encode/decode
pkg/dhcp
- DHCP-based upstream DNS discovery for the client side
sower Data Flow
- Load config from flags, env, and files.
- Validate remote type, listener addresses, and DNS IP fields.
- Log startup metadata with secrets redacted.
- Build the upstream proxy dialer with a stable DNS target. If
dns.upstreamis empty, the dialer usesdns.fallbackto avoid recursive lookup through the local DNS listener. - Build the upstream dialer for the configured remote transport, using standard TLS by default and optional uTLS fingerprints for
sowerandtrojan. - Build the router with suffix-tree rules and optional country CIDRs.
Remote rule files are fetched through the configured upstream proxy dialer, never by direct outbound HTTP, so rule bootstrap uses the same stable egress path as proxied traffic.
Remote domain rule files are filtered through per-router
file_skip_rulesbefore their prefixed entries are appended. - Start enabled local listeners for
udp/53,tcp/80,tcp/443, andtcp/1080only after rule loading completes. - For DNS requests, return local proxy IPs for proxy-routed domains and query upstream DNS for direct domains.
Empty
dns.upstreamkeeps router-side DHCP DNS discovery enabled;dns.fallbackis appended as a backup upstream and is also used while initial discovery is in flight. Proxy-routed domains return local A/AAAA records, suppress HTTPS/SVCB and other non-address metadata locally, and never leak proxy-matched names to direct upstream DNS. Direct upstream DNS failures fall back only for retryable upstream service errors; when no fallback succeeds, the last upstream DNS response code is returned as-is. Service discovery names are matched against both the full query name and the base domain only for service record types. - For HTTP traffic, parse the target host from the request line. For HTTPS transparent traffic, peek the TLS ClientHello to extract SNI. For SOCKS5 traffic, read the SOCKS5 target address. Apply routing rules and either dial directly or wrap traffic in the configured upstream transport. HTTPS transparent proxying reads only the TLS ClientHello, then replays the untouched bytes to the selected upstream; it must not complete or terminate TLS locally.
- On shutdown signal, stop listeners and DNS servers through
contextpropagation.
sowerd Data Flow
- Load config from flags, env, and files.
- Validate required fields and address/certificate combinations.
- Initialize logger with configured level and redact secrets from startup logs.
- Start
:80HTTP server. - Handle ACME HTTP-01 challenge on
:80. - Redirect normal HTTP traffic to HTTPS.
- If
fakeSiteis a local directory, serve it only for loopback fallback traffic through127.0.0.1:80. - Start
:443TLS listener. - For each accepted connection, apply a short read deadline for protocol probing.
- Try
sowertransport first, thentrojan. - Relay matched traffic to the decoded target.
- If no transport matches, relay to
fakeSite.
sowerd Install Flow
- Detect install mode from CLI flags before normal config loading.
- Require root privileges because the installer writes to
/usr/local/bin,/etc/systemd/system, and/etc/sower. - Optionally copy or update the current binary to
/usr/local/bin/sowerd. - Write
/etc/systemd/system/sowerd.servicewithExecStart=/usr/local/bin/sowerd -c /etc/sower/sowerd.toml. - Ensure
/etc/sower/sowerd.tomlexists and bootstrap/var/wwwfor directory-backed fake site mode. - Reload systemd and optionally enable/start or restart the service.
Design Decisions
- Client and server both fail fast on invalid startup configuration instead of silently degrading.
- The client loads TOML by default, with YAML kept as an alternate file format; HCL is not supported.
- Sensitive configuration values must never be printed verbatim in logs.
- Local listeners use explicit shutdown hooks instead of blocking forever with unmanaged goroutines.
- Network operations use timeouts and
contextto limit hangs during dialing and remote rule downloads. - Upstream TLS behavior is configured only on the client side;
sowerdremains a normal TLS server and does not need uTLS-specific logic. - Rule loading supports local files and remote HTTP sources; remote downloads must use the configured upstream proxy and fail startup if the proxy path cannot fetch them.
- Domain rule files support per-router skip rules for filtering third-party file entries without removing explicit local rules.
- Country routing treats
router.country.mmdbas optional; an empty value disables GeoIP lookup and keeps CIDR-based matching active without startup warnings. - Fake site directory mode is loopback-only on port
80to avoid exposing local static assets directly to the public internet. sowerdprefers the user cache directory for ACME state, but falls back to/var/cache/sowerso systemd services can start withoutHOME/XDG_CACHE_HOMEor a config file.
Operational Notes
sowerusually needs elevated privileges to bind53/udp,80/tcp, and443/tcp.sowerdmust bind privileged ports80and443.sowerd -ialso requires root because it writes system-level files for self-deployment.- ACME mode requires port
80to be reachable from the public internet. - Remote rule download failures stop startup after bounded retries before local listeners are exposed.