From 9687c4606538edd84d2497e78af7cb9f62efad00 Mon Sep 17 00:00:00 2001 From: Adam Fisk Date: Tue, 26 May 2026 12:18:05 -0600 Subject: [PATCH 1/2] config: fix yaml tags for FrontingSNIs / SNIConfig The upstream generator (lantern-cloud/cmd/update_masquerades) uses the older getlantern/fronted Go types which carry no yaml struct tags, so yaml.Marshal writes lowercased Go field names with no separator: frontingsnis: ir: usearbitrarysnis: true arbitrarysnis: - python.org This domainfront package's tags expected snake_case (`fronting_snis`, `use_arbitrary_snis`, `arbitrary_snis`), which yaml.v3 silently fails to match, so every consumer of the parsed Config saw FrontingSNIs as empty. The runtime fronting client's arbitrary-SNI cover path was disabled across all clients. Aligns the tags with the wire format. Adds no migration cost since the older format was the only one ever produced. Local verification against the live fronted.yaml.gz from getlantern/fronted/main: akamai.frontingsnis.cn: useArbitrary=false count=2570 akamai.frontingsnis.default: useArbitrary=true count=4638 akamai.frontingsnis.ir: useArbitrary=true count=0 --- config.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 1479dfa..3365f62 100644 --- a/config.go +++ b/config.go @@ -32,13 +32,18 @@ type Provider struct { TestURL string `yaml:"testurl"` Masquerades []*Masquerade `yaml:"masquerades"` VerifyHostname *string `yaml:"verifyhostname"` - FrontingSNIs map[string]*SNIConfig `yaml:"fronting_snis"` + // Pipeline-emitted YAML keys are lowercase-concatenated, not + // snake_case (the upstream generator uses lowercased Go field + // names with no yaml tag); the tag here must match the wire + // format exactly or yaml.Unmarshal silently leaves the field + // zero-valued. + FrontingSNIs map[string]*SNIConfig `yaml:"frontingsnis"` } // SNIConfig controls SNI generation for a specific country or "default". type SNIConfig struct { - UseArbitrarySNIs bool `yaml:"use_arbitrary_snis"` - ArbitrarySNIs []string `yaml:"arbitrary_snis"` + UseArbitrarySNIs bool `yaml:"usearbitrarysnis"` + ArbitrarySNIs []string `yaml:"arbitrarysnis"` } // Masquerade contains the data for a single domain front. From 3fdbf7308d12311113ea2830518378928f4774c2 Mon Sep 17 00:00:00 2001 From: Adam Fisk Date: Tue, 26 May 2026 13:23:57 -0600 Subject: [PATCH 2/2] config: README + regression test for frontingsnis yaml keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses PR review: - README documented the snake_case form (fronting_snis / use_arbitrary_snis / arbitrary_snis) that never actually parsed — the upstream generator only ever emits the lowercase-concatenated form. Corrected the example to the real wire format so consumers don't copy keys that silently parse as zero values. - TestParseConfigYAML now includes a frontingsnis section with usearbitrarysnis/arbitrarysnis and asserts the fields populate, guarding the tag spelling against silent regression. No dual-key support added: there is no snake_case config in the wild to be compatible with (the format never changed; the tags were just wrong). --- README.md | 8 ++++---- config_test.go | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6367006..1da276f 100644 --- a/README.md +++ b/README.md @@ -103,12 +103,12 @@ providers: hostaliases: api.example.com: api.dsa.akamai.example.com testurl: https://fronted-ping.dsa.akamai.example.com/ping - fronting_snis: + frontingsnis: default: - use_arbitrary_snis: false + usearbitrarysnis: false br: - use_arbitrary_snis: true - arbitrary_snis: + usearbitrarysnis: true + arbitrarysnis: - mercadopago.com - amazon.com.br masquerades: diff --git a/config_test.go b/config_test.go index 17b794f..b5dfcb1 100644 --- a/config_test.go +++ b/config_test.go @@ -76,6 +76,10 @@ func TestExpandedProvider(t *testing.T) { } func TestParseConfigYAML(t *testing.T) { + // Keys are the lowercase-concatenated form the upstream generator + // emits (frontingsnis / usearbitrarysnis / arbitrarysnis), NOT + // snake_case — a tag-spelling mismatch silently parses these as zero + // values, so this fixture guards against that regressing. yml := ` trustedcas: - commonname: "Test CA" @@ -88,6 +92,14 @@ providers: hostaliases: example.com: cdn.example.com testurl: https://test.example.com/ping + frontingsnis: + default: + usearbitrarysnis: false + ir: + usearbitrarysnis: true + arbitrarysnis: + - python.org + - snapp.ir masquerades: - domain: cdn.example.com ipaddress: "1.2.3.4" @@ -101,4 +113,11 @@ providers: assert.Equal(t, "cdn.example.com", p.HostAliases["example.com"]) require.Len(t, p.Masquerades, 1) assert.Equal(t, "1.2.3.4", p.Masquerades[0].IpAddress) + + require.Contains(t, p.FrontingSNIs, "default") + require.Contains(t, p.FrontingSNIs, "ir") + assert.False(t, p.FrontingSNIs["default"].UseArbitrarySNIs) + ir := p.FrontingSNIs["ir"] + assert.True(t, ir.UseArbitrarySNIs) + assert.Equal(t, []string{"python.org", "snapp.ir"}, ir.ArbitrarySNIs) }