@marcel91200 / caddy Mirror · read-only / commits / ac14b64e
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 21:45 UTC

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>

BitWuehler committed Mar 1, 2022 at 23:50 UTC ac14b64e08a6ea63067c62cf1bad9cd6ad823d60
1 file changed +35 -7
modules/caddyhttp/matchers.go
+35 -7
@@ -131,7 +131,10 @@ type (
131 // to spoof request headers. Default: false
132 Forwarded bool `json:"forwarded,omitempty"`
133
134 + // cidrs and zones vars should aligned always in the same
135 + // length and indexes for matching later
136 cidrs []*net.IPNet
137 + zones []string
138 logger *zap.Logger
139 }
140
@@ -877,10 +880,19 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
880 func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
881 m.logger = ctx.Logger(m)
882 for _, str := range m.Ranges {
883 + // Exclude the zone_id from the IP
884 + if strings.Contains(str, "%") {
885 + split := strings.Split(str, "%")
886 + str = split[0]
887 + // write zone identifiers in m.zones for matching later
888 + m.zones = append(m.zones, split[1])
889 + } else {
890 + m.zones = append(m.zones, "")
891 + }
892 if strings.Contains(str, "/") {
893 _, ipNet, err := net.ParseCIDR(str)
894 if err != nil {
883 - return fmt.Errorf("parsing CIDR expression: %v", err)
895 + return fmt.Errorf("parsing CIDR expression '%s': %v", str, err)
896 }
897 m.cidrs = append(m.cidrs, ipNet)
898 } else {
@@ -898,8 +910,9 @@ func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
910 return nil
911 }
912
901 -func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, error) {
913 +func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, string, error) {
914 remote := r.RemoteAddr
915 + zoneID := ""
916 if m.Forwarded {
917 if fwdFor := r.Header.Get("X-Forwarded-For"); fwdFor != "" {
918 remote = strings.TrimSpace(strings.Split(fwdFor, ",")[0])
@@ -909,25 +922,40 @@ func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, error) {
922 if err != nil {
923 ipStr = remote // OK; probably didn't have a port
924 }
925 + // Some IPv6-Adresses can contain zone identifiers at the end,
926 + // which are separated with "%"
927 + if strings.Contains(ipStr, "%") {
928 + split := strings.Split(ipStr, "%")
929 + ipStr = split[0]
930 + zoneID = split[1]
931 + }
932 ip := net.ParseIP(ipStr)
933 if ip == nil {
914 - return nil, fmt.Errorf("invalid client IP address: %s", ipStr)
934 + return nil, zoneID, fmt.Errorf("invalid client IP address: %s", ipStr)
935 }
916 - return ip, nil
936 + return ip, zoneID, nil
937 }
938
939 // Match returns true if r matches m.
940 func (m MatchRemoteIP) Match(r *http.Request) bool {
921 - clientIP, err := m.getClientIP(r)
941 + clientIP, zoneID, err := m.getClientIP(r)
942 if err != nil {
943 m.logger.Error("getting client IP", zap.Error(err))
944 return false
945 }
926 - for _, ipRange := range m.cidrs {
946 + zoneFilter := true
947 + for i, ipRange := range m.cidrs {
948 if ipRange.Contains(clientIP) {
928 - return true
949 + // Check if there are zone filters assigned and if they match.
950 + if m.zones[i] == "" || zoneID == m.zones[i] {
951 + return true
952 + }
953 + zoneFilter = false
954 }
955 }
956 + if !zoneFilter {
957 + m.logger.Debug("zone ID from remote did not match", zap.String("zone", zoneID))
958 + }
959 return false
960 }
961