fix(8201): restore old behavior forward plugin continue on empty conf file (#8203)

This commit is contained in:
Antoine
2026-07-02 08:11:37 +02:00
committed by GitHub
parent 8d94712f99
commit 3a4b87bdb4
4 changed files with 34 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
package forward package forward
import ( import (
"errors"
"fmt" "fmt"
"net" "net"
"strings" "strings"
@@ -39,9 +40,14 @@ func classifyToAddrs(toAddrs []string) ([]toEntry, error) {
continue continue
} }
// Empty file are skip
if errors.Is(parseErr, parse.ErrNoNameservers) {
continue
}
// Only fall through to hostname parsing if the error specifically // Only fall through to hostname parsing if the error specifically
// indicates the address is not an IP or file. Other errors (like // indicates the address is not an IP or file. Other errors (like
// "no nameservers found" from file parsing) should be propagated. // "invalid address" from ip parsing) should be propagated.
if !strings.Contains(parseErr.Error(), "not an IP address or file") { if !strings.Contains(parseErr.Error(), "not an IP address or file") {
return nil, parseErr return nil, parseErr
} }

View File

@@ -24,6 +24,13 @@ func TestClassifyToAddrs(t *testing.T) {
} }
defer os.Remove(resolv) defer os.Remove(resolv)
// Create a commented.conf for file test
const commentedResolv = "commented_resolv.conf"
if err := os.WriteFile(commentedResolv, []byte("# nameserver 1.1.1.1\n# nameserver 1.0.0.1\n"), 0666); err != nil {
t.Fatal(err)
}
defer os.Remove(commentedResolv)
tests := []struct { tests := []struct {
name string name string
input []string input []string
@@ -84,10 +91,10 @@ func TestClassifyToAddrs(t *testing.T) {
wantDynamic: 1, wantDynamic: 1,
}, },
{ {
name: "/dev/null returns file error", name: "an existing file not empty but without nameserver is skipped",
input: []string{"/dev/null"}, input: []string{commentedResolv},
wantErr: true, wantDynamic: 0,
errContains: "no nameservers", wantStatic: 0,
}, },
} }

View File

@@ -242,6 +242,14 @@ nameserver 10.10.255.253`), 0666); err != nil {
} }
defer os.Remove(resolvIPV6) defer os.Remove(resolvIPV6)
const emptyResolv = "empty.conf"
if err := os.WriteFile(emptyResolv,
[]byte(`# nameserver 1.1.1.1
# nameserver 1.0.0.1`), 0666); err != nil {
t.Fatalf("Failed to write empty.conf file: %s", err)
}
defer os.Remove(emptyResolv)
tests := []struct { tests := []struct {
input string input string
shouldErr bool shouldErr bool
@@ -251,9 +259,11 @@ nameserver 10.10.255.253`), 0666); err != nil {
// pass // pass
{`forward . ` + resolv, false, "", []string{"10.10.255.252:53", "10.10.255.253:53"}}, {`forward . ` + resolv, false, "", []string{"10.10.255.252:53", "10.10.255.253:53"}},
// fail // fail
{`forward . /dev/null`, true, "no nameservers", nil}, {`forward . /dev/null`, true, "no valid upstream addresses found", nil},
// IPV6 with local zone // IPV6 with local zone
{`forward . ` + resolvIPV6, false, "", []string{"[0388:d254:7aec:6892:9f7f:e93b:5806:1b0f]:53"}}, {`forward . ` + resolvIPV6, false, "", []string{"[0388:d254:7aec:6892:9f7f:e93b:5806:1b0f]:53"}},
// pass when empty forward file is found
{`forward . ` + emptyResolv + ` 127.0.0.1`, false, "", []string{"127.0.0.1:53"}},
} }
for i, test := range tests { for i, test := range tests {
@@ -517,6 +527,7 @@ func TestMultiForward(t *testing.T) {
t.Error("expected third plugin to be last, but Next is not nil") t.Error("expected third plugin to be last, but Next is not nil")
} }
} }
func TestNextAlternate(t *testing.T) { func TestNextAlternate(t *testing.T) {
testsValid := []struct { testsValid := []struct {
input string input string

View File

@@ -54,7 +54,7 @@ func HostPortOrFile(s ...string) ([]string, error) {
servers = append(servers, ss...) servers = append(servers, ss...)
continue continue
} }
return servers, fmt.Errorf("not an IP address or file: %q", host) return servers, fmt.Errorf("not an IP address or file %q: %w", host, err)
} }
var ss string var ss string
switch trans { switch trans {
@@ -79,7 +79,7 @@ func HostPortOrFile(s ...string) ([]string, error) {
servers = append(servers, ss...) servers = append(servers, ss...)
continue continue
} }
return servers, fmt.Errorf("not an IP address or file: %q", host) return servers, fmt.Errorf("not an IP address or file %q: %w", host, err)
} }
servers = append(servers, h) servers = append(servers, h)
} }
@@ -92,13 +92,13 @@ func HostPortOrFile(s ...string) ([]string, error) {
// Try to open this is a file first. // Try to open this is a file first.
func tryFile(s string) ([]string, error) { func tryFile(s string) ([]string, error) {
c, err := dns.ClientConfigFromFile(s) c, err := dns.ClientConfigFromFile(s)
if err == os.ErrNotExist { if errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("failed to open file %q: %q", s, err) return nil, fmt.Errorf("failed to open file %q: %q", s, err)
} else if err != nil { } else if err != nil {
return nil, err return nil, err
} }
servers := []string{} var servers []string
for _, s := range c.Servers { for _, s := range c.Servers {
servers = append(servers, net.JoinHostPort(stripZone(s), c.Port)) servers = append(servers, net.JoinHostPort(stripZone(s), c.Port))
} }