Introduce [domain-fronting] config

This commit is contained in:
9seconds
2026-02-24 18:05:12 +01:00
parent af72b2a574
commit 1cb225f52c
5 changed files with 85 additions and 23 deletions
+33 -3
View File
@@ -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
+3 -3
View File
@@ -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),
+28 -1
View File
@@ -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())
+6 -1
View File
@@ -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"`
+15 -15
View File
@@ -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"),