ff3ec65719
Synthetic CoreDNS Plugin CI/CD Build / test (push) Has been cancelled
Dockerfile used golang:1.21 but go.mod requires 1.25; CI was broken. Refactored plugin code with proper godoc comments, extracted helpers to eliminate duplicated response-building logic, modernized tests with t.Run subtests and shared assertion helpers, and rewrote README with configuration reference table and professional structure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
113 lines
3.8 KiB
Markdown
113 lines
3.8 KiB
Markdown
# synthetic
|
|
|
|
A [CoreDNS](https://coredns.io) plugin that generates DNS records from IP addresses embedded in hostnames.
|
|
|
|
Inspired by dnsmasq's [`synth-domain`](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html) option, `synthetic` provides automatic alignment between forward and reverse lookups — eliminating a common class of DNS misconfigurations described in [RFC 1912 Section 2.1](https://tools.ietf.org/html/rfc1912#section-2.1).
|
|
|
|
## Features
|
|
|
|
- **Forward lookups** (A/AAAA) — extract an IP from a prefixed hostname and respond directly
|
|
- **Reverse lookups** (PTR) — generate a synthetic hostname from a reverse query
|
|
- **Static record priority** — responses from upstream plugins (e.g., `file`) always take precedence over synthetic records
|
|
- **Dual-stack** — full IPv4 and IPv6 support, including compressed IPv6 notation
|
|
- **Configurable** — custom prefix, TTL, and per-network scoping
|
|
|
|
## How It Works
|
|
|
|
### Forward Lookups (A / AAAA)
|
|
|
|
A hostname with an embedded IP address is resolved directly. Dots (IPv4) or colons (IPv6) are replaced with dashes in the hostname label:
|
|
|
|
| Hostname | Record | Address |
|
|
|---|---|---|
|
|
| `ip-192-0-2-1.example.com` | A | `192.0.2.1` |
|
|
| `ip-2001-db8-abcd--1.example.com` | AAAA | `2001:db8:abcd::1` |
|
|
| `ip-2001-0db8-0000-0000-0000-0000-0000-0001.example.com` | AAAA | `2001:db8::1` |
|
|
|
|
Only addresses within a configured `net` CIDR are resolved. All other queries pass through to the next plugin.
|
|
|
|
### Reverse Lookups (PTR)
|
|
|
|
When a PTR query arrives, the plugin first consults the next plugin in the chain. If that plugin provides a successful answer (e.g., from a zone file), it is used as-is. Otherwise, a synthetic PTR record is generated pointing back to the corresponding forward hostname.
|
|
|
|
IPv6 reverse responses use the compressed address form per [RFC 5952](https://tools.ietf.org/html/rfc5952#section-2.2).
|
|
|
|
## Configuration
|
|
|
|
### Directives
|
|
|
|
| Directive | Description | Default |
|
|
|---|---|---|
|
|
| `net` | CIDR network(s) for which synthetic forward responses are generated. May be specified multiple times. | *(none — required for forward lookups)* |
|
|
| `forward` | Domain name appended to synthetic hostnames in PTR responses. | *(none — required for reverse lookups)* |
|
|
| `ttl` | Time-to-live for synthetic responses, in seconds. | `0` |
|
|
| `prefix` | Hostname label prefix identifying synthetic queries. A trailing dash is added automatically. | `ip` |
|
|
|
|
### Examples
|
|
|
|
**Forward lookups** for two IPv6 prefixes and one IPv4 prefix:
|
|
|
|
```
|
|
example.com {
|
|
synthetic {
|
|
net 2001:db8:abcd::/48
|
|
net 2001:db8:1234::/48
|
|
net 192.0.2.0/24
|
|
prefix ip
|
|
ttl 300
|
|
}
|
|
file db.example.com
|
|
}
|
|
```
|
|
|
|
**Reverse lookups** for an IPv6 prefix, with zone file records taking priority:
|
|
|
|
```
|
|
d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa {
|
|
synthetic {
|
|
forward example.com
|
|
prefix ip
|
|
}
|
|
file d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa
|
|
}
|
|
```
|
|
|
|
## Compiling into CoreDNS
|
|
|
|
Follow the standard [external plugin procedure](https://coredns.io/manual/plugins/#plugins). Add the following line to `plugin.cfg` in the CoreDNS source tree:
|
|
|
|
```
|
|
synthetic:code.fritzlab.net/dns/synthetic
|
|
```
|
|
|
|
Then rebuild CoreDNS:
|
|
|
|
```sh
|
|
go generate
|
|
go build
|
|
```
|
|
|
|
## FAQ
|
|
|
|
### Why not use the `template` plugin?
|
|
|
|
Two reasons:
|
|
|
|
1. The `template` plugin cannot coexist with `file` for the same zone in a way that lets file records take priority. See this [upstream discussion](https://github.com/coredns/coredns/issues/2977#issuecomment-555938144). The `synthetic` plugin is designed to work alongside `file`, deferring to it for static records.
|
|
|
|
2. Writing regex patterns to match arbitrary IPv4 and IPv6 addresses within CIDR ranges is impractical. This plugin accepts CIDR notation directly.
|
|
|
|
## Development
|
|
|
|
```sh
|
|
# Run tests
|
|
go test -v ./...
|
|
|
|
# Lint
|
|
go vet ./...
|
|
```
|
|
|
|
## License
|
|
|
|
[Apache License 2.0](LICENSE)
|