mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-06 22:40:31 -05: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
|
// to spoof request headers. Default: false
|
||||||
Forwarded bool `json:"forwarded,omitempty"`
|
Forwarded bool `json:"forwarded,omitempty"`
|
||||||
|
|
||||||
|
// cidrs and zones vars should aligned always in the same
|
||||||
|
// length and indexes for matching later
|
||||||
cidrs []*net.IPNet
|
cidrs []*net.IPNet
|
||||||
|
zones []string
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,10 +880,19 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
||||||
func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
|
func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
|
||||||
m.logger = ctx.Logger(m)
|
m.logger = ctx.Logger(m)
|
||||||
for _, str := range m.Ranges {
|
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, "/") {
|
if strings.Contains(str, "/") {
|
||||||
_, ipNet, err := net.ParseCIDR(str)
|
_, ipNet, err := net.ParseCIDR(str)
|
||||||
if err != nil {
|
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)
|
m.cidrs = append(m.cidrs, ipNet)
|
||||||
} else {
|
} else {
|
||||||
|
@ -898,8 +910,9 @@ func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
|
||||||
return nil
|
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
|
remote := r.RemoteAddr
|
||||||
|
zoneID := ""
|
||||||
if m.Forwarded {
|
if m.Forwarded {
|
||||||
if fwdFor := r.Header.Get("X-Forwarded-For"); fwdFor != "" {
|
if fwdFor := r.Header.Get("X-Forwarded-For"); fwdFor != "" {
|
||||||
remote = strings.TrimSpace(strings.Split(fwdFor, ",")[0])
|
remote = strings.TrimSpace(strings.Split(fwdFor, ",")[0])
|
||||||
|
@ -909,25 +922,40 @@ func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ipStr = remote // OK; probably didn't have a port
|
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)
|
ip := net.ParseIP(ipStr)
|
||||||
if ip == nil {
|
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.
|
// Match returns true if r matches m.
|
||||||
func (m MatchRemoteIP) Match(r *http.Request) bool {
|
func (m MatchRemoteIP) Match(r *http.Request) bool {
|
||||||
clientIP, err := m.getClientIP(r)
|
clientIP, zoneID, err := m.getClientIP(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Error("getting client IP", zap.Error(err))
|
m.logger.Error("getting client IP", zap.Error(err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, ipRange := range m.cidrs {
|
zoneFilter := true
|
||||||
|
for i, ipRange := range m.cidrs {
|
||||||
if ipRange.Contains(clientIP) {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue