Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions commands/types/dnscontrol.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,8 @@ declare function HASH(algorithm: "SHA1" | "SHA256" | "SHA512", value: string): s
*
* Modifiers can be any number of [record modifiers](https://docs.dnscontrol.org/language-reference/record-modifiers) or JSON objects, which will be merged into the record's metadata.
*
* If you set the parameter `ech` to the special value `IGNORE`, DNSControl will ignore the contents of that parameter when updating a zone.
*
* ```javascript
* D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER),
* HTTPS("@", 1, ".", "ipv4hint=123.123.123.123 alpn=h3,h2 port=443"),
Expand Down
2 changes: 2 additions & 0 deletions documentation/language-reference/domain-modifiers/HTTPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The params may be configured to specify the `alpn`, `ipv4hint`, `ipv6hint`, `ech

Modifiers can be any number of [record modifiers](https://docs.dnscontrol.org/language-reference/record-modifiers) or JSON objects, which will be merged into the record's metadata.

If you set the parameter `ech` to the special value `IGNORE`, DNSControl will ignore the contents of that parameter when updating a zone.

{% code title="dnsconfig.js" %}
```javascript
D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER),
Expand Down
12 changes: 12 additions & 0 deletions integrationTest/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ func makeTests() []*TestGroup {
tc("Change HTTPS all", https("@", 3, "example.com.", "port=100")),
),

testgroup("Ech",
requires(providers.CanUseHTTPS),
tc("Create a HTTPS record", https("@", 1, "example.com.", "alpn=h2,h3")),
tc("Add an ECH key", https("@", 1, "example.com.", "alpn=h2,h3 ech=some+base64+encoded+value///")),
tc("Ignore the ECH key while changing other values", https("@", 1, "example.net.", "port=80 ech=IGNORE")),
// tc("Should be a no-op", https("@", 1, "example.net.", "port=80 ech=some+base64+encoded+value///")),
tc("Change the ECH key and other values", https("@", 1, "example.org.", "port=80 ipv4hint=127.0.0.1 ech=another+base64+encoded+value")),
// tc("Ignore the ECH key while not changing anything", https("@", 1, "example.org.", "port=80 ipv4hint=127.0.0.1 ech=IGNORE")),
// tc("Should be a no-op", https("@", 1, "example.org.", "port=80 ipv4hint=127.0.0.1 ech=another+base64+encoded+value")),
tc("Another domain with a different ECH value", https("ech", 1, "example.com.", "ech=some+base64+encoded+value///")),
),

testgroup("SVCB",
requires(providers.CanUseSVCB),
tc("Create a SVCB record", svcb("@", 1, "test.com.", "port=80")),
Expand Down
4 changes: 4 additions & 0 deletions models/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,10 @@ func (rc *RecordConfig) Key() RecordKey {

// GetSVCBValue returns the SVCB Key/Values as a list of Key/Values.
func (rc *RecordConfig) GetSVCBValue() []dns.SVCBKeyValue {
if !strings.Contains(rc.SvcParams, "IGNORE+DNSCONTROL") {
rc.SvcParams = strings.ReplaceAll(rc.SvcParams, "ech=IGNORE", "ech=IGNORE+DNSCONTROL+++")
}

record, err := dns.NewRR(fmt.Sprintf("%s %s %d %s %s", rc.NameFQDN, rc.Type, rc.SvcPriority, rc.target, rc.SvcParams))
if err != nil {
log.Fatalf("could not parse SVCB record: %s", err)
Expand Down
27 changes: 27 additions & 0 deletions pkg/diff2/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package diff2

import (
"fmt"
"regexp"
"sort"
"strings"

Expand Down Expand Up @@ -247,6 +248,8 @@ func humanDiff(a, b targetConfig) string {
return fmt.Sprintf("%s ttl=(%d->%d)", a.comparableNoTTL, a.rec.TTL, b.rec.TTL)
}

var echRe = regexp.MustCompile(`ech="?([\w+/=]+)"?`)

func diffTargets(existing, desired []targetConfig) ChangeList {
// fmt.Printf("DEBUG: diffTargets(\nexisting=%v\ndesired=%v\nDEBUG.\n", existing, desired)

Expand All @@ -255,6 +258,30 @@ func diffTargets(existing, desired []targetConfig) ChangeList {
return nil
}

echs := make(map[string]string)
for _, v := range existing {
matches := echRe.FindStringSubmatch(v.rec.SvcParams)
if len(matches) == 2 {
echs[v.rec.NameFQDN] = matches[1]
}
}
for i, v := range desired {
if strings.Contains(v.rec.SvcParams, "ech=IGNORE") {
var unquoted, quoted string
if _, ok := echs[v.rec.NameFQDN]; ok {
unquoted = fmt.Sprintf("ech=%s", echs[v.rec.NameFQDN])
quoted = fmt.Sprintf("ech=%q", echs[v.rec.NameFQDN])
} else {
unquoted = ""
quoted = ""
}
v.rec.SvcParams = echRe.ReplaceAllString(v.rec.SvcParams, unquoted)
v.comparableFull = echRe.ReplaceAllString(v.comparableFull, quoted)
v.comparableNoTTL = echRe.ReplaceAllString(v.comparableNoTTL, quoted)
}
desired[i] = v
}

var instructions ChangeList

// remove the exact matches.
Expand Down