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, 15:30 UTC
core: Change net.IP to netip.Addr; use netip.Prefix (#4966)
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
WilczyńskiT committed
Aug 18, 2022 at 00:10 UTC
c7772588bd44ceffcc0ba4817e4d43c826675379
5 files changed
+50
-57
caddyconfig/httpcaddyfile/addresses.go
+4
-3
@@ -17,6 +17,7 @@ package httpcaddyfile
17
import (
18
"fmt"
19
"net"
20
+ "net/netip"
21
"reflect"
22
"sort"
23
"strconv"
@@ -354,9 +355,9 @@ func (a Address) Normalize() Address {
355
356
// ensure host is normalized if it's an IP address
357
host := strings.TrimSpace(a.Host)
357
- if ip := net.ParseIP(host); ip != nil {
358
- if ipv6 := ip.To16(); ipv6 != nil && ipv6.DefaultMask() == nil {
359
- host = ipv6.String()
358
+ if ip, err := netip.ParseAddr(host); err == nil {
359
+ if ip.Is6() && !ip.Is4() && !ip.Is4In6() {
360
+ host = ip.String()
361
}
362
}
363
listeners.go
+3
-2
@@ -20,6 +20,7 @@ import (
20
"errors"
21
"fmt"
22
"net"
23
+ "net/netip"
24
"os"
25
"strconv"
26
"strings"
@@ -400,7 +401,7 @@ func (na NetworkAddress) isLoopback() bool {
401
if na.Host == "localhost" {
402
return true
403
}
403
- if ip := net.ParseIP(na.Host); ip != nil {
404
+ if ip, err := netip.ParseAddr(na.Host); err == nil {
405
return ip.IsLoopback()
406
}
407
return false
@@ -410,7 +411,7 @@ func (na NetworkAddress) isWildcardInterface() bool {
411
if na.Host == "" {
412
return true
413
}
413
- if ip := net.ParseIP(na.Host); ip != nil {
414
+ if ip, err := netip.ParseAddr(na.Host); err == nil {
415
return ip.IsUnspecified()
416
}
417
return false
modules/caddyhttp/matchers.go
+14
-16
@@ -20,6 +20,7 @@ import (
20
"fmt"
21
"net"
22
"net/http"
23
+ "net/netip"
24
"net/textproto"
25
"net/url"
26
"path"
@@ -171,7 +172,7 @@ type (
172
173
// cidrs and zones vars should aligned always in the same
174
// length and indexes for matching later
174
- cidrs []*net.IPNet
175
+ cidrs []*netip.Prefix
176
zones []string
177
logger *zap.Logger
178
}
@@ -1311,27 +1312,24 @@ func (m *MatchRemoteIP) Provision(ctx caddy.Context) error {
1312
m.zones = append(m.zones, "")
1313
}
1314
if strings.Contains(str, "/") {
1314
- _, ipNet, err := net.ParseCIDR(str)
1315
+ ipNet, err := netip.ParsePrefix(str)
1316
if err != nil {
1317
return fmt.Errorf("parsing CIDR expression '%s': %v", str, err)
1318
}
1318
- m.cidrs = append(m.cidrs, ipNet)
1319
+ m.cidrs = append(m.cidrs, &ipNet)
1320
} else {
1320
- ip := net.ParseIP(str)
1321
- if ip == nil {
1322
- return fmt.Errorf("invalid IP address: %s", str)
1321
+ ipAddr, err := netip.ParseAddr(str)
1322
+ if err != nil {
1323
+ return fmt.Errorf("invalid IP address: '%s': %v", str, err)
1324
}
1324
- mask := len(ip) * 8
1325
- m.cidrs = append(m.cidrs, &net.IPNet{
1326
- IP: ip,
1327
- Mask: net.CIDRMask(mask, mask),
1328
- })
1325
+ ipNew := netip.PrefixFrom(ipAddr, ipAddr.BitLen())
1326
+ m.cidrs = append(m.cidrs, &ipNew)
1327
}
1328
}
1329
return nil
1330
}
1331
1334
-func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, string, error) {
1332
+func (m MatchRemoteIP) getClientIP(r *http.Request) (netip.Addr, string, error) {
1333
remote := r.RemoteAddr
1334
zoneID := ""
1335
if m.Forwarded {
@@ -1350,11 +1348,11 @@ func (m MatchRemoteIP) getClientIP(r *http.Request) (net.IP, string, error) {
1348
ipStr = split[0]
1349
zoneID = split[1]
1350
}
1353
- ip := net.ParseIP(ipStr)
1354
- if ip == nil {
1355
- return nil, zoneID, fmt.Errorf("invalid client IP address: %s", ipStr)
1351
+ ipAddr, err := netip.ParseAddr(ipStr)
1352
+ if err != nil {
1353
+ return netip.IPv4Unspecified(), "", err
1354
}
1357
- return ip, zoneID, nil
1355
+ return ipAddr, zoneID, nil
1356
}
1357
1358
// Match returns true if r matches m.
modules/caddyhttp/reverseproxy/reverseproxy.go
+13
-18
@@ -24,6 +24,7 @@ import (
24
"net"
25
"net/http"
26
"net/http/httptrace"
27
+ "net/netip"
28
"net/textproto"
29
"net/url"
30
"regexp"
@@ -180,7 +181,7 @@ type Handler struct {
181
DynamicUpstreams UpstreamSource `json:"-"`
182
183
// Holds the parsed CIDR ranges from TrustedProxies
183
- trustedProxies []*net.IPNet
184
+ trustedProxies []netip.Prefix
185
186
// Holds the named response matchers from the Caddyfile while adapting
187
responseMatchers map[string]caddyhttp.ResponseMatcher
@@ -251,24 +252,18 @@ func (h *Handler) Provision(ctx caddy.Context) error {
252
// parse trusted proxy CIDRs ahead of time
253
for _, str := range h.TrustedProxies {
254
if strings.Contains(str, "/") {
254
- _, ipNet, err := net.ParseCIDR(str)
255
+ ipNet, err := netip.ParsePrefix(str)
256
if err != nil {
256
- return fmt.Errorf("parsing CIDR expression: %v", err)
257
+ return fmt.Errorf("parsing CIDR expression: '%s': %v", str, err)
258
}
259
h.trustedProxies = append(h.trustedProxies, ipNet)
260
} else {
260
- ip := net.ParseIP(str)
261
- if ip == nil {
262
- return fmt.Errorf("invalid IP address: %s", str)
263
- }
264
- if ipv4 := ip.To4(); ipv4 != nil {
265
- ip = ipv4
261
+ ipAddr, err := netip.ParseAddr(str)
262
+ if err != nil {
263
+ return fmt.Errorf("invalid IP address: '%s': %v", str, err)
264
}
267
- mask := len(ip) * 8
268
- h.trustedProxies = append(h.trustedProxies, &net.IPNet{
269
- IP: ip,
270
- Mask: net.CIDRMask(mask, mask),
271
- })
265
+ ipNew := netip.PrefixFrom(ipAddr, ipAddr.BitLen())
266
+ h.trustedProxies = append(h.trustedProxies, ipNew)
267
}
268
}
269
@@ -672,15 +667,15 @@ func (h Handler) addForwardedHeaders(req *http.Request) error {
667
if before, _, found := strings.Cut(clientIP, "%"); found {
668
clientIP = before
669
}
675
- ip := net.ParseIP(clientIP)
676
- if ip == nil {
677
- return fmt.Errorf("invalid client IP address: %s", clientIP)
670
+ ipAddr, err := netip.ParseAddr(clientIP)
671
+ if err != nil {
672
+ return fmt.Errorf("invalid IP address: '%s': %v", clientIP, err)
673
}
674
675
// Check if the client is a trusted proxy
676
trusted := false
677
for _, ipRange := range h.trustedProxies {
683
- if ipRange.Contains(ip) {
678
+ if ipRange.Contains(ipAddr) {
679
trusted = true
680
break
681
}
modules/caddytls/matchers.go
+16
-18
@@ -18,6 +18,7 @@ import (
18
"crypto/tls"
19
"fmt"
20
"net"
21
+ "net/netip"
22
"strings"
23
24
"github.com/caddyserver/caddy/v2"
@@ -65,8 +66,8 @@ type MatchRemoteIP struct {
66
// The IPs or CIDR ranges to *NOT* match.
67
NotRanges []string `json:"not_ranges,omitempty"`
68
68
- cidrs []*net.IPNet
69
- notCidrs []*net.IPNet
69
+ cidrs []netip.Prefix
70
+ notCidrs []netip.Prefix
71
logger *zap.Logger
72
}
73
@@ -105,38 +106,35 @@ func (m MatchRemoteIP) Match(hello *tls.ClientHelloInfo) bool {
106
if err != nil {
107
ipStr = remoteAddr // weird; maybe no port?
108
}
108
- ip := net.ParseIP(ipStr)
109
- if ip == nil {
109
+ ipAddr, err := netip.ParseAddr(ipStr)
110
+ if err != nil {
111
m.logger.Error("invalid client IP addresss", zap.String("ip", ipStr))
112
return false
113
}
113
- return (len(m.cidrs) == 0 || m.matches(ip, m.cidrs)) &&
114
- (len(m.notCidrs) == 0 || !m.matches(ip, m.notCidrs))
114
+ return (len(m.cidrs) == 0 || m.matches(ipAddr, m.cidrs)) &&
115
+ (len(m.notCidrs) == 0 || !m.matches(ipAddr, m.notCidrs))
116
}
117
117
-func (MatchRemoteIP) parseIPRange(str string) ([]*net.IPNet, error) {
118
- var cidrs []*net.IPNet
118
+func (MatchRemoteIP) parseIPRange(str string) ([]netip.Prefix, error) {
119
+ var cidrs []netip.Prefix
120
if strings.Contains(str, "/") {
120
- _, ipNet, err := net.ParseCIDR(str)
121
+ ipNet, err := netip.ParsePrefix(str)
122
if err != nil {
123
return nil, fmt.Errorf("parsing CIDR expression: %v", err)
124
}
125
cidrs = append(cidrs, ipNet)
126
} else {
126
- ip := net.ParseIP(str)
127
- if ip == nil {
128
- return nil, fmt.Errorf("invalid IP address: %s", str)
127
+ ipAddr, err := netip.ParseAddr(str)
128
+ if err != nil {
129
+ return nil, fmt.Errorf("invalid IP address: '%s': %v", str, err)
130
}
130
- mask := len(ip) * 8
131
- cidrs = append(cidrs, &net.IPNet{
132
- IP: ip,
133
- Mask: net.CIDRMask(mask, mask),
134
- })
131
+ ip := netip.PrefixFrom(ipAddr, ipAddr.BitLen())
132
+ cidrs = append(cidrs, ip)
133
}
134
return cidrs, nil
135
}
136
139
-func (MatchRemoteIP) matches(ip net.IP, ranges []*net.IPNet) bool {
137
+func (MatchRemoteIP) matches(ip netip.Addr, ranges []netip.Prefix) bool {
138
for _, ipRange := range ranges {
139
if ipRange.Contains(ip) {
140
return true