Skip to content

feat: support passing proxy_protocol to reality backend#2693

Open
aJC7737 wants to merge 1 commit into
MetaCubeX:Alphafrom
aJC7737:Alpha
Open

feat: support passing proxy_protocol to reality backend#2693
aJC7737 wants to merge 1 commit into
MetaCubeX:Alphafrom
aJC7737:Alpha

Conversation

@aJC7737

@aJC7737 aJC7737 commented Apr 12, 2026

Copy link
Copy Markdown

TL;DR: This change adds proxy-protocol support to Reality inbound so backends (for example NGINX) can see the original client source address.

Summary

This PR adds optional PROXY protocol support for Reality inbound fallback traffic.

A new reality-config.proxy-protocol option is added:

  • 0: disabled, default
  • 1: send PROXY protocol v1
  • 2: send PROXY protocol v2

When enabled, mihomo records the accepted client connection's source and local destination addresses, then writes the selected PROXY protocol header immediately after connecting to the Reality dest backend. This allows reverse proxy backends such as nginx to see the original client source IP and port instead of only seeing the mihomo-side connection.

The backend must be configured to accept PROXY protocol. Otherwise, the fallback TLS/HTTP traffic will be parsed incorrectly by the backend.

Implementation Notes

  • Adds proxy-protocol to Reality inbound config parsing.
  • Passes the option into the Reality listener config.
  • Stores accepted connection RemoteAddr() and LocalAddr() in the Reality context.
  • Writes the PROXY protocol header before fallback traffic is forwarded to dest.
  • Uses github.com/pires/go-proxyproto for standards-compliant v1/v2 header generation.
  • Validates proxy-protocol values during config build.
  • If the source/destination address pair cannot be represented as a concrete TCP4/TCP6 PROXY header, the implementation degrades to UNKNOWN/LOCAL and logs a warning instead of failing the fallback connection.

Testing

  • Added unit tests for disabled mode, PROXY v1/v2, IPv4, IPv6, invalid config values, degraded address handling, and configured dialer behavior.
  • Added an end-to-end listener-path test to verify that addresses from a real accepted TCP connection are propagated into the generated PROXY protocol header.

@aJC7737

aJC7737 commented May 8, 2026

Copy link
Copy Markdown
Author

New implementation a573147 vs the old 032a2fe and even older 25e89e2

Compared with the earlier implementation, this revision keeps the same user-facing config surface but improves correctness and maintainability:

  • Replaces manual PROXY protocol byte construction with github.com/pires/go-proxyproto, reducing custom protocol encoding logic.
  • Keeps support for both PROXY protocol v1 and v2.
  • Preserves the proxy-protocol: 0/1/2 behavior and validation.
  • Changes unsupported address handling from hard failure to spec-compliant degradation:
    • valid same-family TCP IPv4/IPv6 pairs still produce concrete TCP4/TCP6 headers;
    • missing, non-TCP, invalid, or mixed-family addresses now produce UNKNOWN/LOCAL headers and log a warning.
  • Avoids breaking Reality fallback connections in edge cases where listener wrappers, synthetic listeners, or future listener types provide addresses that cannot be represented as a concrete PROXY TCP address block.
  • Expands tests to parse generated headers through the PROXY protocol library instead of checking only hand-built byte layouts.
  • Adds coverage for degraded behavior.
  • Adds coverage for the full Reality listener path using a real accepted TCP connection, not only direct DialContext calls.
  • Promotes github.com/pires/go-proxyproto v0.8.0 to a direct dependency because the Reality listener now uses it directly.

@wwqgtxx
wwqgtxx force-pushed the Alpha branch 5 times, most recently from 61b8d7f to 17bed79 Compare May 15, 2026 10:13
@wwqgtxx
wwqgtxx force-pushed the Alpha branch 3 times, most recently from f513c49 to d67572b Compare June 12, 2026 02:06
Add a reality-config.proxy-protocol option for Reality inbound listeners.
When enabled, mihomo writes a PROXY protocol v1/v2 header to the Reality
fallback dest connection so reverse proxy backends can recover the original
client source IP and port.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant