hardening(proxy): don't proxy private IP addresses

...by default.

This is useful when `RelayDomainNamePattern` is lax (e.g. just "$")
(which is not the case by default, so this is simply
a hardening measure).
This commit is contained in:
WofWca 2024-08-31 22:05:34 +04:00 committed by Shelikhoo
parent 399bda5257
commit 94c6089cdd
No known key found for this signature in database
GPG key ID: 4C9764E9FE80A3DC
4 changed files with 45 additions and 9 deletions

View file

@ -138,7 +138,12 @@ type SnowflakeProxy struct {
// There is no look ahead assertion when matching domain name suffix,
// thus the string prepend the suffix does not need to be empty or ends with a dot.
RelayDomainNamePattern string
AllowNonTLSRelay bool
// AllowProxyingToPrivateAddresses determines whether to allow forwarding
// client connections to private IP addresses.
// Useful when a Snowflake server (relay) is hosted on the same private network
// as this proxy.
AllowProxyingToPrivateAddresses bool
AllowNonTLSRelay bool
// NATProbeURL is the URL of the probe service we use for NAT checks
NATProbeURL string
// NATTypeMeasurementInterval is time before NAT type is retested
@ -601,7 +606,7 @@ func (sf *SnowflakeProxy) runSession(sid string) {
log.Printf("Received Offer From Broker: \n\t%s", strings.ReplaceAll(offer.SDP, "\n", "\n\t"))
if relayURL != "" {
if err := checkIsRelayURLAcceptable(sf.RelayDomainNamePattern, sf.AllowNonTLSRelay, relayURL); err != nil {
if err := checkIsRelayURLAcceptable(sf.RelayDomainNamePattern, sf.AllowProxyingToPrivateAddresses, sf.AllowNonTLSRelay, relayURL); err != nil {
log.Printf("bad offer from broker: %v", err)
tokens.ret()
return
@ -644,6 +649,7 @@ func (sf *SnowflakeProxy) runSession(sid string) {
// Returns nil if the relayURL is acceptable
func checkIsRelayURLAcceptable(
allowedHostNamePattern string,
allowPrivateIPs bool,
allowNonTLSRelay bool,
relayURL string,
) error {
@ -651,6 +657,16 @@ func checkIsRelayURLAcceptable(
if err != nil {
return fmt.Errorf("bad Relay URL %w", err)
}
if !allowPrivateIPs {
ip := net.ParseIP(parsedRelayURL.Hostname())
// Otherwise it's a domain name, or an invalid IP.
if ip != nil {
// We should probably use a ready library for this.
if !isRemoteAddress(ip) {
return fmt.Errorf("rejected Relay URL: private IPs are not allowed")
}
}
}
if !allowNonTLSRelay && parsedRelayURL.Scheme != "wss" {
return fmt.Errorf("rejected Relay URL protocol: non-TLS not allowed")
}