1
0
Fork 0
forked from External/ergo

more work on websocket support

This commit is contained in:
Shivaram Lingamneni 2020-05-04 22:29:10 -04:00
parent 25813f6d3a
commit 3dc5c8de78
17 changed files with 830 additions and 444 deletions

View file

@ -22,19 +22,13 @@ var (
func AddrToIP(addr net.Addr) net.IP {
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
return tcpaddr.IP.To16()
} else if AddrIsUnix(addr) {
} else if _, ok := addr.(*net.UnixAddr); ok {
return IPv4LoopbackAddress
} else {
return nil
}
}
// AddrIsUnix returns whether the address is a unix domain socket.
func AddrIsUnix(addr net.Addr) bool {
_, ok := addr.(*net.UnixAddr)
return ok
}
// IPStringToHostname converts a string representation of an IP address to an IRC-ready hostname
func IPStringToHostname(ipStr string) string {
if 0 < len(ipStr) && ipStr[0] == ':' {
@ -158,3 +152,44 @@ func ParseNetList(netList []string) (nets []net.IPNet, err error) {
}
return
}
// Process the X-Forwarded-For header, validating against a list of trusted IPs.
// Returns the address that the request was forwarded for, or nil if no trustworthy
// data was available.
func HandleXForwardedFor(remoteAddr string, xForwardedFor string, whitelist []net.IPNet) (result net.IP) {
// http.Request.RemoteAddr "has no defined format". with TCP it's typically "127.0.0.1:23784",
// with unix domain it's typically "@"
var remoteIP net.IP
host, _, err := net.SplitHostPort(remoteAddr)
if err != nil {
remoteIP = IPv4LoopbackAddress
} else {
remoteIP = net.ParseIP(host)
}
if remoteIP == nil || !IPInNets(remoteIP, whitelist) {
return remoteIP
}
// walk backwards through the X-Forwarded-For chain looking for an IP
// that is *not* trusted. that means it was added by one of our trusted
// forwarders (either remoteIP or something ahead of it in the chain)
// and we can trust it:
result = remoteIP
forwardedIPs := strings.Split(xForwardedFor, ",")
for i := len(forwardedIPs) - 1; i >= 0; i-- {
proxiedIP := net.ParseIP(strings.TrimSpace(forwardedIPs[i]))
if proxiedIP == nil {
return
} else if !IPInNets(proxiedIP, whitelist) {
return proxiedIP
} else {
result = proxiedIP
}
}
// no valid untrusted IPs were found in the chain;
// return either the last valid and trusted IP (which must be the origin),
// or nil:
return
}