Commit graph

60 commits

Author SHA1 Message Date
Thomas Limoncelli
0cc19df2ab
BUGFIX: BIND %D not working after v4.28.0 2025-12-08 09:58:43 -05:00
Tom Limoncelli
a0288bd759
bug(split horizon): Domains with split horizons not working (#3895)
Fixes https://github.com/StackExchange/dnscontrol/issues/3894

# Issue

* Split horizon DNS broke in 4.28.0
* Insufficient automated testing to detect this in the future 

# Resolution

* domain.PostProcess() was called twice. The first time the tag was
properly parsed, removing the tag from DomainConfig.Name and putting it
in DomainConfig.Tag. The second time DomainConfig.Name no longer had the
tag and .Tag was set to "".
* The JSON output of DomainConfig doesn't output .UniqueName. If it had,
this bug would have been noticed prior to release. Test updated to
include that field.
2025-12-05 11:41:16 -05:00
Tom Limoncelli
703084160f
REFACTOR: BIND/GANDI_V5 add "RP" record type, rewrite CLOUDFLAREAPI CF_* and more (#3886)
# Issue

* New record type: "RP" (supported by BIND and GANDI_V5) 
* Cloudflare: CF_REDIRECT/CF_TEMP_REDIRECT now generate
CF_SINGLE_REDIRECT records. All PAGE_RULE-based code is removed.
PAGE_RULEs are deprecated at Cloudflare. (be careful when upgrading!)
* New "v2" RecordConfig: RP and CF_SINGLE_REDIRECT are the only record
types that use this method. It shifts most of the work out of JavaScript
and into the Go code, making new record types easier to make, easier to
test, and easier to use by providers. This opens the door to new things
like a potential code-generator for rtypes. Converting existing rtypes
will happen over the next year.
* When only the TTL changes (MODIFY-TTL), the output lists the TTL
change first, not at the end of the line where it is visually lost.
* CF_REDIRECT/CF_TEMP_REDIRECT generate different rule "names". They
will be updated the first time you "push" with this release. The order
of the rules may also change. If you rules depend on a particular order,
be very careful with this upgrade!

Refactoring:

* New "v2" RecordConfig: Record types using this new method simply
package the parameters from dnsconfig.js statements like
CF_REDIRECT(foo,bar) and send them (raw) to the Go code. The Go code
does all processing, validation, etc. and turns them into RecordConfig
that store all the rdata in `RecordConfig.F`. No more adding fields to
RecordConfig for each new record type!
* RecordConfig.IsModernType() returns true if the record uses the new v2
record mechanism.
* PostProcess is now a method on DnsConfig and DomainConfig.
* DOC: How to create new rtypes using the v2 method (incomplete)

Other things:

* Integration tests for CF "full proxy" are removed. This feature
doesn't exist any more.
* DEV: Debugger tips now includes VSCode advice
* TESTING: The names of testgroup's can now have extra spaces to make
data align better
* CF_TEMP_REDIRECT/CF_REDIRECT is now a "builder" that generates
CLOUDFLAREAPI_SINGLE_REDIRECT records.
* And more!

# Resolution

---------

Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
2025-12-04 16:42:20 -05:00
Tom Limoncelli
c11a523982
FEATURE: Fixing IDN support for domains (#3879)
# Issue

The previous fix had backwards compatibility issues and treated
uppercase Unicode incorrectly.

# Resolution

* Don't call strings.ToUpper() on Unicode strings. Only call it on the
output of ToASCII.
* Fix BIND's "filenameformat" to be more compatible (only breaks if you
had uppercase unicode in a domain name... which you probably didn't)
* Change IDN to ASCII in most places (Thanks for the suggestion,
@KaiSchwarz-cnic!)
* Update BIND documentation
2025-12-03 20:31:59 -05:00
Tom Limoncelli
e87f03a8a3
CHORE: fmt (#3882) 2025-12-03 14:53:02 -05:00
tridion
f1b30a1a04
feat: Add IGNORE_EXTERNAL_DNS() for Kubernetes external-dns coexistence (#3869)s
## Summary

This PR adds a new domain modifier `IGNORE_EXTERNAL_DNS()` that
automatically detects and ignores DNS records managed by Kubernetes
[external-dns](https://github.com/kubernetes-sigs/external-dns)
controller.

**Related Issue:** This addresses the feature request discussed in
StackExchange/dnscontrol#935 (Idea: Ownership system), where
@tlimoncelli indicated openness to accepting a PR for this
functionality.

## Problem

When running DNSControl alongside Kubernetes external-dns, users face a
challenge:

- **external-dns** dynamically creates DNS records based on Kubernetes
Ingress/Service resources
- Users cannot use `IGNORE()` because they cannot predict which record
names external-dns will create
- Using `NO_PURGE()` is too broad - it prevents DNSControl from cleaning
up any orphaned records

The fundamental issue is that `IGNORE()` requires static patterns known
at config-time, but external-dns creates records dynamically at runtime.

## Solution

`IGNORE_EXTERNAL_DNS()` solves this by detecting external-dns managed
records at runtime:

```javascript
D("example.com", REG_CHANGEME, DnsProvider(DSP_MY_PROVIDER),
    IGNORE_EXTERNAL_DNS(),  // Automatically ignore external-dns managed records
    A("@", "1.2.3.4"),
    CNAME("www", "@")
);
```

### How It Works

external-dns uses a TXT record registry to track ownership. For each
managed record, it creates a TXT record like:

- `a-myapp.example.com` → TXT containing
`heritage=external-dns,external-dns/owner=...`
- `cname-api.example.com` → TXT containing
`heritage=external-dns,external-dns/owner=...`

This PR:
1. Scans existing TXT records for the `heritage=external-dns` marker
2. Parses the TXT record name prefix (e.g., `a-`, `cname-`) to determine
the managed record type
3. Automatically adds those records to the ignore list during diff
operations

## Changes

| File | Purpose |
|------|---------|
| `models/domain.go` | Add `IgnoreExternalDNS` field to DomainConfig |
| `pkg/js/helpers.js` | Add `IGNORE_EXTERNAL_DNS()` JavaScript helper |
| `pkg/diff2/externaldns.go` | Core detection logic for external-dns TXT
records |
| `pkg/diff2/externaldns_test.go` | Unit tests for detection logic |
| `pkg/diff2/handsoff.go` | Integrate external-dns detection into
handsoff() |
| `pkg/diff2/diff2.go` | Pass IgnoreExternalDNS flag to handsoff() |
| `commands/types/dnscontrol.d.ts` | TypeScript definitions for IDE
support |
| `documentation/.../IGNORE_EXTERNAL_DNS.md` | User documentation |

## Design Philosophy

This follows DNSControl's pattern of convenience builders (like
`M365_BUILDER`, `SPF_BUILDER`, `DKIM_BUILDER`) that make complex
operations simple. Just as those builders abstract away implementation
details, `IGNORE_EXTERNAL_DNS()` abstracts away the complexity of
detecting external-dns managed records.

## Testing

All unit tests pass:
```
go test ./pkg/diff2/... -v  # Tests detection logic
go test ./pkg/js/...        # Tests JS helpers
go build ./...              # Builds successfully
```

## Caveats Documented

- Only supports TXT registry (the default for external-dns)
- Requires external-dns to use default naming conventions
- May need updates if external-dns changes its registry format

---------

Co-authored-by: Tom Limoncelli <6293917+tlimoncelli@users.noreply.github.com>
2025-12-03 08:56:55 -05:00
Tom Limoncelli
1b2f5d4d34
BUGFIX: IDN support is broken for domain names (#3845)
# Issue

Fixes https://github.com/StackExchange/dnscontrol/issues/3842

CC @das7pad

# Resolution

Convert domain.Name to IDN earlier in the pipeline. Hack the --domains
processing to convert everything to IDN.

* Domain names are now stored 3 ways: The original input from
dnsconfig.js, canonical IDN format (`xn--...`), and Unicode format. All
are downcased. Providers that haven't been updated will receive the IDN
format instead of the original input format. This might break some
providers but only for users with unicode in their D("domain.tld").
PLEASE TEST YOUR PROVIDER.
* BIND filename formatting options have been added to access the new
formats.

# Breaking changes

* BIND zonefiles may change. The default used the name input in the D()
statement. It now defaults to the IDN name + "!tag" if there is a tag.
* Providers that are not IDN-aware may break (hopefully only if they
weren't processing IDN already)

---------

Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
2025-11-29 12:17:44 -05:00
Gabe Van Engel
97209bc2fc
AKAMAIEDGEDNS: Add ALIAS and AKAMAITLC support to the Akamai Edge DNS provider (#3836) 2025-11-14 09:48:42 -05:00
Elvis Ratzlaff
2a4e2509bc
POWERDNS: New record type: LUA (#3815) 2025-11-03 11:32:28 -05:00
Jan von Aschwege
a71b89e5a2
NEW FEATURE: Add SMIMEA support for BIND and deSEC (#3786) 2025-10-10 11:16:13 -04:00
Georg
8c8948e69a
NEW RECORD TYPE: OPENPGPKEY (basic) (#3718)
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2025-08-11 10:44:12 -04:00
Ishan Jain
e1830abb58
NEW PROVIDER: ADGUARDHOME (#3638) 2025-07-09 12:06:34 -04:00
Steven Rombauts
063d8b06e8
BUNNY_DNS: Add support for Redirect record (#3472) 2025-03-07 09:07:25 -05:00
Eli Heady
48c99f7065
Improve tagged domain handling in support of Split Horizon feature (#3444)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2025-02-25 12:27:24 -05:00
Costas Drogos
4f5655e510
NS1: remove deprecated NS1_URLFWD (#3400)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2025-01-27 10:29:26 -05:00
Jakob Ackermann
556926a2f7
BUG: Create zones ahead of gathering data (#3337)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2025-01-14 17:02:05 -05:00
Tom Limoncelli
5dbe5e84c9
CHORE: Fix lint warnings from golangci-lint (#3311) 2025-01-13 11:33:12 -05:00
Tom Limoncelli
06ba3cce77
Bugfix: Providers with batched updates might not report the correct number of changes (#3108) 2024-09-16 12:20:30 -04:00
imlonghao
04f34cf2e3
PORKBUN: support URL Forward (#3064)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2024-08-26 14:50:25 -04:00
Tom Limoncelli
088306883d
CLOUDFLAREAPI: Add CF_SINGLE_REDIRECT to manage "dynamic single" redirects (#3035) 2024-07-08 12:38:38 -04:00
Tom Limoncelli
0a784a3803
CHORE: Clean up comments in models/domain.go (#2975) 2024-05-22 16:04:41 -04:00
Tom Limoncelli
1fa92de07e
CHORE: Linting and comment-fixing (#2937) 2024-05-07 14:47:28 -04:00
Florian Ritterhoff
3a9b413175
NEW RECORD TYPE: HTTPS & SVCB (#2919)
Thanks so much for this contribution!  I have a feeling that a lot of people are going to need these records soon!
2024-05-01 11:37:15 -04:00
xtex
3f05482e6b
NEW RECORD TYPE: DNSKEY (#2917)
Signed-off-by: xtex <xtexchooser@duck.com>
2024-04-22 09:54:12 -04:00
imlonghao
42125b5248
NEW RECORD TYPE: DNAME (#2893) 2024-04-02 14:28:57 -04:00
Tom Limoncelli
68c5e87c89
NEW FEATURE: Gather data for providers concurrently (#2873) 2024-03-27 13:54:36 -04:00
Florian Ritterhoff
a5a1facdaf
DOCS: add dhcid RR docs (#2715) 2023-12-11 07:25:27 -05:00
Tom Limoncelli
c91fe6c1c8
CHORE: Remove diff1 from codebase (#2575) 2023-10-22 13:56:13 -04:00
Florian Ritterhoff
b6e183d4b5 add missing handling of dhcid 2023-09-10 08:09:02 +02:00
Tom Limoncelli
0b7dabacc8
NEW FEATURE: IGNORE() (diff2 only) (#2388)
Co-authored-by: Jeffrey Cafferata <jeffrey@jcid.nl>
2023-05-24 15:14:36 -04:00
Tom Limoncelli
66a76c44c1
Don't count diff2.REPORT (informational warnings) as a "correction" (#2361)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-16 10:42:08 -04:00
Daniil Lemenkov
36e3595612
CHORE: Satisfy Staticcheck and remove unused code (#2331) 2023-05-08 16:49:26 -04:00
Tom Limoncelli
489be2e3dc
ROUTE53: fix R53_ZONE() handling for domains (#2306)
Co-authored-by: Tom Limoncelli <tal@whatexit.org>
2023-05-02 13:04:59 -04:00
Tom Limoncelli
367c83a3f5
LOC: Refine which providers support it (#2185) 2023-03-16 19:59:44 -04:00
Paul Dee
2d241b7a78
Update domain.go (#2135)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2023-03-11 05:42:52 -08:00
Tom Limoncelli
fc3a217dc1
Bugfixed: NO_PURGE now works on all diff2 providers (#2084) 2023-02-19 12:33:08 -05:00
Tom Limoncelli
54fc2e9ce3
NEW FEATURE: diff2: A better "diff" mechanism (#1852) 2022-12-11 17:28:58 -05:00
Dragos Harabor
68516025a5
FEATURE: Add rTypes restrictions to IGNORE_NAME (#1808)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2022-11-07 11:27:04 -05:00
tpdn
fc75f89271
ClouDNS: Add CLOUDNS_WR (Web Redirects) (#1421)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2022-03-02 09:21:51 -05:00
F.D.Castel
0d12eb7dc6
CLOUDFLAREAPI: Adds CF_WORKER_ROUTE (#1243)
* CLOUDFLAREAPI: Adds CF_WORKER_ROUTE.

- CLOUDFLAREAPI: Initial support for CF_WORKER_ROUTE.
- Put CF_WORKER_ROUTE behind a per-domain feature-flag.
- Adds Integration Test.
- Create Cloudflare workers for tests.
- Updates documentation.

* Workaround for updateWorkerRoute causing stack overflow.

* Sets AccountID.

* Updates to latest master (Thanks @tresni!).

* Removes $CLOUDFLAREAPI_ACCOUNTNAME.

* Add alltrue() filter and -cfworkers flag

* Final workers changes

* alltrue() should be implemented like other filters.
* Update documentation.

Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2021-10-11 16:04:49 -04:00
Steven Vernick
be1f03fb75
NEW PROVIDER: AkamaiEdgeDNS (#1174)
* downcase TLSA

* Akamai provider

* Akamai provider

* EdgeDNS provider

* AkamaiEdgeDNS provider

* AkamaiEdgeDNS provider

* AkamaiEdgeDNS provider

Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
2021-06-22 10:24:49 -04:00
Tom Limoncelli
21e85e6528
"Target" RecordConfig should not be exported (#1061)
* Unexport RecordConfig.Target
* Fix tests
* HEDNS: Fix usage of target field to resolve TXT handling (#1067)

Co-authored-by: Robert Blenkinsopp <robert@blenkinsopp.net>
2021-03-04 18:58:23 -05:00
Tom Limoncelli
a2042c2eda
NS1: Support NS1_URLFWD (#1046) 2021-02-10 11:57:15 -05:00
Tom Limoncelli
c547beacc0
NEW FEATURE: Support Split Horizon DNS (#1034)
* Implement main feature
* BIND: Permit printf-like file name formats
* BIND: Make filenameformat work forwards and backwards.
* Fix extrator test cases
2021-02-05 12:12:45 -05:00
Tom Limoncelli
23f65163e8
CLOUDFLAREAPI: Support Punycode for CF_REDIRECT/CF_TEMP_REDIRECT (with tests) (#1026)
* CLOUDFLAREAPI: CF_REDIRECT should support Punycode
* Add tests to CF_*REDIR
* CLOUDFLARE: DS records only permitted on children
2021-01-24 16:36:23 -05:00
Tom Limoncelli
f082ad36c8
AUTODNSSEC -> AUTODNSSEC_ON (#863)
* AUTODNSSEC -> AUTODNSSEC_ON
* Validate AutoDNSSEC values
* AUTODNSSEC now generates a warning and does nothing.
2020-09-27 16:37:42 -04:00
Tom Limoncelli
d6dd13820f
gofmt (#826) 2020-08-26 13:45:02 -04:00
Mike Cochrane
960dc66bd2
New feature: IGNORE_TARGET. Rename INGORE to IGNORE_NAME (#806) 2020-08-18 11:14:34 -04:00
Tom Limoncelli
541bb805da
linting (#777) 2020-07-06 20:18:24 -04:00
Tom Limoncelli
87a5c4b339
New RTYPE: DS records now supported! (#753)
Thanks to @haraldkoch for starting this, @McNetic for picking it up.

* Added DS record type

* Added DS for cloudflare provider with tests

* Removed DS validation, fixed parse test

* Added generated files

* Added dnsimple ds record

* Regenerated documentation matrix

* rebased and regenerated

* Updated integration tests

* Rebase and regenerate

* Enable DS record type for provider desec

* Added DS record type

* Added DS for cloudflare provider with tests

* Removed DS validation, fixed parse test

* Added generated files

* Added dnsimple ds record

* Regenerated documentation matrix

* rebased and regenerated

* Updated integration tests

* Rebase and regenerate

* Enable DS record type for provider desec

* Rebase and fixes

Co-authored-by: Robert Koch <robert@kochie.io>
Co-authored-by: Nicolai Ehemann <nicolai.ehemann@enerko-informatik.de>
2020-05-30 10:40:21 -04:00