summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBitWuehler <39520752+BitWuehler@users.noreply.github.com>2022-03-01 23:50:12 +0100
committerGitHub <noreply@github.com>2022-03-01 15:50:12 -0700
commitac14b64e08a6ea63067c62cf1bad9cd6ad823d60 (patch)
tree01d8c68880721da8a53f6f0feddfbdb90ae76d7c
parent15c95e9d5b330a9590bbd7271264d9d47dd6e643 (diff)
caddyhttp: Support zone identifiers in remote_ip matcher (#4597)
* Update matchers.go * Update matchers.go * implementation of zone_id handling * last changes in zone handling * give return true values instead of bool * Apply suggestions from code review Co-authored-by: Francis Lavoie <lavofr@gmail.com> * changes as suggested * Apply suggestions from code review Co-authored-by: Francis Lavoie <lavofr@gmail.com> * Update matchers.go * shortened the Match function * changed mazcher handling * Update matchers.go * delete space Co-authored-by: Francis Lavoie <lavofr@gmail.com>
-rw-r--r--modules/caddyhttp/matchers.go42
1 files changed, 35 insertions, 7 deletions
diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go
index 272c924..9f10e2c 100644
--- a/modules/caddyhttp/matchers.go
+++ b/modules/caddyhttp/matchers.go
@@ -131,7 +131,10 @@ type (
// to spoof request headers. Default: false
Forwarded bool `json:"forwarded,omitempty"`
+ // cidrs and zones vars should aligned always in the same
+ // length and indexes for matching later
cidrs []*net.IPNet
+ zones []string
logger *zap.Logger
}
@@ -877,10 +880,19 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
m.logger = ctx.Logger(m)
for _, str := range m.Ranges {
+ // Exclude the zone_id from the IP
+ if strings.Contains(str, "%") {
+ split := strings.Split(str, "%")
+ str = split[0]
+ // write zone identifiers in m.zones for matching later
+ m.zones = append(m.zones, split[1])
+ } else {
+ m.zones = append(m.zones, "")
+ }
if strings.Contains(str, "/") {
_, ipNet, err := net.ParseCIDR(str)
if err != nil {
- return fmt.Errorf("parsing CIDR expression: %v", err)
+ return fmt.Errorf("parsing CIDR expression '%s': %v", str, err)
}
m.cidrs = append(m.cidrs, ipNet)
} else {
@@ -898,8 +910,9 @@ func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
return nil
}
-func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, error) {
+func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, string, error) {
remote := r.RemoteAddr
+ zoneID := ""
if m.Forwarded {
if fwdFor := r.Header.Get("X-Forwarded-For"); fwdFor != "" {
remote = strings.TrimSpace(strings.Split(fwdFor, ",")[0])
@@ -909,25 +922,40 @@ func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, error) {
if err != nil {
ipStr = remote // OK; probably didn't have a port
}
+ // Some IPv6-Adresses can contain zone identifiers at the end,
+ // which are separated with "%"
+ if strings.Contains(ipStr, "%") {
+ split := strings.Split(ipStr, "%")
+ ipStr = split[0]
+ zoneID = split[1]
+ }
ip := net.ParseIP(ipStr)
if ip == nil {
- return nil, fmt.Errorf("invalid client IP address: %s", ipStr)
+ return nil, zoneID, fmt.Errorf("invalid client IP address: %s", ipStr)
}
- return ip, nil
+ return ip, zoneID, nil
}
// Match returns true if r matches m.
func (m MatchRemoteIP) Match(r *http.Request) bool {
- clientIP, err := m.getClientIP(r)
+ clientIP, zoneID, err := m.getClientIP(r)
if err != nil {
m.logger.Error("getting client IP", zap.Error(err))
return false
}
- for _, ipRange := range m.cidrs {
+ zoneFilter := true
+ for i, ipRange := range m.cidrs {
if ipRange.Contains(clientIP) {
- return true
+ // Check if there are zone filters assigned and if they match.
+ if m.zones[i] == "" || zoneID == m.zones[i] {
+ return true
+ }
+ zoneFilter = false
}
}
+ if !zoneFilter {
+ m.logger.Debug("zone ID from remote did not match", zap.String("zone", zoneID))
+ }
return false
}