FAQ
In my web app (which uses built-in http server) I sometimes need to
know the ip address of the user. I use http.Request.RemoteAddr for
that.

However, it runs on a server on local port behind nginx proxy and in
that scenario RemoteAddr is localhost i.e. 127.0.0.1

My nginx.conf is
https://github.com/kjk/apptranslator/blob/master/scripts/nginx.conf

I do use "proxy_set_header X-Real-IP $remote_addr;" but this is just
config I copied from somewhere else (I'm not nginx expert).

Is there some nginx config that I can use so that http server would
set http.Request.RemoteAddr "properly" in the proxying scenario or is
the right solution to use value of X-Real-IP header instead of
RemoteAddr?

-- kjk

--

Search Discussions

  • Dave Cheney at Oct 21, 2012 at 3:57 am
    The canonical solution is to use X-Forwarded-For.
    On 21/10/2012, at 14:53, Krzysztof Kowalczyk wrote:

    In my web app (which uses built-in http server) I sometimes need to
    know the ip address of the user. I use http.Request.RemoteAddr for
    that.

    However, it runs on a server on local port behind nginx proxy and in
    that scenario RemoteAddr is localhost i.e. 127.0.0.1

    My nginx.conf is
    https://github.com/kjk/apptranslator/blob/master/scripts/nginx.conf

    I do use "proxy_set_header X-Real-IP $remote_addr;" but this is just
    config I copied from somewhere else (I'm not nginx expert).

    Is there some nginx config that I can use so that http server would
    set http.Request.RemoteAddr "properly" in the proxying scenario or is
    the right solution to use value of X-Real-IP header instead of
    RemoteAddr?

    -- kjk

    --
    --
  • PeteT at Oct 21, 2012 at 4:31 am
    When running behind a proxy, wrap your application's mux with a handler
    that modifies the request with the x-fowarded-for header:

    type remoteAddrFixup struct {
    h http.Handler
    }

    func (h remoteAddrFixup) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    r.RemoteAddr = r.Header.Get("X-Forwarded-For")
    h.h(w, r)
    }

    Assuming that you are using the default serve mux, you can do something
    like this in your application main:

    var h http.Handler
    if runningBehindProxy {
    h = remoteAddrFixup{http.DefaultServeMux}
    } else {
    h = http.DefaultServeMux
    }
    http.ListenAndServe(addr, h)

    --
  • Krzysztof Kowalczyk at Oct 21, 2012 at 6:43 am
    Thanks Pete and Dave, those are good tips.

    I did some additional research and here's what I ended up doing (for
    posterity and in case someone has tips on how to further improve the
    code):

    // Request.RemoteAddress contains port, which we want to remove i.e.:
    // "[::1]:58292" => "[::1]"
    func ipAddrFromRemoteAddr(s string) string {
    idx := strings.LastIndex(s, ":")
    if idx == -1 {
    return s
    }
    return s[:idx]
    }

    func getIpAddress(r *http.Request) string {
    hdr := r.Header
    hdrRealIp := hdr.Get("X-Real-Ip")
    hdrForwardedFor := hdr.Get("X-Forwarded-For")
    if hdrRealIp == "" && hdrForwardedFor == "" {
    return ipAddrFromRemoteAddr(r.RemoteAddr)
    }
    if hdrForwardedFor != "" {
    // X-Forwarded-For is potentially a list of addresses separated with ","
    parts := strings.Split(hdrForwardedFor, ",")
    for i, p := range parts {
    parts[i] = strings.TrimSpace(p)
    }
    // TODO: should return first non-local address
    return parts[0]
    }
    return hdrRealIp
    }

    The main point of the code is that "X-Forwarded-For" header can be a
    list of ip addresses and I also use "X-Real-Ip" if "X-Forwarded-For"
    is not present.

    According to http://rod.vagg.org/2011/07/wrangling-the-x-forwarded-for-header/,
    I should really use the first non-local ip address from
    "X-Forwarded-For" list but I ran out of steam.

    -- kjk
    On Sat, Oct 20, 2012 at 9:31 PM, PeteT wrote:
    When running behind a proxy, wrap your application's mux with a handler that
    modifies the request with the x-fowarded-for header:

    type remoteAddrFixup struct {
    h http.Handler
    }

    func (h remoteAddrFixup) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    r.RemoteAddr = r.Header.Get("X-Forwarded-For")
    h.h(w, r)
    }

    Assuming that you are using the default serve mux, you can do something like
    this in your application main:

    var h http.Handler
    if runningBehindProxy {
    h = remoteAddrFixup{http.DefaultServeMux}
    } else {
    h = http.DefaultServeMux
    }
    http.ListenAndServe(addr, h)

    --
    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedOct 21, '12 at 3:53a
activeOct 21, '12 at 6:43a
posts4
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase