XTLS/Xray-core · error · errors.Error

failed to set PROXY protocol v{version}

Error message

failed to set PROXY protocol v{version}

What it means

freedom is configured with settings.proxyProtocol (v1 or v2) and failed while writing the HAProxy PROXY-protocol header onto the freshly dialed connection. The header carries the inbound source address and the remote destination; a write failure at this point means the socket broke between dial success and first write, so the conn is closed and the error wrapped with the version byte.

Source

Thrown at proxy/freedom/freedom.go:374

			common.Interrupt(input)
			common.Interrupt(output)
			errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *blockedDest)
		})
		defer timer.Stop()
		defer common.Close(output)
		if err := buf.Copy(input, buf.Discard); err != nil {
			return nil
		}
		return nil
	}
	if h.config.ProxyProtocol > 0 && h.config.ProxyProtocol <= 2 {
		version := byte(h.config.ProxyProtocol)
		srcAddr := inbound.Source.RawNetAddr()
		dstAddr := conn.RemoteAddr()
		header := proxyproto.HeaderProxyFromAddrs(version, srcAddr, dstAddr)
		if _, err = header.WriteTo(conn); err != nil {
			conn.Close()
			return errors.New("failed to set PROXY protocol v", version).Base(err)
		}
	}
	defer conn.Close()
	errors.LogInfo(ctx, "connection opened to ", destination, ", local endpoint ", conn.LocalAddr(), ", remote endpoint ", conn.RemoteAddr())

	var newCtx context.Context
	var newCancel context.CancelFunc
	if session.TimeoutOnlyFromContext(ctx) {
		newCtx, newCancel = context.WithCancel(context.Background())
	}

	plcy := h.policy()
	ctx, cancel := context.WithCancel(ctx)
	timer := signal.CancelAfterInactivity(ctx, func() {
		cancel()
		if newCancel != nil {
			newCancel()
		}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Confirm the destination server actually speaks PROXY protocol and expects it on this port
  2. Match versions exactly: proxyProtocol:1 for servers expecting v1 text, 2 for binary v2
  3. If the server does not want it, remove settings.proxyProtocol from the outbound
  4. Check for middleboxes/LB in path that strip or reject the header

Example fix

// before
"settings": { "proxyProtocol": 2 }  // target has no PROXY support
// after
"settings": { }
Defensive patterns

Strategy: validation

Try / catch

```go
if err := h.Process(ctx, link, dialer); err != nil {
    if strings.Contains(err.Error(), "failed to set PROXY protocol") {
        // conn already closed; verify server expects the protocol/version
    }
}
```

Prevention

When it happens

Trigger: settings.proxyProtocol: 1 or 2 in the freedom outbound, and the target closes/RESETs the connection immediately after accept (non-PROXY-protocol-aware server), or a middlebox kills the session on first bytes.

Common situations: Sending PROXY protocol to a server that does not expect it (server RSTs the malformed first line), proxyProtocol value out of sync between sender and receiver versions (v1 vs v2), or an aggressive firewall resetting new flows.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/46f2b65797fb2abe. Report an issue: GitHub.