proxyaddr

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package proxyaddr determines the real client address of a request that has passed through one or more trusted reverse proxies. It is a Go port of the npm module "proxy-addr", the same logic Express uses to implement its "trust proxy" setting and the req.ip / req.ips accessors.

When an application sits behind a load balancer, CDN, or reverse proxy, the socket's remote address is the address of the nearest proxy rather than the end user. Each hop is expected to append the address it saw to the X-Forwarded-For header, producing a left-to-right list that runs from the original client through every intermediary. Because any of those values can be forged by a client, they can only be trusted up to the point where the chain leaves infrastructure you control. This package encodes that decision: given the socket address, the header, and a predicate describing which hops are trusted, it returns the closest address that is not itself a trusted proxy.

The forwarded chain is derived from the socket remote address plus the X-Forwarded-For header, in the same reverse ordering used by the "forwarded" module: the socket address comes first, followed by the header entries read from rightmost (nearest proxy) to leftmost (original client). Starting from the socket address, the chain is walked while each address is trusted; the first untrusted address is the real client address. If every address in the chain is trusted, the topmost (leftmost header) address is returned. All returns that full ordered chain, ProxyAddr returns the single resolved client address, and All combined with a trust predicate lets callers build the equivalent of Express's req.ips.

The trust predicate is a func(addr string, i int) bool that receives each candidate address and its index in the chain. Callers may supply arbitrary logic, but Compile builds a predicate from a list of trusted CIDR strings, bare IP addresses (treated as single-host /32 or /128 ranges), and the named presets recognized by proxy-addr. The presets are "loopback" (127.0.0.1/8 and ::1/128), "linklocal" (169.254.0.0/16 and fe80::/10), and "uniquelocal" (the RFC 1918 private IPv4 blocks 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 plus the IPv6 unique-local block fc00::/7). Preset names are matched case-insensitively.

Edge cases follow the Node semantics closely. Addresses may carry a port (including bracketed IPv6 literals such as "[::1]:8080"); the port is stripped before comparison. An empty X-Forwarded-For yields a chain of just the socket address. Compile returns an error for an empty trust value or any entry that is neither a preset nor a valid CIDR/IP, and the predicate it returns reports false for addresses that fail to parse rather than treating them as trusted. The chief parity gap versus the JavaScript original is that this port operates on the raw remote-address and header strings a Go handler already has, rather than on a Node request object.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All(remoteAddr, xff string) []string

All returns the full forwarded address chain for the request, starting with the socket remote address followed by the X-Forwarded-For entries in reverse order.

Example

ExampleAll returns the full forwarded address chain without applying any trust decision, which is useful for logging or for building the equivalent of Express's req.ips. The chain always begins with the socket remote address, followed by the X-Forwarded-For entries read from right (nearest proxy) to left (original client). Here the socket address 127.0.0.1 comes first, then the rightmost header value 198.51.100.2, then the leftmost 203.0.113.1. Callers can pair this ordering with a trust predicate to reason about each hop.

package main

import (
	"fmt"

	"github.com/malcolmston/express/proxyaddr"
)

func main() {
	fmt.Println(proxyaddr.All("127.0.0.1", "203.0.113.1, 198.51.100.2"))
}
Output:
[127.0.0.1 198.51.100.2 203.0.113.1]

func Compile

func Compile(vals []string) (func(addr string, i int) bool, error)

Compile builds a trust function from a list of trusted CIDR strings and/or the named presets "loopback", "linklocal", and "uniquelocal". The returned function reports whether a given address falls within any of the trusted ranges. It returns an error if any value is not a valid preset or CIDR.

func ProxyAddr

func ProxyAddr(remoteAddr, xff string, trust func(addr string, i int) bool) string

ProxyAddr walks the forwarded chain and returns the first address that is not trusted according to trust. The trust function receives each candidate address and its index in the chain. Walking starts at the socket address and continues up the chain while the current address is trusted. If every address in the chain is trusted, the topmost (leftmost header) address is returned.

Example

ExampleProxyAddr resolves the real client address of a request that arrived through a trusted reverse proxy. Compile builds a trust predicate from the "loopback" preset, which trusts 127.0.0.1 and ::1. The socket's remote address is the loopback proxy, and the X-Forwarded-For header carries the original client address 203.0.113.1. Because the socket hop is trusted, the walk steps past it to the header entry, and since that address is not itself trusted it is returned as the client. This is the logic behind Express's req.ip under a "trust proxy" setting.

package main

import (
	"fmt"

	"github.com/malcolmston/express/proxyaddr"
)

func main() {
	trust, err := proxyaddr.Compile([]string{"loopback"})
	if err != nil {
		panic(err)
	}
	fmt.Println(proxyaddr.ProxyAddr("127.0.0.1", "203.0.113.1", trust))
}
Output:
203.0.113.1

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL