On Tue, Apr 15, 2014 at 6:13 AM, Willy Tarreau <[email protected]> wrote:

> 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
>
> Hi Willy--
    This makes sense.  With all the possible fields, I would prefer a more
machine friendly format. (I think that is your preference too.)
    How about a proxy protocol extension that can be appended to either V1
or V2?

     To configure, the command could look like:

send-proxy-extension 1,2,3,17,18,33,26

      The protocol could look like:

(2 bytes):    Total extension length (N) in network order
(N-2 bytes):  A series of TLVs

TLVs:
(1 byte)   :  Type Field as defined below
(2 bytes) :  Total length (N) of vector, in network order
(N-3 bytes) : Payload in format depending on type

Defined Vector Types
--------------------------------
1: interface name (string)
2: source mac address (in binary)
3: destination mac address (in binary)

17: ASN (string)

33: SSL Version (string)
34: SNI (string)
35: ALPN (string)
36: Certificate received (byte)
37: Certificate verify result (32 bit integer, network order)
38: Fully Distinguished Name (string)
39: Common Name (string)


For V1, we could replace "\r\n" with "0xffff" to signify the presence of
the extension.  For V2, we could borrow a bit somewhere in the header to
signify the same.

   What do you think?
--Dave

Reply via email to