Hi David, On Mon, Apr 14, 2014 at 09:54:19PM -0400, David S wrote: > Hello-- > Part of my solution uses a non-HTTP protocol. My backend server need > L3/L4 information, so the PROXY protocol is a perfect fit. In addition to > TCP and IP addresses, my backend server needs information from the client > SSL connection. So, I would like to extend the PROXY protocol. > I want to keep the protocol header small, extensible, and backwards > compatible. > > The current version 1 header looks like: > PROXY TCP4 1.2.3.4 2.3.4.5 51111 443\r\n > It is sent when the server keyword "send-proxy" is configured. > > I propose a Version 1-SSL that can be sent when a new server keyword > "send-proxy-ssl" is configured. > It would look like: > PROXY SSL4 1.2.3.4 2.3.4.5 51111 443 1 0 CN="certificate common name"\r\n > > The rules to follow would be: > 1) If the connection is not SSL, then the original TCP4 format is used > 2) The first integer after the destination port is: > 0 if not client certifcate was sent > 1 if a client certificate was sent > 3) The second integer after destination port is: > 0 if the certificate verified > X the return code from the SSL verify() function if the certificate > did not verify > 4) Delimited by quotation marks, following CN=, is the Common Name from the > client certificate. > > My hope is these values will solve most people's needs, and if not, this > format can be easily extended. > > I intend this email to start a discussion, but I am also attaching a code > patch implementing the above. > > My To Do List: > 1) remove printf() in src/stream_interface.c left in for ease of testing > 2) update doc/configuration.txt > 3) update doc/proxy-protocol.txt > > Please let me know your feedback.
I have nothing against the patch itself but don't completely agree with the change for a few reasons that were discussed at the beginning of the year when you started that thread : - other fields will have to be exchanged as well (SNI, ALPN, TLS version, ciphers immediately come to mind) - replacing the L4 protocol with a new name will only ask server-side to support the two versions. Thus I'd suggest *not* to change the L4 keyword and keep TCP4 or TCP6 there. I think that one way of extending the protocol would be by adding fields at the end of the line before the CRLF. That way, existing implementations can easily be upgraded (eg: check for CRLF or space and ignore the rest). And we keep the leftmost part of the protocol for the lower layers and the rightmost part for the upper layers as it is right now. Thus the following string : PROXY SSL4 1.2.3.4 2.3.4.5 51111 443 1 0 CN="certificate common name"\r\n Could become something more or less like this : PROXY TCP4 1.2.3.4 2.3.4.5 51111 443 SSL 1 0 CN="certificate common name"\r\n After the next protocol name (SSL here), we absolutely need to specify the version (eg: 3.1). I agree with passing some information about the result of the cert check and the cert name when available. Most people will definitely want ALPN/SNI over CN. So that's something we must pass as well when known. I also agree with using FIELD="quoted value" for any field there. I'm wondering whether we should "register" a certain number of field names or also support some hex-encoded opaque extensions. Maybe that would become harder to standarize in the long run however. Another thing to keep in mind is that other people want to see the incoming interface name, which would conflict with this format. Thus I'm thinking that we could proceed with a stricter format after the TCP ports : (PROTONAME (FIELD=value|quoted_value)*)* That means that "SSL" would indicate that whatever follows is still related to SSL as long as there are equal signs after the words, and that each new name without an equal sign indicates a different layer. Thus it could lead to something like this for someone who would like to add more fields : PROXY TCP4 1.2.3.4 2.3.4.5 51111 443 DEV IF=eth0 MAC SRC=00:01:02:03:04:05 DST=02:03:04:05:06:07 IP ASN=12345 SSL VER=3.1 SNI="www.example.com" ALPN="spdy/3.1" CRT=1 RES=0 CN="certificate common name"\r\n The parser just has to focus on the relevant parts. And even with something that large, it remains easy for any existing parser to ignore the extra parts or to only pick the one it needs. I really think that we should design with such possibilities in mind, and it will allow for easier later enhancements even in your use case to support extra fields. I'm pretty sure that some fields could easily be added within the same "context" (eg: IF, SRC, ...). That's something to think about when naming or grouping fields. Some container-based systems might want to see a context number for example. Unix-based sockets will like to pass an UID. Some virtualized systems might want to indicate the UUID of the originating VM sometimes. Thus maybe we'll finally configure the send-proxy parameter to specify what fields we want to report, and the recipient will simply ignore those it's not interestd in. Note that this probably marks the death of protocol v2 that nobody implemented yet, but that was supposed to be easier to parse... Willy