Re: [PATCH] MINOR: acl: add support for TLS ALPN matching

2018-12-29 Thread Alex Zorin
Unfortunately I attached the wrong patch file. Attaching in reply.

Alex

On Sun, Dec 30, 2018, at 2:20 PM, Alex Zorin wrote:
> Hello,
> 
> The attached patch adds acl support for the TLS ALPN extension 
> (RFC7301) extension via  "req.ssl_alpn", in a similar vein to 
> "req.ssl_sni".
> 
> It is useful for pass-thru of TLS connections in scenarios like ACME's 
> tls-alpn-01.
> 
> Thank you
> Alex
> Attachments:
> * 0001-MINOR-update-proxy-protocol-v2-define.patch>From 59c8e558d1e46dc20bfffc683f8c89e06b0dbaef Mon Sep 17 00:00:00 2001
From: Alex Zorin 
Date: Sun, 30 Dec 2018 13:56:28 +1100
Subject: [PATCH] MINOR: acl: add support for TLS ALPN matching

Application-Layer Protocol Negotiation (ALPN, RFC7301) is a TLS
extension which allows a client to present the name of the protocol
it is connecting to, when a single port supports multiple application
protocols.
It allows a transparent proxy to take a decision based on the beginning
of an SSL/TLS stream without deciphering it.

The new ACL "req.ssl_alpn" matches the protocol name extracted from the
TLS ClientHello request.
---
 src/payload.c | 164 ++
 1 file changed, 164 insertions(+)

diff --git a/src/payload.c b/src/payload.c
index 7ef6d97e..ab989864 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -659,6 +659,169 @@ smp_fetch_ssl_hello_sni(const struct arg *args, struct sample *smp, const char *
 	return 0;
 }
 
+/* Try to extract the Application-Layer Protocol Negotiation (ALPN) that may
+ * be presented in a TLS client hello handshake message. The format of the
+ * message is the following (cf RFC5246 + RFC7301) :
+ * TLS frame :
+ *   - uint8  type= 0x16   (Handshake)
+ *   - uint16 version>= 0x0301 (TLSv1)
+ *   - uint16 length   (frame length)
+ *   - TLS handshake :
+ * - uint8  msg_type  = 0x01   (ClientHello)
+ * - uint24 length (handshake message length)
+ * - ClientHello :
+ *   - uint16 client_version >= 0x0301 (TLSv1)
+ *   - uint8 Random[32]  (4 first ones are timestamp)
+ *   - SessionID :
+ * - uint8 session_id_len (0..32)  (SessionID len in bytes)
+ * - uint8 session_id[session_id_len]
+ *   - CipherSuite :
+ * - uint16 cipher_len   >= 2  (Cipher length in bytes)
+ * - uint16 ciphers[cipher_len/2]
+ *   - CompressionMethod :
+ * - uint8 compression_len   >= 1  (# of supported methods)
+ * - uint8 compression_methods[compression_len]
+ *   - optional client_extension_len   (in bytes)
+ *   - optional sequence of ClientHelloExtensions  (as many bytes as above):
+ * - uint16 extension_type= 16 for application_layer_protocol_negotiation
+ * - uint16 extension_len
+ * - opaque extension_data[extension_len]
+ *   - uint16 protocol_names_len   (# of bytes here)
+ *   - opaque protocol_names[protocol_names_len bytes]
+ * - uint8 name_len
+ * - opaque protocol_name[name_len bytes]
+ */
+static int
+smp_fetch_ssl_hello_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+	int hs_len, ext_len, bleft;
+	struct channel *chn;
+	unsigned char *data;
+
+	if (!smp->strm)
+		goto not_ssl_hello;
+
+	chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
+	bleft = ci_data(chn);
+	data = (unsigned char *)ci_head(chn);
+
+	/* Check for SSL/TLS Handshake */
+	if (!bleft)
+		goto too_short;
+	if (*data != 0x16)
+		goto not_ssl_hello;
+
+	/* Check for SSLv3 or later (SSL version >= 3.0) in the record layer*/
+	if (bleft < 3)
+		goto too_short;
+	if (data[1] < 0x03)
+		goto not_ssl_hello;
+
+	if (bleft < 5)
+		goto too_short;
+	hs_len = (data[3] << 8) + data[4];
+	if (hs_len < 1 + 3 + 2 + 32 + 1 + 2 + 2 + 1 + 1 + 2 + 2)
+		goto not_ssl_hello; /* too short to have an extension */
+
+	data += 5; /* enter TLS handshake */
+	bleft -= 5;
+
+	/* Check for a complete client hello starting at  */
+	if (bleft < 1)
+		goto too_short;
+	if (data[0] != 0x01) /* msg_type = Client Hello */
+		goto not_ssl_hello;
+
+	/* Check the Hello's length */
+	if (bleft < 4)
+		goto too_short;
+	hs_len = (data[1] << 16) + (data[2] << 8) + data[3];
+	if (hs_len < 2 + 32 + 1 + 2 + 2 + 1 + 1 + 2 + 2)
+		goto not_ssl_hello; /* too short to have an extension */
+
+	/* We want the full handshake here */
+	if (bleft < hs_len)
+		goto too_short;
+
+	data += 4;
+	/* Start of the ClientHello message */
+	if (data[0] < 0x03 || data[1] < 0x01) /* TLSv1 minimum */
+		goto not_ssl_hello;
+
+	ext_len = data[34]; /* session_id_len */
+	if (ext_len > 32 || ext_len > (hs_len - 35)) /* check for correct session_id len */
+		goto not_ssl_hello;
+
+	/* Jump to cipher suite */
+	hs_len -= 35 + ext_len;
+	data   += 35

[PATCH] MINOR: acl: add support for TLS ALPN matching

2018-12-29 Thread Alex Zorin
Hello,

The attached patch adds acl support for the TLS ALPN extension (RFC7301) 
extension via  "req.ssl_alpn", in a similar vein to "req.ssl_sni".

It is useful for pass-thru of TLS connections in scenarios like ACME's 
tls-alpn-01.

Thank you
Alex>From 8008e5e8f23747741ed005f56c247bcd366cfda9 Mon Sep 17 00:00:00 2001
From: Emmanuel Hocdet 
Date: Fri, 13 Oct 2017 12:15:28 +0200
Subject: [PATCH 1/3] MINOR: update proxy-protocol-v2 #define

Report #define from doc/proxy-protocol.txt.
---
 include/types/connection.h | 15 +++
 src/connection.c   |  4 ++--
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/include/types/connection.h b/include/types/connection.h
index 1c923c578..eee75ec42 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -373,10 +373,17 @@ struct proxy_hdr_v2 {
 	} addr;
 };
 
-#define PP2_TYPE_SSL   0x20
-#define PP2_TYPE_SSL_VERSION   0x21
-#define PP2_TYPE_SSL_CN0x22
-#define PP2_TYPE_NETNS 0x30
+#define PP2_TYPE_ALPN   0x01
+#define PP2_TYPE_AUTHORITY  0x02
+#define PP2_TYPE_CRC32C 0x03
+#define PP2_TYPE_NOOP   0x04
+#define PP2_TYPE_SSL0x20
+#define PP2_SUBTYPE_SSL_VERSION 0x21
+#define PP2_SUBTYPE_SSL_CN  0x22
+#define PP2_SUBTYPE_SSL_CIPHER  0x23
+#define PP2_SUBTYPE_SSL_SIG_ALG 0x24
+#define PP2_SUBTYPE_SSL_KEY_ALG 0x25
+#define PP2_TYPE_NETNS  0x30
 
 #define TLV_HEADER_SIZE  3
 struct tlv {
diff --git a/src/connection.c b/src/connection.c
index 48f0ec331..a29bc2c32 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1037,7 +1037,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
 			tlv->client |= PP2_CLIENT_SSL;
 			value = ssl_sock_get_version(remote);
 			if (value) {
-ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len-ret-ssl_tlv_len), PP2_TYPE_SSL_VERSION, strlen(value), value);
+ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len-ret-ssl_tlv_len), PP2_SUBTYPE_SSL_VERSION, strlen(value), value);
 			}
 			if (ssl_sock_get_cert_used_sess(remote)) {
 tlv->client |= PP2_CLIENT_CERT_SESS;
@@ -1048,7 +1048,7 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
 			if (srv->pp_opts & SRV_PP_V2_SSL_CN) {
 cn_trash = get_trash_chunk();
 if (ssl_sock_get_remote_common_name(remote, cn_trash) > 0) {
-	ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_TYPE_SSL_CN, cn_trash->len, cn_trash->str);
+	ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_SUBTYPE_SSL_CN, cn_trash->len, cn_trash->str);
 }
 			}
 		}
-- 
2.11.0



Re: Question about Maglev algorithm

2018-12-29 Thread Aleksandar Lazic
Am 29.12.2018 um 19:25 schrieb Valentin Vidic:
> On Sat, Dec 29, 2018 at 06:03:51PM +0100, Aleksandar Lazic wrote:
>> I thought I have misunderstood the Idea behind maglev, thanks for 
>> clarification.
> 
> Found another mention of Maglev [Eis16] for high-level load balancing (between
> datacenters):
> 
>   https://landing.google.com/sre/sre-book/chapters/load-balancing-frontend/

Thanks.

As explained from Willy the Eis16 is for IP packages, I think.

```
.
.

Our current VIP load balancing solution [Eis16] uses packet encapsulation. A
network load balancer puts the forwarded packet into another IP packet with
Generic Routing Encapsulation (GRE) [Han94], and uses a backend’s address as the
destination. A backend receiving the packet strips off the outer IP+GRE layer
and processes the inner IP packet as if it were delivered directly to its
network interface. The network load balancer and the backend no longer need to
exist in the same broadcast domain; they can even be on separate continents as
long as a route between the two exists.
.
.

```

As in the Kubernetes environments are more and more SDNs in use I'm asking my
self if this algorithm could have some benefit. The network setup and in general
the IT have a high change rate let's keep it in mind and let us see what the
future brings or requires ;-)

QUICK is coming "quick" over the edge and this will change a lot especially for
reverse proxies like haproxy, IMHO.

Regards
Aleks



Re: Question about Maglev algorithm

2018-12-29 Thread Valentin Vidic
On Sat, Dec 29, 2018 at 06:03:51PM +0100, Aleksandar Lazic wrote:
> I thought I have misunderstood the Idea behind maglev, thanks for 
> clarification.

Found another mention of Maglev [Eis16] for high-level load balancing (between
datacenters):

  https://landing.google.com/sre/sre-book/chapters/load-balancing-frontend/

-- 
Valentin



Re: Question about Maglev algorithm

2018-12-29 Thread Aleksandar Lazic
Am 29.12.2018 um 07:41 schrieb Willy Tarreau:
> On Fri, Dec 28, 2018 at 07:55:11PM +0100, Aleksandar Lazic wrote:
>> Well as far as I understood the pdf one of the biggest difference is that
>> Maglev is a distributed system where the consistent hash is for local system.
> 
> No, not at all. The difference is that it's designed for packet processing
> so they have to take care of connection tracking and per-packet processing
> cost. From what I've read in the paper, it could be seen as a subset of
> what we already do :
>   - server weights are not supported in Maglev (and very likely not needed)
>   - slow start is not supported
>   - server insertion/removal can be extremely expensive (O(N^2)) due to the
> way they need to build the hash table for fast lookup
>   - no possibility for bounded load either
> 
> It's really important to understand the different focus of the algorithm,
> being packet-oriented instead of L7-oriented. This explains a number of
> differences and choices. I think Maglev is excellent for what it does and
> that our mechanism wouldn't be as fast if used on a per-packet basis. But
> conversely, we already do the same and even much more by default because
> we work at a different layer.

I thought I have misunderstood the Idea behind maglev, thanks for clarification.

> Willy

Cheers
Aleks