Implement MCNS v1: custom Go DNS server replacing CoreDNS

Replace the CoreDNS precursor with a purpose-built authoritative DNS
server. Zones and records (A, AAAA, CNAME) are stored in SQLite and
managed via synchronized gRPC + REST APIs authenticated through MCIAS.
Non-authoritative queries are forwarded to upstream resolvers with
in-memory caching.

Key components:
- DNS server (miekg/dns) with authoritative zone handling and forwarding
- gRPC + REST management APIs with MCIAS auth (mcdsl integration)
- SQLite storage with CNAME exclusivity enforcement and auto SOA serials
- 30 tests covering database CRUD, DNS resolution, and caching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 18:37:14 -07:00
parent a545fec658
commit f9635578e0
48 changed files with 6015 additions and 87 deletions

49
internal/config/config.go Normal file
View File

@@ -0,0 +1,49 @@
package config
import (
"fmt"
mcdslconfig "git.wntrmute.dev/kyle/mcdsl/config"
)
// Config is the top-level MCNS configuration.
type Config struct {
mcdslconfig.Base
DNS DNSConfig `toml:"dns"`
}
// DNSConfig holds the DNS server settings.
type DNSConfig struct {
ListenAddr string `toml:"listen_addr"`
Upstreams []string `toml:"upstreams"`
}
// Load reads a TOML config file, applies environment variable overrides
// (MCNS_ prefix), sets defaults, and validates required fields.
func Load(path string) (*Config, error) {
cfg, err := mcdslconfig.Load[Config](path, "MCNS")
if err != nil {
return nil, err
}
// Apply DNS defaults.
if cfg.DNS.ListenAddr == "" {
cfg.DNS.ListenAddr = ":53"
}
if len(cfg.DNS.Upstreams) == 0 {
cfg.DNS.Upstreams = []string{"1.1.1.1:53", "8.8.8.8:53"}
}
return cfg, nil
}
// Validate implements the mcdsl config.Validator interface.
func (c *Config) Validate() error {
if c.Database.Path == "" {
return fmt.Errorf("database.path is required")
}
if c.MCIAS.ServerURL == "" {
return fmt.Errorf("mcias.server_url is required")
}
return nil
}