mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-30 22:34:15 -05:00
caddyhttp: Remote IP prefix placeholders
See https://github.com/mholt/caddy-ratelimit/issues/12
This commit is contained in:
parent
5e52bbb136
commit
9873ff9918
2 changed files with 48 additions and 4 deletions
|
@ -31,6 +31,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -196,6 +197,37 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo
|
||||||
return or.URL.RawQuery, true
|
return or.URL.RawQuery, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remote IP range/prefix (e.g. keep top 24 bits of 1.2.3.4 => "1.2.3.0/24")
|
||||||
|
// syntax: "/V4,V6" where V4 = IPv4 bits, and V6 = IPv6 bits; if no comma, then same bit length used for both
|
||||||
|
// (EXPERIMENTAL)
|
||||||
|
if strings.HasPrefix(key, "http.request.remote.host/") {
|
||||||
|
host, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
host = req.RemoteAddr // assume no port, I guess?
|
||||||
|
}
|
||||||
|
addr, err := netip.ParseAddr(host)
|
||||||
|
if err != nil {
|
||||||
|
return host, true // not an IP address
|
||||||
|
}
|
||||||
|
// extract the bits from the end of the placeholder (start after "/") then split on ","
|
||||||
|
bitsBoth := key[strings.Index(key, "/")+1:]
|
||||||
|
ipv4BitsStr, ipv6BitsStr, cutOK := strings.Cut(bitsBoth, ",")
|
||||||
|
bitsStr := ipv4BitsStr
|
||||||
|
if addr.Is6() && cutOK {
|
||||||
|
bitsStr = ipv6BitsStr
|
||||||
|
}
|
||||||
|
// convert to integer then compute prefix
|
||||||
|
bits, err := strconv.Atoi(bitsStr)
|
||||||
|
if err != nil {
|
||||||
|
return "", true
|
||||||
|
}
|
||||||
|
prefix, err := addr.Prefix(bits)
|
||||||
|
if err != nil {
|
||||||
|
return "", true
|
||||||
|
}
|
||||||
|
return prefix.String(), true
|
||||||
|
}
|
||||||
|
|
||||||
// hostname labels
|
// hostname labels
|
||||||
if strings.HasPrefix(key, reqHostLabelsReplPrefix) {
|
if strings.HasPrefix(key, reqHostLabelsReplPrefix) {
|
||||||
idxStr := key[len(reqHostLabelsReplPrefix):]
|
idxStr := key[len(reqHostLabelsReplPrefix):]
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TestHTTPVarReplacement(t *testing.T) {
|
||||||
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
|
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
req.Host = "example.com:80"
|
req.Host = "example.com:80"
|
||||||
req.RemoteAddr = "localhost:1234"
|
req.RemoteAddr = "192.168.159.32:1234"
|
||||||
|
|
||||||
clientCert := []byte(`-----BEGIN CERTIFICATE-----
|
clientCert := []byte(`-----BEGIN CERTIFICATE-----
|
||||||
MIIB9jCCAV+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1DYWRk
|
MIIB9jCCAV+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1DYWRk
|
||||||
|
@ -61,7 +61,7 @@ eqp31wM9il1n+guTNyxJd+FzVAH+hCZE5K+tCgVDdVFUlDEHHbS/wqb2PSIoouLV
|
||||||
req.TLS = &tls.ConnectionState{
|
req.TLS = &tls.ConnectionState{
|
||||||
Version: tls.VersionTLS13,
|
Version: tls.VersionTLS13,
|
||||||
HandshakeComplete: true,
|
HandshakeComplete: true,
|
||||||
ServerName: "foo.com",
|
ServerName: "example.com",
|
||||||
CipherSuite: tls.TLS_AES_256_GCM_SHA384,
|
CipherSuite: tls.TLS_AES_256_GCM_SHA384,
|
||||||
PeerCertificates: []*x509.Certificate{cert},
|
PeerCertificates: []*x509.Certificate{cert},
|
||||||
NegotiatedProtocol: "h2",
|
NegotiatedProtocol: "h2",
|
||||||
|
@ -97,7 +97,19 @@ eqp31wM9il1n+guTNyxJd+FzVAH+hCZE5K+tCgVDdVFUlDEHHbS/wqb2PSIoouLV
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: "http.request.remote.host",
|
get: "http.request.remote.host",
|
||||||
expect: "localhost",
|
expect: "192.168.159.32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
get: "http.request.remote.host/24",
|
||||||
|
expect: "192.168.159.0/24",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
get: "http.request.remote.host/24,32",
|
||||||
|
expect: "192.168.159.0/24",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
get: "http.request.remote.host/999",
|
||||||
|
expect: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: "http.request.remote.port",
|
get: "http.request.remote.port",
|
||||||
|
@ -146,7 +158,7 @@ eqp31wM9il1n+guTNyxJd+FzVAH+hCZE5K+tCgVDdVFUlDEHHbS/wqb2PSIoouLV
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: "http.request.tls.server_name",
|
get: "http.request.tls.server_name",
|
||||||
expect: "foo.com",
|
expect: "example.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
get: "http.request.tls.version",
|
get: "http.request.tls.version",
|
||||||
|
|
Loading…
Reference in a new issue