[master] c8d7078 Add VMOD proxy

Emmanuel Hocdet manu at gandi.net
Wed Mar 14 16:10:09 UTC 2018


commit c8d7078fcc902445530f45120b1e6efbd4e93bae
Author: Emmanuel Hocdet <manu at gandi.net>
Date:   Thu Mar 1 18:06:31 2018 +0100

    Add VMOD proxy

diff --git a/bin/varnishtest/tests/o00005.vtc b/bin/varnishtest/tests/o00005.vtc
new file mode 100644
index 0000000..49cb0ef
--- /dev/null
+++ b/bin/varnishtest/tests/o00005.vtc
@@ -0,0 +1,41 @@
+varnishtest "PROXY v2 TLV test"
+
+server s1 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -proto "PROXY" -vcl+backend {
+	import proxy;
+
+	sub vcl_deliver {
+	    if (proxy.ssl_verify_result() == 0) {
+	       set resp.http.verify = "ok";
+	    }
+	    set resp.http.alpn = proxy.alpn();
+	    set resp.http.ssl-version = proxy.ssl_version();
+	    set resp.http.cipher = proxy.ssl_cipher();
+	    set resp.http.key = proxy.cert_key();
+	    set resp.http.sign = proxy.cert_sign();
+	}
+} -start
+
+client c1 {
+	sendhex "0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a 21 11 00 65"
+	sendhex "d9 46 b5 21 5f 8e a8 22 ed 96 01 bb 03 00 04 95"
+	sendhex "03 ee 75 01 00 02 68 32 02 00 0a 68 6f 63 64 65"
+	sendhex "74 2e 6e 65 74 20 00 3d 01 00 00 00 00 21 00 07"
+	sendhex "54 4c 53 76 31 2e 33 25 00 05 45 43 32 35 36 24"
+	sendhex "00 0a 52 53 41 2d 53 48 41 32 35 36 23 00 16 41"
+	sendhex "45 41 44 2d 41 45 53 31 32 38 2d 47 43 4d 2d 53"
+	sendhex "48 41 32 35 36"
+	txreq
+	rxresp
+	expect resp.status == 200
+	expect resp.http.verify == ok
+	expect resp.http.alpn == h2
+	expect resp.http.ssl-version == TLSv1.3
+	expect resp.http.cipher == AEAD-AES128-GCM-SHA256
+	expect resp.http.key == EC256
+	expect resp.http.sign == RSA-SHA256
+} -run
diff --git a/bin/varnishtest/vmods.h b/bin/varnishtest/vmods.h
index fb8f68f..06ab9b8 100644
--- a/bin/varnishtest/vmods.h
+++ b/bin/varnishtest/vmods.h
@@ -34,3 +34,4 @@ VTC_VMOD(purge)
 VTC_VMOD(vtc)
 VTC_VMOD(blob)
 VTC_VMOD(unix)
+VTC_VMOD(proxy)
diff --git a/configure.ac b/configure.ac
index 4323d1b..45bdb45 100644
--- a/configure.ac
+++ b/configure.ac
@@ -760,6 +760,7 @@ AC_CONFIG_FILES([
     lib/libvmod_vtc/Makefile
     lib/libvmod_blob/Makefile
     lib/libvmod_unix/Makefile
+    lib/libvmod_proxy/Makefile
     man/Makefile
     varnishapi.pc
     varnishapi-uninstalled.pc
diff --git a/doc/sphinx/Makefile.am b/doc/sphinx/Makefile.am
index 810e903..04fa9db 100644
--- a/doc/sphinx/Makefile.am
+++ b/doc/sphinx/Makefile.am
@@ -222,6 +222,10 @@ reference/vmod_unix.generated.rst: reference $(top_builddir)/lib/libvmod_unix/vm
 	cp $(top_builddir)/lib/libvmod_unix/vmod_unix.rst $@ || true
 BUILT_SOURCES += reference/vmod_unix.generated.rst
 
+reference/vmod_proxy.generated.rst: reference $(top_builddir)/lib/libvmod_proxy/vmod_proxy.rst
+	cp $(top_builddir)/lib/libvmod_proxy/vmod_proxy.rst $@ || true
+BUILT_SOURCES += reference/vmod_proxy.generated.rst
+
 EXTRA_DIST += $(BUILT_SOURCES)
 MAINTAINERCLEANFILES = $(EXTRA_DIST)
 
diff --git a/doc/sphinx/reference/index.rst b/doc/sphinx/reference/index.rst
index 9df60eb..1bf5435 100644
--- a/doc/sphinx/reference/index.rst
+++ b/doc/sphinx/reference/index.rst
@@ -26,6 +26,7 @@ The Varnish Reference Manual
 	vmod_purge.generated.rst
 	vmod_blob.generated.rst
 	vmod_unix.generated.rst
+	vmod_proxy.generated.rst
 	directors.rst
 	varnish-counters.rst
 	vsl.rst
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 411bd80..907ee4a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -11,4 +11,5 @@ SUBDIRS = \
 	libvmod_purge \
 	libvmod_vtc \
 	libvmod_blob \
-	libvmod_unix
+	libvmod_unix \
+	libvmod_proxy
diff --git a/lib/libvmod_proxy/Makefile.am b/lib/libvmod_proxy/Makefile.am
new file mode 100644
index 0000000..d8d5861
--- /dev/null
+++ b/lib/libvmod_proxy/Makefile.am
@@ -0,0 +1,7 @@
+#
+
+libvmod_proxy_la_SOURCES = \
+	vmod_proxy.c
+
+# Use vmodtool.py generated automake boilerplate
+include $(srcdir)/automake_boilerplate.am
diff --git a/lib/libvmod_proxy/automake_boilerplate.am b/lib/libvmod_proxy/automake_boilerplate.am
new file mode 100644
index 0000000..64f3c5a
--- /dev/null
+++ b/lib/libvmod_proxy/automake_boilerplate.am
@@ -0,0 +1,39 @@
+
+# Boilerplate generated by vmodtool.py - changes will be overwritten
+
+AM_LDFLAGS  = $(AM_LT_LDFLAGS)
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/bin/varnishd \
+	-I$(top_builddir)/include
+
+vmoddir = $(pkglibdir)/vmods
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
+vmodtoolargs = --strict --boilerplate
+
+vmod_LTLIBRARIES = libvmod_proxy.la
+
+libvmod_proxy_la_CFLAGS = \
+	@SAN_CFLAGS@
+
+libvmod_proxy_la_LDFLAGS = \
+	$(AM_LDFLAGS) \
+	$(VMOD_LDFLAGS) \
+	@SAN_LDFLAGS@
+
+nodist_libvmod_proxy_la_SOURCES = vcc_if.c vcc_if.h
+
+$(libvmod_proxy_la_OBJECTS): vcc_if.h
+
+vcc_if.h vmod_proxy.rst vmod_proxy.man.rst: vcc_if.c
+
+vcc_if.c: $(vmodtool) $(srcdir)/vmod.vcc
+	@PYTHON@ $(vmodtool) $(vmodtoolargs) $(srcdir)/vmod.vcc
+
+EXTRA_DIST = vmod.vcc automake_boilerplate.am
+
+CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \
+	$(builddir)/vmod_proxy.rst \
+	$(builddir)/vmod_proxy.man.rst
+
diff --git a/lib/libvmod_proxy/vmod.vcc b/lib/libvmod_proxy/vmod.vcc
new file mode 100644
index 0000000..c3774db
--- /dev/null
+++ b/lib/libvmod_proxy/vmod.vcc
@@ -0,0 +1,125 @@
+#-
+# Copyright (c) 2018 GANDI SAS
+# All rights reserved.
+#
+# Author: Emmanuel Hocdet <manu at gandi.net>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+$Module proxy 3 Varnish Standard Module
+$ABI strict
+
+DESCRIPTION
+===========
+
+`vmod_proxy` contains functions to extract proxy-protocol-v2 TLV attributes
+as described in https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt.
+
+
+$Function STRING alpn()
+
+Description
+	Extract alpn attribute.
+Example
+	set req.http.alpn = proxy.alpn();
+
+$Function STRING authority()
+
+Description
+	Extract authority attribute. This corresponds to sni from a tls
+	connection.
+Example
+	set req.http.authority = proxy.authority();
+
+$Function BOOL is_ssl()
+
+Description
+	Report if proxy-protocol-v2 has ssl tlv.
+
+Example
+	| if (proxy.is_ssl()) {
+	|     set req.http.ssl-version = proxy.ssl_version();
+	| }
+
+$Function BOOL client_has_cert_sess()
+
+Description
+	Report if the client provided a certificate at least once over the TLS
+	session this connection belongs to.
+
+$Function BOOL client_has_cert_conn()
+
+Description
+	Report if the client provided a certificate over the current connection.
+
+$Function INT ssl_verify_result()
+
+Description
+	Report the SSL_get_verify_result from a TLS session. It only matters
+	if client_has_cert_sess() is true. Per default, value is set to 0
+	(X509_V_OK).
+
+Example
+	| if (proxy.client_has_cert_sess() && proxy.ssl_verify_result() == 0) {
+	|     set req.http.ssl-verify = "ok";
+	| }
+
+$Function STRING ssl_version()
+
+Description
+	Extract ssl version attribute.
+Example
+	set req.http.ssl-version = proxy.ssl_version();
+
+$Function STRING client_cert_cn()
+
+Description
+	Extract the common name attribute of the client certificate's.
+Example
+	set req.http.cert-cn = proxy.client_cert_cn();
+
+$Function STRING ssl_cipher()
+
+Description
+	Extract the ssl cipher attribute.
+Example
+	set req.http.ssl-cipher = proxy.ssl_cipher();
+
+$Function STRING cert_sign()
+
+Description
+	Extract the certificate signature algorithm attribute.
+Example
+	set req.http.cert-sign = proxy.cert_sign();
+
+$Function STRING cert_key()
+
+Description
+	Extract the certificate key algorithm attribute.
+Example
+	set req.http.cert-key = proxy.cert_key();
+
+SEE ALSO
+========
+
+* :ref:`varnishd(1)`
+* :ref:`vsl(7)`
diff --git a/lib/libvmod_proxy/vmod_proxy.c b/lib/libvmod_proxy/vmod_proxy.c
new file mode 100644
index 0000000..8c6973c
--- /dev/null
+++ b/lib/libvmod_proxy/vmod_proxy.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2018 GANDI SAS
+ * All rights reserved.
+ *
+ * Author: Emmanuel Hocdet <manu at gandi.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cache/cache.h"
+
+#include "vend.h"
+#include "vcl.h"
+
+#include "proxy/cache_proxy.h"
+
+#include "vcc_if.h"
+
+
+struct pp2_tlv_ssl {
+	uint8_t  client;
+	uint32_t verify;
+}__attribute__((packed));
+
+#define PP2_CLIENT_SSL           0x01
+#define PP2_CLIENT_CERT_CONN     0x02
+#define PP2_CLIENT_CERT_SESS     0x04
+
+static VCL_BOOL
+tlv_ssl_flag(VRT_CTX, int flag)
+{
+	struct pp2_tlv_ssl *dst;
+	int len;
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	if (VPX_tlv(ctx->req, PP2_TYPE_SSL, (void **)&dst, &len))
+		return (0);
+
+	return ((dst->client & flag) == flag);
+}
+
+VCL_BOOL v_matchproto_(td_proxy_is_ssl)
+vmod_is_ssl(VRT_CTX)
+{
+	return tlv_ssl_flag(ctx, PP2_CLIENT_SSL);
+}
+
+VCL_BOOL v_matchproto_(td_proxy_client_has_cert_sess)
+vmod_client_has_cert_sess(VRT_CTX)
+{
+	return tlv_ssl_flag(ctx, PP2_CLIENT_CERT_SESS);
+}
+
+VCL_BOOL v_matchproto_(td_proxy_client_has_cert_conn)
+vmod_client_has_cert_conn(VRT_CTX)
+{
+	return tlv_ssl_flag(ctx, PP2_CLIENT_CERT_CONN);
+}
+
+/* return come from SSL_get_verify_result */
+VCL_INT v_matchproto_(td_proxy_ssl_verify_result)
+vmod_ssl_verify_result(VRT_CTX)
+{
+	struct pp2_tlv_ssl *dst;
+	int len;
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	if (VPX_tlv(ctx->req, PP2_TYPE_SSL, (void **)&dst, &len))
+		return (0); /* X509_V_OK */
+
+	return (vbe32dec(&dst->verify));
+}
+
+static VCL_STRING
+tlv_string(VRT_CTX, int tlv)
+{
+	char *dst, *d;
+	int len;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	if (VPX_tlv(ctx->req, tlv, (void **)&dst, &len))
+		return (NULL);
+	if (!WS_Reserve(ctx->ws, len+1))
+		return (NULL);
+	d = ctx->ws->f;
+	memcpy(d, dst, len);
+	d[len] = '\0';
+	WS_Release(ctx->ws, len+1);
+	return (d);
+}
+
+VCL_STRING v_matchproto_(td_proxy_alpn)
+vmod_alpn(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_TYPE_ALPN);
+}
+
+VCL_STRING v_matchproto_(td_proxy_authority)
+vmod_authority(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_TYPE_AUTHORITY);
+}
+
+VCL_STRING v_matchproto_(td_proxy_ssl_version)
+vmod_ssl_version(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_SUBTYPE_SSL_VERSION);
+}
+
+VCL_STRING v_matchproto_(td_proxy_ssl_cipher)
+vmod_ssl_cipher(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_SUBTYPE_SSL_CIPHER);
+}
+
+VCL_STRING v_matchproto_(td_proxy_cert_sign)
+vmod_cert_sign(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_SUBTYPE_SSL_SIG_ALG);
+}
+
+VCL_STRING v_matchproto_(td_proxy_cert_key)
+vmod_cert_key(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_SUBTYPE_SSL_KEY_ALG);
+}
+
+VCL_STRING v_matchproto_(td_proxy_client_cert_cn)
+vmod_client_cert_cn(VRT_CTX)
+{
+	return tlv_string(ctx, PP2_SUBTYPE_SSL_CN);
+}
diff --git a/man/Makefile.am b/man/Makefile.am
index e7c00df..0e35dc5 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -20,7 +20,8 @@ dist_man_MANS = \
 	vmod_std.3 \
 	vmod_vtc.3 \
 	vmod_blob.3 \
-	vmod_unix.3
+	vmod_unix.3 \
+	vmod_proxy.3
 
 CLEANFILES = $(dist_man_MANS)
 
@@ -105,4 +106,7 @@ vmod_blob.3: $(top_builddir)/lib/libvmod_blob/vmod_blob.man.rst
 vmod_unix.3: $(top_builddir)/lib/libvmod_unix/vmod_unix.man.rst
 	${RST2MAN} $(RST2ANY_FLAGS) $? $@
 
+vmod_proxy.3: $(top_builddir)/lib/libvmod_proxy/vmod_proxy.man.rst
+	${RST2MAN} $(RST2ANY_FLAGS) $? $@
+
 .NOPATH: $(dist_man_MANS)


More information about the varnish-commit mailing list