[master] 99ec7796d Add capability to send the authority TLV in the PROXY header

Nils Goroll nils.goroll at uplex.de
Wed Jan 15 16:12:08 UTC 2020


commit 99ec7796d8f475db038a44054c72b34d1ef889f9
Author: Geoff Simmons <geoff at uplex.de>
Date:   Wed Aug 21 14:33:45 2019 +0200

    Add capability to send the authority TLV in the PROXY header
    
    This gives the receiver of the PROXY header (usually the ssl-onloader)
    the opportunity to set the SNI (HostName field) from the TLV value, for
    the TLS handshake with the remote backend.
    
    From
    https://github.com/nigoroll/varnish-cache/commit/e0eb7d0a9c65cdc3c58978656b4c71f4ab8aabca
    edited by @nigoroll to split out the proxy header functionality.
    
    Add vmod_debug access to the proxy header formatting and test it

diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index d1ad0f6d6..d6d32ca0a 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -989,7 +989,8 @@ VRT_VSA_GetPtr(VRT_CTX, const struct suckaddr *sua, const unsigned char ** dst)
 }
 
 void
-VRT_Format_Proxy(struct vsb *vsb, VCL_INT version, VCL_IP sac, VCL_IP sas)
+VRT_Format_Proxy(struct vsb *vsb, VCL_INT version, VCL_IP sac, VCL_IP sas,
+    VCL_STRING auth)
 {
-	VPX_Format_Proxy(vsb, (int)version, sac, sas);
+	VPX_Format_Proxy(vsb, (int)version, sac, sas, auth);
 }
diff --git a/bin/varnishd/proxy/cache_proxy.h b/bin/varnishd/proxy/cache_proxy.h
index c8d07ddb5..97c11deaf 100644
--- a/bin/varnishd/proxy/cache_proxy.h
+++ b/bin/varnishd/proxy/cache_proxy.h
@@ -40,4 +40,4 @@
 
 int VPX_tlv(const struct req *req, int tlv, void **dst, int *len);
 void VPX_Format_Proxy(struct vsb *, int, const struct suckaddr *,
-    const struct suckaddr *);
+    const struct suckaddr *, const char *);
diff --git a/bin/varnishd/proxy/cache_proxy_proto.c b/bin/varnishd/proxy/cache_proxy_proto.c
index 2ee6f82d2..4a9d0e681 100644
--- a/bin/varnishd/proxy/cache_proxy_proto.c
+++ b/bin/varnishd/proxy/cache_proxy_proto.c
@@ -606,6 +606,24 @@ vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
 	VSB_bcat(vsb, b, sizeof(b));
 }
 
+static void
+vpx_enc_authority(struct vsb *vsb, const char *authority, size_t l_authority)
+{
+	uint16_t l;
+
+	AN(vsb);
+
+	if (l_authority == 0)
+		return;
+	AN(authority);
+	AN(*authority);
+
+	VSB_putc(vsb, PP2_TYPE_AUTHORITY);
+	vbe16enc(&l, l_authority);
+	VSB_bcat(vsb, &l, sizeof(l));
+	VSB_cat(vsb, authority);
+}
+
 /* short path for stringified addresses from session attributes */
 static void
 vpx_format_proxy_v1(struct vsb *vsb, int proto,
@@ -634,22 +652,33 @@ vpx_format_proxy_v1(struct vsb *vsb, int proto,
 
 static void
 vpx_format_proxy_v2(struct vsb *vsb, int proto,
-    const struct suckaddr *sac, const struct suckaddr *sas)
+    const struct suckaddr *sac, const struct suckaddr *sas,
+    const char *authority)
 {
+	size_t l_authority = 0;
+	uint16_t l_tlv = 0, l;
+
 	AN(vsb);
 	AN(sac);
 	AN(sas);
 
+	if (authority != NULL && *authority != '\0') {
+		l_authority = strlen(authority);
+		/* 3 bytes in the TLV before the authority string */
+		assert(3 + l_authority <= UINT16_MAX);
+		l_tlv = 3 + l_authority;
+	}
+
 	VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
 	VSB_putc(vsb, 0x21);
 	if (proto == PF_INET6) {
 		VSB_putc(vsb, 0x21);
-		VSB_putc(vsb, 0x00);
-		VSB_putc(vsb, 0x24);
+		vbe16enc(&l, 0x24 + l_tlv);
+		VSB_bcat(vsb, &l, sizeof(l));
 	} else if (proto == PF_INET) {
 		VSB_putc(vsb, 0x11);
-		VSB_putc(vsb, 0x00);
-		VSB_putc(vsb, 0x0c);
+		vbe16enc(&l, 0x0c + l_tlv);
+		VSB_bcat(vsb, &l, sizeof(l));
 	} else {
 		WRONG("Wrong proxy v2 proto");
 	}
@@ -657,12 +686,14 @@ vpx_format_proxy_v2(struct vsb *vsb, int proto,
 	vpx_enc_addr(vsb, proto, sas);
 	vpx_enc_port(vsb, sac);
 	vpx_enc_port(vsb, sas);
+	vpx_enc_authority(vsb, authority, l_authority);
 	AZ(VSB_finish(vsb));
 }
 
 void
 VPX_Format_Proxy(struct vsb *vsb, int version,
-    const struct suckaddr *sac, const struct suckaddr *sas)
+    const struct suckaddr *sac, const struct suckaddr *sas,
+    const char *authority)
 {
 	int proto;
 	char hac[VTCP_ADDRBUFSIZE];
@@ -684,7 +715,7 @@ VPX_Format_Proxy(struct vsb *vsb, int version,
 		VTCP_name(sas, has, sizeof has, pas, sizeof pas);
 		vpx_format_proxy_v1(vsb, proto, hac, pac, has, pas);
 	} else if (version == 2) {
-		vpx_format_proxy_v2(vsb, proto, sac, sas);
+		vpx_format_proxy_v2(vsb, proto, sac, sas, authority);
 	} else
 		WRONG("Wrong proxy version");
 }
@@ -721,7 +752,7 @@ VPX_Send_Proxy(int fd, int version, const struct sess *sp)
 	} else if (version == 2) {
 		AZ(SES_Get_client_addr(sp, &sac));
 		AN(sac);
-		vpx_format_proxy_v2(vsb, proto, sac, sas);
+		vpx_format_proxy_v2(vsb, proto, sac, sas, NULL);
 	} else
 		WRONG("Wrong proxy version");
 
diff --git a/bin/varnishtest/tests/o00003.vtc b/bin/varnishtest/tests/o00003.vtc
index c883131d4..34d96e0bb 100644
--- a/bin/varnishtest/tests/o00003.vtc
+++ b/bin/varnishtest/tests/o00003.vtc
@@ -1,4 +1,4 @@
-varnishtest "VCL backend side access to IP#s"
+varnishtest "VCL backend side access to IP#s and debug.proxy_header"
 
 server s1 {
 	rxreq
@@ -6,11 +6,20 @@ server s1 {
 } -start
 
 varnish v1 -proto PROXY -vcl+backend {
+	import vtc;
+	import blob;
+
 	sub vcl_backend_response {
 		set beresp.http.li = local.ip;
 		set beresp.http.ri = remote.ip;
 		set beresp.http.ci = client.ip;
 		set beresp.http.si = server.ip;
+
+		set beresp.http.proxy1 = blob.encode(blob=blob.sub(
+		    vtc.proxy_header(v1, client.ip, server.ip), 36B));
+		set beresp.http.proxy2 = blob.encode(encoding=HEX,
+		    blob=vtc.proxy_header(v2, client.ip, server.ip,
+			"vtc.varnish-cache.org"));
 	}
 } -start
 
@@ -20,4 +29,6 @@ client c1 -proxy1 "1.2.3.4:1111 5.6.7.8:5678" {
 	expect resp.http.li == ${v1_addr}
 	expect resp.http.ci == 1.2.3.4
 	expect resp.http.si == 5.6.7.8
+	expect resp.http.proxy1 == "PROXY TCP4 1.2.3.4 5.6.7.8 1111 5678"
+	expect resp.http.proxy2 == "0d0a0d0a000d0a515549540a2111002401020304050607080457162e0200157674632e7661726e6973682d63616368652e6f7267"
 } -run
diff --git a/include/vrt.h b/include/vrt.h
index b8ee0fc61..168a4251e 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -57,6 +57,7 @@
  *	VRT_HashStrands32() added
  *	VRT_l_resp_body() changed
  *	VRT_l_beresp_body() changed
+ *	VRT_Format_Proxy() added	// transitional interface
  * 10.0 (2019-09-15)
  *	VRT_UpperLowerStrands added.
  *	VRT_synth_page now takes STRANDS argument
@@ -76,7 +77,6 @@
  *	VRT_Stv_*() functions renamed to VRT_stevedore_*()
  *	[cache.h] WS_ReserveAll() added
  *	[cache.h] WS_Reserve(ws, 0) deprecated
- *	VRT_Fortmat_Proxy() added
  * 9.0 (2019-03-15)
  *	Make 'len' in vmod_priv 'long'
  *	HTTP_Copy() removed
@@ -550,7 +550,8 @@ void VRT_DelDirector(VCL_BACKEND *);
 
 /* Suckaddr related */
 int VRT_VSA_GetPtr(VRT_CTX, VCL_IP sua, const unsigned char ** dst);
-void VRT_Format_Proxy(struct vsb *, VCL_INT, VCL_IP, VCL_IP);
+/* transitional interface */
+void VRT_Format_Proxy(struct vsb *, VCL_INT, VCL_IP, VCL_IP, VCL_STRING);
 
 typedef int vmod_event_f(VRT_CTX, struct vmod_priv *, enum vcl_event_e);
 
diff --git a/lib/libvmod_vtc/vmod.vcc b/lib/libvmod_vtc/vmod.vcc
index d111f9eb6..22d3dded1 100644
--- a/lib/libvmod_vtc/vmod.vcc
+++ b/lib/libvmod_vtc/vmod.vcc
@@ -155,6 +155,18 @@ Returns the size in bytes of a collection of C-datatypes:
 
 This can be useful for VMOD authors in conjunction with workspace operations.
 
+$Function BLOB proxy_header(ENUM {v1,v2} version,
+    IP client, IP server, STRING authority=0)
+
+Format a proxy header of the given version ``v1`` or ``v2`` and
+addresses (The VCL IP type also conatins the port number).
+
+Optionally also send an authority TLV with version ``v2`` (ignored for
+version ``v1``).
+
+Candidate for moving into vmod_proxy, but there were concerns about
+the interface design
+
 SEE ALSO
 ========
 
diff --git a/lib/libvmod_vtc/vmod_vtc.c b/lib/libvmod_vtc/vmod_vtc.c
index fac65a75c..cb3e3a19e 100644
--- a/lib/libvmod_vtc/vmod_vtc.c
+++ b/lib/libvmod_vtc/vmod_vtc.c
@@ -35,6 +35,7 @@
 
 #include "cache/cache.h"
 
+#include "vsb.h"
 #include "vtcp.h"
 #include "vtim.h"
 
@@ -331,3 +332,41 @@ vmod_typesize(VRT_CTX, VCL_STRING s)
 		i += (p - a); /* pad */
 	return ((VCL_INT)i);
 }
+
+/*--------------------------------------------------------------------*/
+
+#define BLOB_VMOD_PROXY_HEADER_TYPE	0xc8f34f78
+
+VCL_BLOB v_matchproto_(td_vtc_proxy_header)
+vmod_proxy_header(VRT_CTX, VCL_ENUM venum, VCL_IP client, VCL_IP server,
+    VCL_STRING authority)
+{
+	struct vsb *vsb;
+	const void *h;
+	int version;
+	size_t l;
+
+	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
+
+	if (venum == VENUM(v1))
+		version = 1;
+	else if (venum == VENUM(v2))
+		version = 2;
+	else
+		WRONG(venum);
+
+	vsb = VSB_new_auto();
+	AN(vsb);
+	VRT_Format_Proxy(vsb, version, client, server, authority);
+	l = VSB_len(vsb);
+	h = WS_Copy(ctx->ws, VSB_data(vsb), l);
+	VSB_delete(vsb);
+
+	if (h == NULL) {
+		VRT_fail(ctx, "proxy_header: out of workspace");
+		return (NULL);
+	}
+
+	return (VRT_blob(ctx, "proxy_header", h, l,
+	    BLOB_VMOD_PROXY_HEADER_TYPE));
+}


More information about the varnish-commit mailing list