I am trying to write a function that returns the client IPv4 address.
I fetch the string from http.Request.RemoteAddr
and filter out the ip with net.SplitHostPort
. This gives me ::1 because I am on localhost which I asume is supposed to be an IPv6 address?
then I do ip := net.ParseIP(s)
and then ip = ip.To4()
to get the IPv4 address.
I am on Windows and have this in my hosts file: (The rest is commented out.)
127.0.0.1 localhost localhost.com www.localhost.com *.localhost.com
Basically I expect to get 127.0.0.1, but I can't get it.
This is the code:
func FilterIpv4(r *http.Request) (string, error) {
var s string
// if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
// ip = xff
// }
s, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return "", err
}
ip := net.ParseIP(s)
ip = ip.To4()
spew.Dump(ip.String()) // outputs "<nil>"
return "", nil
}
EDIT:
I don't know if it is a good idea to do this but atleast I get the ipv4 addresses now. Maybe I should just stick to ipv6? I don't know about this. But replacing this code:
log.Fatal(http.ListenAndServe(":"+config.SrvPort, router))
With this:
ln, err := net.Listen("tcp4", ":"+config.SrvPort)
if err != nil {
log.Fatal(err)
}
log.Fatal(http.Serve(ln, router))
Made it possible for me to get the ipv4 address.
Does someone know if this is a good idea in general? Or should I stick to ipv6 addresses?
EDIT 2:
I ended up with this function:
func FilterIP(r *http.Request) (string, error) {
var ip string
var err error
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
ips := strings.Split(xff, ", ")
ip = ips[0]
} else {
ip, _, err = net.SplitHostPort(r.RemoteAddr)
if err != nil {
return "", err
}
}
if !IsIP(ip) {
return "", err
}
return ip, nil
}
I will save both ipv6 and ipv4 addresses.