v1: accept plain IPv4 addresses in TCP6 headers#167
Open
cmarker-gl wants to merge 1 commit intopires:mainfrom
Open
v1: accept plain IPv4 addresses in TCP6 headers#167cmarker-gl wants to merge 1 commit intopires:mainfrom
cmarker-gl wants to merge 1 commit intopires:mainfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When proxying SSH connections through a chain involving nginx's OSS stream module, PROXY protocol v1 headers with mixed address families are emitted and currently rejected by this library.
The chain looks like:
nginx's OSS stream module (
proxy_protocol on) always re-encodes as PROXY protocol v1. When the original client is IPv6 but the backend is IPv4, nginx emits:This is technically outside the strict spec (which says both addresses in a
TCP6header should be IPv6 format), but it is the real-world output of a widely deployed proxy and there is no workaround available in nginx OSS.go-proxyproto was returning
proxyproto: invalid addressfor these headers, causing the connection to fail. IPv4-only connections worked fine.Root Cause
parseV1IPAddressinv1.gohandledTCPv6by accepting addresses whereaddr.Is6()oraddr.Is4In6()(i.e.::ffff:x.x.x.xnotation). A plain IPv4 address like192.0.2.1parses asaddr.Is4()— neither condition matched, so it fell through toErrInvalidAddress.Fix
When parsing a
TCPv6header and the address is a plain IPv4, promote it to a 16-byte IPv4-mapped-IPv6 representation viaaddr.As16(). This is consistent with hownet.IP.To16()works elsewhere in the library and produces a validnet.IPthat callers can use normally.Tests
"TCP6 with IPv4 addresses"invalid test, which was asserting the now-intentionally-relaxed behaviourPROXY TCP4 1.2.3.4 5.6.7.8 12345 22\r\n— baseline IPv4PROXY TCP6 2001:db8::1 192.0.2.1 51512 22\r\n— IPv6 src, IPv4 dst (the nginx mixed case);skipWrite: truesince round-trip serialisation changes the destination representationPROXY TCP6 ::1 ::1 1234 5678\r\n— loopback IPv6Notes