plugin/forward: fix parsing error when handling TLS+IPv6 address (#7848)

This commit is contained in:
yangsenzk
2026-02-25 18:21:39 +08:00
committed by GitHub
parent 7ae1c40db2
commit 5b7da1fbf7
3 changed files with 23 additions and 1 deletions

View File

@@ -99,17 +99,28 @@ func parseForward(c *caddy.Controller) ([]*Forward, error) {
// Splits the zone, preserving any port that comes after the zone // Splits the zone, preserving any port that comes after the zone
func splitZone(host string) (newHost string, zone string) { func splitZone(host string) (newHost string, zone string) {
trans, host, found := strings.Cut(host, "://")
if !found {
host, trans = trans, ""
}
newHost = host newHost = host
if strings.Contains(host, "%") { if strings.Contains(host, "%") {
lastPercent := strings.LastIndex(host, "%") lastPercent := strings.LastIndex(host, "%")
newHost = host[:lastPercent] newHost = host[:lastPercent]
if strings.HasPrefix(newHost, "[") {
newHost = newHost + "]"
}
zone = host[lastPercent+1:] zone = host[lastPercent+1:]
if strings.Contains(zone, ":") { if strings.Contains(zone, ":") {
lastColon := strings.LastIndex(zone, ":") lastColon := strings.LastIndex(zone, ":")
newHost += zone[lastColon:] newHost += zone[lastColon:]
zone = zone[:lastColon] zone = zone[:lastColon]
zone = strings.TrimSuffix(zone, "]")
} }
} }
if trans != "" {
newHost = trans + "://" + newHost
}
return return
} }

View File

@@ -44,6 +44,7 @@ func TestSetup(t *testing.T) {
{"forward 10.9.3.0/18 127.0.0.1", false, "0.9.10.in-addr.arpa.", nil, 2, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, ""}, {"forward 10.9.3.0/18 127.0.0.1", false, "0.9.10.in-addr.arpa.", nil, 2, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, ""},
{`forward . ::1 {`forward . ::1
forward com ::2`, false, ".", nil, 2, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "plugin"}, forward com ::2`, false, ".", nil, 2, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "plugin"},
{"forward . tls://[2400:3200::1%dns.alidns.com]:853 {\ntls\n}\n", false, ".", nil, 2, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, ""},
// negative // negative
{"forward . a27.0.0.1", true, "", nil, 0, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "not an IP"}, {"forward . a27.0.0.1", true, "", nil, 0, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "not an IP"},
{"forward . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, 0, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "unknown property"}, {"forward . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, 0, proxy.Options{HCRecursionDesired: true, HCDomain: "."}, "unknown property"},
@@ -106,6 +107,8 @@ func TestSplitZone(t *testing.T) {
"dns://127.0.0.1", "dns://127.0.0.1", "", "dns://127.0.0.1", "dns://127.0.0.1", "",
}, { }, {
"foo%bar:baz", "foo:baz", "bar", "foo%bar:baz", "foo:baz", "bar",
}, {
"tls://[::1%example.net]:853", "tls://[::1]:853", "example.net",
}, },
} }
for i, test := range tests { for i, test := range tests {
@@ -115,7 +118,7 @@ func TestSplitZone(t *testing.T) {
t.Errorf("Test %d: expected host %q, actual: %q", i, test.expectedHost, host) t.Errorf("Test %d: expected host %q, actual: %q", i, test.expectedHost, host)
} }
if zone != test.expectedZone { if zone != test.expectedZone {
t.Errorf("Test %d: expected host %q, actual: %q", i, test.expectedHost, host) t.Errorf("Test %d: expected zone %q, actual: %q", i, test.expectedZone, zone)
} }
} }
} }
@@ -151,6 +154,13 @@ func TestSetupTLS(t *testing.T) {
tls tls
}`, false, "", ""}, }`, false, "", ""},
{`forward . tls://127.0.0.1`, false, "", ""}, {`forward . tls://127.0.0.1`, false, "", ""},
{`forward . tls://[2400:3200::1%dns.alidns.com]:853 {
tls
}`, false, "dns.alidns.com", ""},
{`forward . tls://[2400:3200::1]:853 {
tls
tls_servername dns.alidns.com
}`, false, "dns.alidns.com", ""},
} }
for i, test := range tests { for i, test := range tests {

View File

@@ -46,6 +46,7 @@ func HostPortOrFile(s ...string) ([]string, error) {
if err != nil { if err != nil {
// Parse didn't work, it is not a addr:port combo // Parse didn't work, it is not a addr:port combo
host = strings.Trim(host, "[]")
hostNoZone := stripZone(host) hostNoZone := stripZone(host)
if net.ParseIP(hostNoZone) == nil { if net.ParseIP(hostNoZone) == nil {
ss, err := tryFile(host) ss, err := tryFile(host)