Files
godoxy/config.example.yml
T
Yuzerion 5c7838bbfe Feat/tls passthrough (#230)
* feat(entrypoint): multiplex HTTPS TCP routes by TLS SNI with tls_termination

Add an SNI router on the shared HTTPS listener that inspects TLS ClientHello
SNI, matches TCP routes by alias while honoring domain filters, and either
forwards TLS end-to-end without termination or terminates with autocert before
plaintext upstream relay when tls_termination is enabled.

Wire TCPTCPStream and idlewatcher through ConnProxy.ProxyConn instead of inline
handlers. Validate tls_termination for TCP schemes only and refresh README and
config examples. Bump internal/go-oidc submodule.

* fix(entrypoint,route): align SNI shared HTTPS listen addrs and gate tls_termination

Compare listen addresses with SplitHostPort so empty, 0.0.0.0, and ::
wildcard hosts on the HTTPS port match the proxy’s shared HTTPS address
for SNI route registration, keys, and passthrough eligibility.

Require tls_termination TCP routes to listen on that shared HTTPS
listener; add tests for address equality and validation.

* refactor(net,entrypoint,route): centralize shared HTTPS listener matching helpers

Move equivalence logic next to ProxyHTTPSAddr into internal/net/listen_addr.go and use it from SNI passthrough and tls_termination validation, dropping duplicated helpers.

Close the SNI listener and finish the http_server task when StartServer fails after SNI Listen. Update README examples for autocert-gated tls_termination and HTTPS_ADDR-relative ports.

* feat(entrypoint,net): open SNI HTTPS listener without autocert; widen wildcard host checks

Remove the autocert guard so the shared HTTPS listener still starts the SNI
multiplexer for passthrough when no certificate provider is configured.

Extend IsWildcardListenHost for trimmed input, host:port and bracketed IPv6,
using net.ParseIP and IsUnspecified for IPv4/IPv6. Add listen_addr tests,
README detail, and align SNI passthrough tests with ProxyHTTPSAddr.

* fix: apply CodeRabbit auto-fixes

Fixed 2 file(s) based on 2 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>

* test(dev,compose): add TCP echo fixture and SNI passthrough smoke test

Wire `cmd/tcp_echo_server` with plaintext and self-signed TLS listeners,
dev.compose labels for passthrough and `tls_termination` aliases, and
`scripts/tcp_echo_test.ts` invoked by `make tcp-echo-test` via bun.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
2026-05-01 13:20:38 +08:00

195 lines
5.9 KiB
YAML

# Autocert (choose one below and uncomment to enable)
#
# 1. use existing cert
# autocert:
# provider: local
# cert_path: /path/to/cert.crt # default: /app/certs/cert.crt
# key_path: /path/to/priv.key # default: /app/certs/priv.key
# 2. cloudflare
# autocert:
# provider: cloudflare
# email: abc@gmail.com # ACME Email
# domains: # a list of domains for cert registration
# - "*.domain.com"
# - "domain.com"
# # certificate_key_type: RSA2048 # optional; default EC256. Use RSA* for clients that lack ECDSA (e.g. some IoT TLS stacks)
# options:
# auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token
# 3. other providers, see https://docs.godoxy.dev/DNS-01-Providers
# Inbound mTLS profiles (optional)
#
# Reusable named profiles for inbound HTTPS client-certificate validation.
# A profile must trust either the system CA store, one or more CA files, or both.
#
# inbound_mtls_profiles:
# corp:
# use_system_cas: true
# ca_files:
# - /app/certs/corp-ca.pem
# Access Control
# When enabled, it will be applied globally at connection level,
# all incoming connections (web, tcp and udp) will be checked against the ACL rules.
# acl:
# default: allow # or deny (default: allow)
# allow_local: true # or false (default: true)
# allow:
# - ip:1.2.3.4
# - cidr:1.2.3.4/32
# - country:US
# - timezone:Asia/Shanghai
# deny:
# - ip:1.2.3.4
# - cidr:1.2.3.4/32
# - country:US
# - timezone:Asia/Shanghai
# log: # warning: logging ACL can be slow based on the number of incoming connections and configured rules
# path: /app/logs/acl.log # (default: none)
# stdout: false # (default: false)
# keep: 30 days # (default: 30 days)
# log_allowed: false # (default: false)
# notify:
# interval: 1m # (default: 1m)
# to: [gotify, discord] # names under providers.notification
# include_allowed: false # (default: false)
entrypoint:
# Proxy Protocol: https://www.haproxy.com/blog/use-the-proxy-protocol-to-preserve-a-clients-ip-address
# When set to true, web entrypoint and all tcp routes will be wrapped with Proxy Protocol listener in order to preserve the client's IP address.
# Note that HTTP/3 with proxy protocol is not supported yet.
support_proxy_protocol: false
# Below define an example of middleware config
# 1. set security headers
# 2. block non local IP connections
# 3. redirect HTTP to HTTPS
#
middlewares:
- use: CloudflareRealIP
- use: ModifyResponse
set_headers:
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Headers: "*"
Access-Control-Allow-Origin: "*"
Access-Control-Max-Age: 180
X-XSS-Protection: 1; mode=block
Content-Security-Policy: "object-src 'self'; frame-ancestors 'self';"
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: same-origin
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
# - use: RedirectHTTP
# below enables access log
access_log:
format: combined
path: /app/logs/entrypoint.log
stdout: false # (default: false)
keep: 30 days # (default: 30 days)
# customize behavior for non-existent routes, e.g. pass over to another proxy
#
# rules:
# not_found:
# - name: default
# do: proxy http://other-proxy:8080
defaults:
healthcheck:
interval: 5s
timeout: 15s
retries: 3
providers:
# include files are standalone yaml files under `config/` directory
#
# include:
# - file1.yml
# - file2.yml
docker:
# $DOCKER_HOST implies environment variable `DOCKER_HOST` or unix:///var/run/docker.sock by default
local: $DOCKER_HOST
# explicit only mode
# only containers with explicit aliases will be proxied
# add "!" after provider name to enable explicit only mode
#
# local!: $DOCKER_HOST
#
# add more docker providers if needed
# for value format, see https://docs.docker.com/reference/cli/dockerd/
#
# remote-1: tcp://10.0.2.1:2375
# remote-2: ssh://root:1234@10.0.2.2
# notification providers
#
# notification:
# - name: ntfy
# provider: ntfy
# url: https://ntfy.domain.tld
# topic: godoxy
# - name: gotify
# provider: gotify
# url: https://gotify.domain.tld
# token: abcd
# - name: discord
# provider: webhook
# url: https://discord.com/api/webhooks/...
# template: discord # this means use payload template from internal/notif/templates/discord.json
# - name: pushover
# provider: webhook
# url: https://api.pushover.net/1/messages.json
# mime_type: application/x-www-form-urlencoded
# payload: '{"token": "your-app-token", "user": "your-user-key", "title": $title, "message": $message}'
# Proxmox providers (for idlesleep support for proxmox LXCs)
#
# proxmox:
# - url: https://pve.domain.com:8006/api2/json
# token_id: root@pam!abcdef
# secret: aaaa-bbbb-cccc-dddd
# no_tls_verify: true
# To relay the downstream client address to a TCP upstream, set
# `relay_proxy_protocol_header: true` on that specific TCP route in route
# configuration (for example, see providers.example.yml). UDP relay is not
# supported yet.
# TCP routes on HTTPS_ADDR match TLS SNI by alias, same as HTTP routes.
# Default is passthrough; set tls_termination to proxy plaintext upstream.
#
# routes:
# site2:
# scheme: tcp
# host: 100.64.0.10
# port: 443:443
# mqtt:
# scheme: tcp
# host: 100.64.0.20
# port: 443:1883
# tls_termination: true
# Match domains
# See https://docs.godoxy.dev/Certificates-and-domain-matching
#
# match_domains:
# - my.site
# - node1.my.app
# homepage config
homepage:
# use default app categories detected from alias or docker image name
use_default_categories: true
# Below are fixed options (non hot-reloadable)
# timeout for shutdown (in seconds)
timeout_shutdown: 5