mirror of
https://github.com/schollz/hostyoself.git
synced 2026-01-23 02:15:14 +00:00
116 lines
3.2 KiB
Go
116 lines
3.2 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"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
|
|
|
|
}
|
|
|
|
const letterBytes = "abcdefghijklmnopqrstuvwxyz"
|
|
const (
|
|
letterIdxBits = 6 // 6 bits to represent a letter index
|
|
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
|
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
|
)
|
|
|
|
func RandStringBytesMaskImpr(n int) string {
|
|
b := make([]byte, n)
|
|
// A rand.Int63() generates 63 random bits, enough for letterIdxMax letters!
|
|
for i, cache, remain := n-1, rand.Int63(), letterIdxMax; i >= 0; {
|
|
if remain == 0 {
|
|
cache, remain = rand.Int63(), letterIdxMax
|
|
}
|
|
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
|
b[i] = letterBytes[idx]
|
|
i--
|
|
}
|
|
cache >>= letterIdxBits
|
|
remain--
|
|
}
|
|
|
|
return string(b)
|
|
}
|