Skip to content

RealIP sets r.RemoteAddr without port #453

Description

@Dirbaio

The Go documentation states the following on http.Request.RemoteAddr:

The HTTP server in this package sets RemoteAddr to an "IP:port" address before invoking a handler.

Therefore, you could expect that a code like this is correct:

package main

import (
	"fmt"
	"net"
	"net/http"

	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"
)

func main() {
	r := chi.NewMux()
	r.Use(middleware.RealIP)
	r.Get("/test", func(rw http.ResponseWriter, r *http.Request) {
		host, port, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			fmt.Fprintf(rw, "Error: %v\n", err)
		} else {
			fmt.Fprintf(rw, "Host: %s\nPort: %s\n", host, port)
		}
	})
	http.ListenAndServe(":8000", r)
}

However, the RealIP middleware is just copying the X-Forwarded-For value into r.RemoteAddr, which usually does not contain a port, making the code fail:

[dirbaio@mars]$ curl localhost:8000/test
Host: ::1
Port: 40188
[dirbaio@mars]$ curl localhost:8000/test -H 'X-Forwarded-For: 1.2.3.4'
Error: address 1.2.3.4: missing port in address
[dirbaio@mars]$ curl localhost:8000/test -H 'X-Forwarded-For: ::1'
Error: address ::1: too many colons in address

Perhaps RealIP should try to parse X-Forwarded-For for a host:port, and if it isn't, add a port? Maybe 0 to denote the port is unknown, like 1.2.3.4 -> 1.2.3.4:0?

This is particularly frustrating with IPv6 addresses because they have colons but they're not the host:port colon, making it hard to parse the RemoteAddr in user code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions