Skip to content

RealIP sets r.RemoteAddr without port #453

@Dirbaio

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions