hostyoself/utils.go
2019-07-10 06:27:21 -07:00

90 lines
2.5 KiB
Go

package main
import (
"errors"
"fmt"
"net"
"net/http"
"net/url"
)
// GetClientIPHelper gets the client IP using a mixture of techniques.
// This is how it is with golang at the moment.
func GetClientIPHelper(req *http.Request) (ipResult string, errResult error) {
// Try lots of ways :) Order is important.
// Try Request Headers (X-Forwarder). Client could be behind a Proxy
ip, err := getClientIPByHeaders(req)
if err == nil {
// log.Printf("debug: Found IP using Request Headers sniffing. ip: %v", ip)
return ip, nil
}
// Try by Request
ip, err = getClientIPByRequestRemoteAddr(req)
if err == nil {
// log.Printf("debug: Found IP using Request sniffing. ip: %v", ip)
return ip, nil
}
// Try Request Header ("Origin")
url, err := url.Parse(req.Header.Get("Origin"))
if err == nil {
host := url.Host
ip, _, err := net.SplitHostPort(host)
if err == nil {
// log.Printf("debug: Found IP using Header (Origin) sniffing. ip: %v", ip)
return ip, nil
}
}
err = errors.New("error: Could not find clients IP address")
return "", err
}
// getClientIPByRequest tries to get directly from the Request.
// https://blog.golang.org/context/userip/userip.go
func getClientIPByRequestRemoteAddr(req *http.Request) (ip string, err error) {
// Try via request
ip, _, err = net.SplitHostPort(req.RemoteAddr)
if err != nil {
// log.Printf("debug: Getting req.RemoteAddr %v", err)
return "", err
} else {
// log.Printf("debug: With req.RemoteAddr found IP:%v; Port: %v", ip, port)
}
userIP := net.ParseIP(ip)
if userIP == nil {
message := fmt.Sprintf("debug: Parsing IP from Request.RemoteAddr got nothing.")
// log.Printf(message)
return "", fmt.Errorf(message)
}
// log.Printf("debug: Found IP: %v", userIP)
return userIP.String(), nil
}
// getClientIPByHeaders tries to get directly from the Request Headers.
// This is only way when the client is behind a Proxy.
func getClientIPByHeaders(req *http.Request) (ip string, err error) {
// Client could be behid a Proxy, so Try Request Headers (X-Forwarder)
ipSlice := []string{}
ipSlice = append(ipSlice, req.Header.Get("X-Forwarded-For"))
ipSlice = append(ipSlice, req.Header.Get("x-forwarded-for"))
ipSlice = append(ipSlice, req.Header.Get("X-FORWARDED-FOR"))
for _, v := range ipSlice {
// log.Printf("debug: client request header check gives ip: %v", v)
if v != "" {
return v, nil
}
}
err = errors.New("error: Could not find clients IP address from the Request Headers")
return "", err
}