diff --git a/example.config.toml b/example.config.toml index 4676021..01ab257 100644 --- a/example.config.toml +++ b/example.config.toml @@ -50,7 +50,10 @@ prefer-ip = "prefer-ipv6" # FakeTLS uses domain fronting protection. So it needs to know a port to # access. -domain-fronting-port = 443 +# +# Deprecated: use [domain-fronting] configuration block. If relevant option +# is defined there, this one would be ignored. +# domain-fronting-port = 443 # By default, mtg resolves the fronting hostname (from the secret) via DNS # to establish a TCP connection. If DNS resolution of that hostname is blocked, @@ -58,11 +61,17 @@ domain-fronting-port = 443 # used for SNI in the TLS handshake. # # default value is not set (DNS resolution is used). -# domain-fronting-ip = "142.250.185.112" +# +# Deprecated: use [domain-fronting] configuration block. If relevant option +# is defined there, this one would be ignored. +# domain-fronting-ip = "10.0.0.10" # This makes a communication between both fronting website and mtg to use # proxy protocol. -domain-fronting-proxy-protocol = false +# +# Deprecated: use [domain-fronting] configuration block. If relevant option +# is defined there, this one would be ignored. +# domain-fronting-proxy-protocol = false # FakeTLS can compare timestamps to prevent probes. Each message has # encrypted timestamp. So, mtg can compare this timestamp and decide if @@ -85,6 +94,27 @@ tolerate-time-skewness = "5s" # Otherwise, chose a new DC. allow-fallback-on-unknown-dc = false +# This section is relevant to communication with fronting domain. Usually +# you do not need to setup anything here but there are plenty of cases, especially +# if you put mtg behind load balancer, when some specific configuration is +# required. +[domain-fronting] +# By default, mtg resolves the fronting hostname (from the secret) via DNS +# to establish a TCP connection. If DNS resolution of that hostname is blocked, +# you can specify an IP address to connect to directly. The hostname is still +# used for SNI in the TLS handshake. +# +# default value is not set (DNS resolution is used). +# ip = "10.10.10.11" + +# FakeTLS uses domain fronting protection. So it needs to know a port to +# access. Default value is 443 +# port = 443 + +# This makes a communication between both fronting website and mtg to use +# proxy protocol. +# proxy-protocol = false + # network defines different network-related settings [network] # please be aware that mtg needs to do some external requests. For diff --git a/internal/cli/run_proxy.go b/internal/cli/run_proxy.go index f7e9c6e..307d154 100644 --- a/internal/cli/run_proxy.go +++ b/internal/cli/run_proxy.go @@ -251,9 +251,9 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen EventStream: eventStream, Secret: conf.Secret, - DomainFrontingPort: conf.DomainFrontingPort.Get(mtglib.DefaultDomainFrontingPort), - DomainFrontingIP: conf.DomainFrontingIP.String(), - DomainFrontingProxyProtocol: conf.DomainFrontingProxyProtocol.Get(false), + DomainFrontingPort: conf.GetDomainFrontingPort(mtglib.DefaultDomainFrontingPort), + DomainFrontingIP: conf.GetDomainFrontingIP(nil), + DomainFrontingProxyProtocol: conf.GetDomainFrontingProxyProtocol(false), PreferIP: conf.PreferIP.Get(mtglib.DefaultPreferIP), AllowFallbackOnUnknownDC: conf.AllowFallbackOnUnknownDC.Get(false), diff --git a/internal/config/config.go b/internal/config/config.go index 5c7890e..30c0c20 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "net" "github.com/9seconds/mtg/v2/mtglib" ) @@ -32,7 +33,12 @@ type Config struct { DomainFrontingProxyProtocol TypeBool `json:"domainFrontingProxyProtocol"` TolerateTimeSkewness TypeDuration `json:"tolerateTimeSkewness"` Concurrency TypeConcurrency `json:"concurrency"` - Defense struct { + DomainFronting struct { + IP TypeIP `json:"ip"` + Port TypePort `json:"port"` + ProxyProtocol TypeBool `json:"proxyProtocol"` + } `json:"domainFronting"` + Defense struct { AntiReplay struct { Optional @@ -69,6 +75,27 @@ type Config struct { } `json:"stats"` } +func (c *Config) GetDomainFrontingPort(defaultValue uint) uint { + if port := c.DomainFronting.Port.Get(0); port != 0 { + return port + } + return c.DomainFrontingPort.Get(defaultValue) +} + +func (c *Config) GetDomainFrontingIP(defaultValue net.IP) string { + if ip := c.DomainFronting.IP.Get(nil); ip != nil { + return ip.String() + } + if ip := c.DomainFrontingIP.Get(defaultValue); ip != nil { + return ip.String() + } + return "" +} + +func (c *Config) GetDomainFrontingProxyProtocol(defaultValue bool) bool { + return c.DomainFronting.ProxyProtocol.Get(false) || c.DomainFrontingProxyProtocol.Get(defaultValue) +} + func (c *Config) Validate() error { if !c.Secret.Valid() { return fmt.Errorf("invalid secret %s", c.Secret.String()) diff --git a/internal/config/parse.go b/internal/config/parse.go index c72730a..e58bc14 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -20,7 +20,12 @@ type tomlConfig struct { DomainFrontingProxyProtocol bool `toml:"domain-fronting-proxy-protocol" json:"domainFrontingProxyProtocol,omitempty"` TolerateTimeSkewness string `toml:"tolerate-time-skewness" json:"tolerateTimeSkewness,omitempty"` Concurrency uint `toml:"concurrency" json:"concurrency,omitempty"` - Defense struct { + DomainFronting struct { + IP string `toml:"ip" json:"ip,omitempty"` + Port uint `toml:"port" json:"port,omitempty"` + ProxyProtocol bool `toml:"proxy-protocol" json:"proxyProtocol,omitempty"` + } `toml:"domain-fronting" json:"domainFronting,omitempty"` + Defense struct { AntiReplay struct { Enabled bool `toml:"enabled" json:"enabled,omitempty"` MaxSize string `toml:"max-size" json:"maxSize,omitempty"` diff --git a/mtglib/proxy.go b/mtglib/proxy.go index 750658d..a0e4965 100644 --- a/mtglib/proxy.go +++ b/mtglib/proxy.go @@ -31,8 +31,8 @@ type Proxy struct { domainFrontingProxyProtocol bool workerPool *ants.PoolWithFunc telegram *dc.Telegram - configUpdater *dc.PublicConfigUpdater - clientObfuscatror obfuscation.Obfuscator + configUpdater *dc.PublicConfigUpdater + clientObfuscatror obfuscation.Obfuscator secret Secret network Network @@ -321,20 +321,20 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) { updatersLogger := logger.Named("telegram-updaters") proxy := &Proxy{ - ctx: ctx, - ctxCancel: cancel, - secret: opts.Secret, - network: opts.Network, - antiReplayCache: opts.AntiReplayCache, - blocklist: opts.IPBlocklist, - allowlist: opts.IPAllowlist, - eventStream: opts.EventStream, + ctx: ctx, + ctxCancel: cancel, + secret: opts.Secret, + network: opts.Network, + antiReplayCache: opts.AntiReplayCache, + blocklist: opts.IPBlocklist, + allowlist: opts.IPAllowlist, + eventStream: opts.EventStream, logger: logger, - domainFrontingPort: opts.getDomainFrontingPort(), - domainFrontingIP: opts.DomainFrontingIP, - tolerateTimeSkewness: opts.getTolerateTimeSkewness(), - allowFallbackOnUnknownDC: opts.AllowFallbackOnUnknownDC, - telegram: tg, + domainFrontingPort: opts.getDomainFrontingPort(), + domainFrontingIP: opts.DomainFrontingIP, + tolerateTimeSkewness: opts.getTolerateTimeSkewness(), + allowFallbackOnUnknownDC: opts.AllowFallbackOnUnknownDC, + telegram: tg, configUpdater: dc.NewPublicConfigUpdater( tg, updatersLogger.Named("public-config"),