Restrict Host-based origin fetches to Steam CDN names.
When upstream is empty the cache used the client Host as the fetch URL, so any LAN client with a spoofed Steam User-Agent could proxy to literal IPs or arbitrary names. Reject those hosts, stop following upstream redirects, and keep path-only cache keys so real Steam CDNs still share entries.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -163,3 +164,44 @@ func generateServiceCacheKey(urlPath string, servicePrefix string) (string, erro
|
||||
}
|
||||
return servicePrefix + "/" + hash, nil
|
||||
}
|
||||
|
||||
// requestHostName strips a port and brackets from an HTTP Host header.
|
||||
func requestHostName(host string) string {
|
||||
host = strings.TrimSpace(host)
|
||||
if host == "" {
|
||||
return ""
|
||||
}
|
||||
if h, _, err := net.SplitHostPort(host); err == nil {
|
||||
host = h
|
||||
}
|
||||
return strings.Trim(host, "[]")
|
||||
}
|
||||
|
||||
func hostIsLiteralIP(host string) bool {
|
||||
return net.ParseIP(requestHostName(host)) != nil
|
||||
}
|
||||
|
||||
// defaultDirectFetchSuffixes are CDN names Steam actually uses. Applied only when
|
||||
// no configured upstream is set and the request Host is used as the fetch target.
|
||||
var defaultDirectFetchSuffixes = []string{
|
||||
"steamcontent.com",
|
||||
"steampowered.com",
|
||||
"steamstatic.com",
|
||||
}
|
||||
|
||||
// hostAllowedForDirectFetch reports whether Host may be used as an origin when
|
||||
// upstream is empty. Literal IPs are rejected (LAN/metadata SSRF). Names must
|
||||
// be Steam CDN suffixes so a spoofed User-Agent cannot turn the cache into an
|
||||
// open reverse proxy.
|
||||
func hostAllowedForDirectFetch(host string) bool {
|
||||
name := strings.ToLower(requestHostName(host))
|
||||
if name == "" || hostIsLiteralIP(host) {
|
||||
return false
|
||||
}
|
||||
for _, suf := range defaultDirectFetchSuffixes {
|
||||
if name == suf || strings.HasSuffix(name, "."+suf) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user