more config
build / build-push (push) Successful in 24s

This commit is contained in:
mats committed 2026-09-28 21:34:59 +02:00
1 parent 0b6dcbd547
commit d48c1863bf
9 files changed
+222 -7

No files matched your search

+51
View File
@@ -23,6 +23,7 @@ import (
"strings"
"time"
"github.com/miekg/dns"
"gopkg.in/yaml.v3"
)
@@ -202,7 +203,14 @@ type EDNS struct {
PreserveEDNS0 bool `yaml:"preserve"`
}
// ForwardZone routes the apex and every name below it exclusively to Servers.
type ForwardZone struct {
Zone string `yaml:"zone" json:"zone"`
Servers []UpstreamServer `yaml:"servers" json:"servers"`
}
type Upstream struct {
ForwardZones []ForwardZone `yaml:"forward_zones,omitempty" json:"forward_zones,omitempty"`
// Servers is the upstream pool.
Servers []UpstreamServer `yaml:"servers"`
// Policy is "parallel" (query all, first answer wins), "random" (pick N)
@@ -962,6 +970,24 @@ func (c *Config) applyDefaults() {
l.MaxBytes = 512 << 20
}
}
for i := range c.Upstream.ForwardZones {
z := &c.Upstream.ForwardZones[i]
z.Zone = strings.ToLower(strings.TrimSuffix(strings.TrimSpace(z.Zone), "."))
for j := range z.Servers {
u := &z.Servers[j]
if u.Proto == "" {
u.Proto = "udp"
}
if u.Weight <= 0 {
u.Weight = 1
}
if u.Addr != "" {
if _, _, err := net.SplitHostPort(u.Addr); err != nil {
u.Addr = net.JoinHostPort(u.Addr, defaultPort(u.Proto))
}
}
}
}
for i := range c.Upstream.Servers {
u := &c.Upstream.Servers[i]
if u.Proto == "" {
@@ -1035,6 +1061,31 @@ func (c *Config) Validate() error {
if len(c.Upstream.Servers) == 0 {
add("upstream.servers must not be empty")
}
zones := map[string]bool{}
for i, z := range c.Upstream.ForwardZones {
name := strings.ToLower(strings.TrimSuffix(z.Zone, "."))
if _, ok := dns.IsDomainName(name); !ok || name == "" || strings.Contains(name, "*") {
add("upstream.forward_zones[%d]: invalid zone %q", i, z.Zone)
}
if zones[name] {
add("upstream.forward_zones[%d]: duplicate zone %q", i, z.Zone)
}
zones[name] = true
if len(z.Servers) == 0 {
add("upstream.forward_zones[%d]: servers must not be empty", i)
}
for _, u := range z.Servers {
host, port, err := net.SplitHostPort(u.Addr)
if err != nil || host == "" || port == "" {
add("upstream.forward_zones[%d]: invalid server address %q", i, u.Addr)
}
switch u.Proto {
case "udp", "tcp", "tls":
default:
add("upstream.forward_zones[%d]: invalid proto %q", i, u.Proto)
}
}
}
seen := map[string]bool{}
for i, u := range c.Upstream.Servers {
if u.Addr == "" {
+30
View File
@@ -371,3 +371,33 @@ func writeTempConfig(t *testing.T, content string) string {
}
return path
}
func TestForwardZoneConfig(t *testing.T) {
c := Default()
c.Block.Enabled = false
c.Upstream.ForwardZones = []ForwardZone{{Zone: "LOCAL.", Servers: []UpstreamServer{{Addr: "10.10.0.1"}}}}
c.applyDefaults()
if err := c.Validate(); err != nil {
t.Fatal(err)
}
z := c.Upstream.ForwardZones[0]
if z.Zone != "local" || z.Servers[0].Addr != "10.10.0.1:53" || z.Servers[0].Proto != "udp" {
t.Fatalf("defaults: %+v", z)
}
for _, bad := range []ForwardZone{
{Zone: "*.local", Servers: z.Servers},
{Zone: "", Servers: z.Servers},
{Zone: "local"},
{Zone: "local", Servers: []UpstreamServer{{Addr: "", Proto: "udp"}}},
{Zone: "local", Servers: []UpstreamServer{{Addr: "10.10.0.1:53", Proto: "http"}}},
} {
c.Upstream.ForwardZones = []ForwardZone{bad}
if err := c.Validate(); err == nil {
t.Fatalf("accepted %+v", bad)
}
}
c.Upstream.ForwardZones = []ForwardZone{z, z}
if err := c.Validate(); err == nil {
t.Fatal("accepted duplicate zone")
}
}