mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-26 21:53:48 +03:00
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>
This commit is contained in:
parent
15c95e9d5b
commit
ac14b64e08
1 changed files with 35 additions and 7 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue