From 59cbb2c83a03b6fe352ae0b5d05581d9148a4d24 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 7 Aug 2024 20:02:23 +0300 Subject: [PATCH] caddytls,caddyhttp: Placeholders for some TLS and HTTP matchers (#6480) * Runtime placeholders for caddytls matchers (1/3): - remove IPs validation in UnmarshalCaddyfile * Runtime placeholders for caddytls matchers (2/3): - add placeholder replacement for IPs in Provision * Runtime placeholders for caddytls matchers (3/3): - add placeholder replacement for other strings * Runtime placeholders for caddyhttp matchers (1/1): - add placeholder replacement for IPs in Provision * Runtime placeholders for caddyhttp/caddytls matchers: - move PrivateRandesCIDR under internal --- internal/ranges.go | 14 +++++ modules/caddyhttp/ip_matchers.go | 7 ++- modules/caddyhttp/ip_range.go | 16 +----- modules/caddyhttp/reverseproxy/caddyfile.go | 3 +- modules/caddytls/matchers.go | 58 ++++++++++++--------- 5 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 internal/ranges.go diff --git a/internal/ranges.go b/internal/ranges.go new file mode 100644 index 000000000..e9429e263 --- /dev/null +++ b/internal/ranges.go @@ -0,0 +1,14 @@ +package internal + +// PrivateRangesCIDR returns a list of private CIDR range +// strings, which can be used as a configuration shortcut. +func PrivateRangesCIDR() []string { + return []string{ + "192.168.0.0/16", + "172.16.0.0/12", + "10.0.0.0/8", + "127.0.0.1/8", + "fd00::/8", + "::1", + } +} diff --git a/modules/caddyhttp/ip_matchers.go b/modules/caddyhttp/ip_matchers.go index 9101a0357..2e735cb69 100644 --- a/modules/caddyhttp/ip_matchers.go +++ b/modules/caddyhttp/ip_matchers.go @@ -29,6 +29,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/caddyserver/caddy/v2/internal" ) // MatchRemoteIP matches requests by the remote IP address, @@ -79,7 +80,7 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return d.Err("the 'forwarded' option is no longer supported; use the 'client_ip' matcher instead") } if d.Val() == "private_ranges" { - m.Ranges = append(m.Ranges, PrivateRangesCIDR()...) + m.Ranges = append(m.Ranges, internal.PrivateRangesCIDR()...) continue } m.Ranges = append(m.Ranges, d.Val()) @@ -173,7 +174,7 @@ func (m *MatchClientIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { for d.Next() { for d.NextArg() { if d.Val() == "private_ranges" { - m.Ranges = append(m.Ranges, PrivateRangesCIDR()...) + m.Ranges = append(m.Ranges, internal.PrivateRangesCIDR()...) continue } m.Ranges = append(m.Ranges, d.Val()) @@ -250,7 +251,9 @@ func (m MatchClientIP) Match(r *http.Request) bool { func provisionCidrsZonesFromRanges(ranges []string) ([]*netip.Prefix, []string, error) { cidrs := []*netip.Prefix{} zones := []string{} + repl := caddy.NewReplacer() for _, str := range ranges { + str = repl.ReplaceAll(str, "") // Exclude the zone_id from the IP if strings.Contains(str, "%") { split := strings.Split(str, "%") diff --git a/modules/caddyhttp/ip_range.go b/modules/caddyhttp/ip_range.go index b1db25475..7632e460c 100644 --- a/modules/caddyhttp/ip_range.go +++ b/modules/caddyhttp/ip_range.go @@ -22,6 +22,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/caddyserver/caddy/v2/internal" ) func init() { @@ -92,7 +93,7 @@ func (m *StaticIPRange) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } for d.NextArg() { if d.Val() == "private_ranges" { - m.Ranges = append(m.Ranges, PrivateRangesCIDR()...) + m.Ranges = append(m.Ranges, internal.PrivateRangesCIDR()...) continue } m.Ranges = append(m.Ranges, d.Val()) @@ -121,19 +122,6 @@ func CIDRExpressionToPrefix(expr string) (netip.Prefix, error) { return prefix, nil } -// PrivateRangesCIDR returns a list of private CIDR range -// strings, which can be used as a configuration shortcut. -func PrivateRangesCIDR() []string { - return []string{ - "192.168.0.0/16", - "172.16.0.0/12", - "10.0.0.0/8", - "127.0.0.1/8", - "fd00::/8", - "::1", - } -} - // Interface guards var ( _ caddy.Provisioner = (*StaticIPRange)(nil) diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go index 1c3b49447..4ca5d0e0d 100644 --- a/modules/caddyhttp/reverseproxy/caddyfile.go +++ b/modules/caddyhttp/reverseproxy/caddyfile.go @@ -28,6 +28,7 @@ import ( "github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" + "github.com/caddyserver/caddy/v2/internal" "github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/caddy/v2/modules/caddyhttp/headers" "github.com/caddyserver/caddy/v2/modules/caddyhttp/rewrite" @@ -688,7 +689,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { case "trusted_proxies": for d.NextArg() { if d.Val() == "private_ranges" { - h.TrustedProxies = append(h.TrustedProxies, caddyhttp.PrivateRangesCIDR()...) + h.TrustedProxies = append(h.TrustedProxies, internal.PrivateRangesCIDR()...) continue } h.TrustedProxies = append(h.TrustedProxies, d.Val()) diff --git a/modules/caddytls/matchers.go b/modules/caddytls/matchers.go index a23a19317..83a464713 100644 --- a/modules/caddytls/matchers.go +++ b/modules/caddytls/matchers.go @@ -26,6 +26,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/caddyserver/caddy/v2/internal" ) func init() { @@ -49,8 +50,17 @@ func (MatchServerName) CaddyModule() caddy.ModuleInfo { // Match matches hello based on SNI. func (m MatchServerName) Match(hello *tls.ClientHelloInfo) bool { + // caddytls.TestServerNameMatcher calls this function without any context + var repl *caddy.Replacer + if ctx := hello.Context(); ctx != nil { + repl = ctx.Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + } else { + repl = caddy.NewReplacer() + } + for _, name := range m { - if certmagic.MatchWildcard(hello.ServerName, name) { + rs := repl.ReplaceAll(name, "") + if certmagic.MatchWildcard(hello.ServerName, rs) { return true } } @@ -107,16 +117,19 @@ func (MatchRemoteIP) CaddyModule() caddy.ModuleInfo { // Provision parses m's IP ranges, either from IP or CIDR expressions. func (m *MatchRemoteIP) Provision(ctx caddy.Context) error { + repl := caddy.NewReplacer() m.logger = ctx.Logger() for _, str := range m.Ranges { - cidrs, err := m.parseIPRange(str) + rs := repl.ReplaceAll(str, "") + cidrs, err := m.parseIPRange(rs) if err != nil { return err } m.cidrs = append(m.cidrs, cidrs...) } for _, str := range m.NotRanges { - cidrs, err := m.parseIPRange(str) + rs := repl.ReplaceAll(str, "") + cidrs, err := m.parseIPRange(rs) if err != nil { return err } @@ -185,22 +198,18 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { for d.NextArg() { val := d.Val() + var exclamation bool if len(val) > 1 && val[0] == '!' { - prefixes, err := m.parseIPRange(val[1:]) - if err != nil { - return err - } - for _, prefix := range prefixes { - m.NotRanges = append(m.NotRanges, prefix.String()) - } + exclamation, val = true, val[1:] + } + ranges := []string{val} + if val == "private_ranges" { + ranges = internal.PrivateRangesCIDR() + } + if exclamation { + m.NotRanges = append(m.NotRanges, ranges...) } else { - prefixes, err := m.parseIPRange(val) - if err != nil { - return err - } - for _, prefix := range prefixes { - m.Ranges = append(m.Ranges, prefix.String()) - } + m.Ranges = append(m.Ranges, ranges...) } } @@ -233,9 +242,11 @@ func (MatchLocalIP) CaddyModule() caddy.ModuleInfo { // Provision parses m's IP ranges, either from IP or CIDR expressions. func (m *MatchLocalIP) Provision(ctx caddy.Context) error { + repl := caddy.NewReplacer() m.logger = ctx.Logger() for _, str := range m.Ranges { - cidrs, err := m.parseIPRange(str) + rs := repl.ReplaceAll(str, "") + cidrs, err := m.parseIPRange(rs) if err != nil { return err } @@ -300,13 +311,12 @@ func (m *MatchLocalIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } for d.NextArg() { - prefixes, err := m.parseIPRange(d.Val()) - if err != nil { - return err - } - for _, prefix := range prefixes { - m.Ranges = append(m.Ranges, prefix.String()) + val := d.Val() + if val == "private_ranges" { + m.Ranges = append(m.Ranges, internal.PrivateRangesCIDR()...) + continue } + m.Ranges = append(m.Ranges, val) } // No blocks are supported