fatedier/frp · error

failed to write proxy protocol header: %v

Error message

failed to write proxy protocol header: %v

What it means

BuildProxyProtocolHeader serializes a proxy-protocol header struct (v1 or v2, built by HeaderProxyFromAddrs) into a bytes.Buffer via WriteTo. Because the destination is an in-memory bytes.Buffer, WriteTo only fails if the header object itself refuses to encode — e.g. an address family that the proxy protocol cannot represent. Real network failures cannot occur here.

Source

Thrown at pkg/util/net/proxyprotocol.go:42

func BuildProxyProtocolHeaderStruct(srcAddr, dstAddr net.Addr, version string) *pp.Header {
	var versionByte byte
	if version == "v1" {
		versionByte = 1
	} else {
		versionByte = 2 // default to v2
	}
	return pp.HeaderProxyFromAddrs(versionByte, srcAddr, dstAddr)
}

func BuildProxyProtocolHeader(srcAddr, dstAddr net.Addr, version string) ([]byte, error) {
	h := BuildProxyProtocolHeaderStruct(srcAddr, dstAddr, version)

	// Convert header to bytes using a buffer
	var buf bytes.Buffer
	_, err := h.WriteTo(&buf)
	if err != nil {
		return nil, fmt.Errorf("failed to write proxy protocol header: %v", err)
	}
	return buf.Bytes(), nil
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Pass plain *net.TCPAddr (or UDP/Unix addrs) as srcAddr/dstAddr.
  2. If you wrap conns, make sure LocalAddr/RemoteAddr still return standard address types.
  3. On error, fall back to omitting the proxy protocol header for that connection.

Example fix

// before
hdr, err := netpkg.BuildProxyProtocolHeader(customAddr{network: "weird"}, dst, "v2")

// after
hdr, err := netpkg.BuildProxyProtocolHeader(conn.RemoteAddr().(*net.TCPAddr), conn.LocalAddr().(*net.TCPAddr), "v2")
Defensive patterns

Strategy: fallback

Validate before calling

// ensure addresses are proxy-protocol representable before building the header
func proxyProtocolRepresentable(addr net.Addr) bool {
    switch addr.(type) {
    case *net.TCPAddr, *net.UDPAddr, *net.UnixAddr:
        return true
    }
    return false
}

Try / catch

header, err := netpkg.BuildProxyProtocolHeader(srcAddr, dstAddr, version)
if err != nil {
    // degrade gracefully: serve the connection without PROXY info
    log.Warnf("proxy protocol header build failed: %v", err)
    header = nil
}

Prevention

When it happens

Trigger: srcAddr/dstAddr with a network type the proxy protocol library cannot map to a v1/v2 family (an exotic net.Addr implementation rather than TCPAddr/UDPAddr/UnixAddr), since v1 text encoding or v2 binary encoding of unsupported families fails.

Common situations: Custom net.Conn wrappers whose LocalAddr/RemoteAddr return bespoke address types; essentially never with standard TCP conns.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/c8adeaa22feac1e7. Report an issue: GitHub.