[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