aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-06-10 01:39:15 +0000
committerLaurent Bercot <ska@appnovation.com>2025-06-10 01:39:15 +0000
commit5db792ba17ce1c372ece1a9d4b152290d4f1b867 (patch)
tree7a2e186b483cc82ca509ff5033d90ce2015352a1
parent992508c00caddc5576968bad88b6e6f01344e472 (diff)
downloads6-networking-5db792ba17ce1c372ece1a9d4b152290d4f1b867.tar.gz
proxy-server: support in s6-tlsserver
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--doc/s6-tlsserver.html14
-rw-r--r--src/conn-tools/proxy-server.c75
-rw-r--r--src/tls/s6-tlsserver.c22
3 files changed, 85 insertions, 26 deletions
diff --git a/doc/s6-tlsserver.html b/doc/s6-tlsserver.html
index 6f199e7..27bcc66 100644
--- a/doc/s6-tlsserver.html
+++ b/doc/s6-tlsserver.html
@@ -139,13 +139,25 @@ variables will not appear in <em>prog</em>'s environment.
<h2> Options </h2>
<p>
- <tt>s6-tlsserver</tt> accepts a myriad of options, all of which are
+ <tt>s6-tlsserver</tt> accepts a myriad of options, most of which are
passed as is to the correct executable. Not giving any options will
generally work, but unless you're running a very public server
(such as a Web server) or base your access control on client
certificates, you probably still want TCP access rules.
</p>
+<h3> Options informing s6-tlsserver behaviour </h3>
+
+<ul>
+ <li> <tt>-L</tt>&nbsp;: if this option is given, s6-tlsserver will
+add an invocation of <a href="proxy-server.html">proxy-server</a> so that
+a PROXY line or binary block is read <em>in cleartext</em> before the
+TLS tunnel is established. If the proxy uses the v2 version of the PROXY
+protocol and transmits SSL information from the client connection, this
+information will be reflected in the SSL environment variables transmitted
+to <em>prog</em>. </li>
+</ul>
+
<h3> Options passed as is to s6-tcpserver </h3>
<ul>
diff --git a/src/conn-tools/proxy-server.c b/src/conn-tools/proxy-server.c
index 0d15cea..129955b 100644
--- a/src/conn-tools/proxy-server.c
+++ b/src/conn-tools/proxy-server.c
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <string.h>
#include <unistd.h>
+#include <stdlib.h>
#include <errno.h>
#include <skalibs/gccattributes.h>
@@ -23,8 +24,25 @@
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+enum main_golb_e
+{
+ MAIN_GOLB_V1,
+ MAIN_GOLB_V2,
+ MAIN_GOLB_BEFORE,
+ MAIN_GOLB_AFTER,
+ MAIN_GOLB_N
+} ;
+
+enum main_gola_e
+{
+ MAIN_GOLA_TIMEOUT,
+ MAIN_GOLA_VERBOSITY,
+ MAIN_GOLA_N
+} ;
+
static unsigned int verbosity = 1 ;
static tain deadline ;
+static uint64_t golb = 1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2 ;
/* v2 */
@@ -79,7 +97,7 @@ static void process_v2_extensions (char const *s, uint16_t len, int sub)
char tmp[n+1] ;
if (sub) strerr_dief1x(1, "invalid sub-extension type") ;
memcpy(tmp, s, n) ; tmp[n] = 0 ;
- if (!env_mexec("SSL_TLS_SNI_SERVERNAME", tmp)) dienomem() ;
+ if (!env_mexec(golb & 1 << MAIN_GOLB_BEFORE ? "tlsbak_SSL_TLS_SNI_SERVERNAME" : "SSL_TLS_SNI_SERVERNAME", tmp)) dienomem() ;
break ;
}
case 0x20 : /* PP2_TYPE_SSL */
@@ -92,7 +110,7 @@ static void process_v2_extensions (char const *s, uint16_t len, int sub)
char tmp[n+1] ;
if (!sub) strerr_dief1x(1, "invalid main extension type") ;
memcpy(tmp, s, n) ; tmp[n] = 0 ;
- if (!env_mexec("SSL_PROTOCOL", tmp)) dienomem() ;
+ if (!env_mexec(golb & 1 << MAIN_GOLB_BEFORE ? "tlsbak_SSL_PROTOCOL" : "SSL_PROTOCOL", tmp)) dienomem() ;
break ;
}
case 0x22 : /* PP2_SUBTYPE_SSL_CN */
@@ -100,7 +118,7 @@ static void process_v2_extensions (char const *s, uint16_t len, int sub)
char tmp[n+1] ;
if (!sub) strerr_dief1x(1, "invalid main extension type") ;
memcpy(tmp, s, n) ; tmp[n] = 0 ;
- if (!env_mexec("SSL_PEER_CERT_CN", tmp)) dienomem() ;
+ if (!env_mexec(golb & 1 << MAIN_GOLB_BEFORE ? "tlsbak_SSL_PEER_CERT_CN" : "SSL_PEER_CERT_CN", tmp)) dienomem() ;
break ;
}
case 0x23 : /* PP2_SUBTYPE_SSL_CIPHER */
@@ -108,7 +126,7 @@ static void process_v2_extensions (char const *s, uint16_t len, int sub)
char tmp[n+1] ;
if (!sub) strerr_dief1x(1, "invalid main extension type") ;
memcpy(tmp, s, n) ; tmp[n] = 0 ;
- if (!env_mexec("SSL_CIPHER", tmp)) dienomem() ;
+ if (!env_mexec(golb & 1 << MAIN_GOLB_BEFORE ? "tlsbak_SSL_CIPHER" : "SSL_CIPHER", tmp)) dienomem() ;
break ;
}
default : break ;
@@ -299,19 +317,28 @@ static void both (void)
else maybe_v2(buf) ;
}
-enum main_golb_e
+static void after (void)
{
- MAIN_GOLB_V1,
- MAIN_GOLB_V2,
- MAIN_GOLB_N
-} ;
-
-enum main_gola_e
-{
- MAIN_GOLA_TIMEOUT,
- MAIN_GOLA_VERBOSITY,
- MAIN_GOLA_N
-} ;
+ static char const *const vars[] =
+ {
+ "SSL_TLS_SNI_SERVERNAME",
+ "SSL_PROTOCOL",
+ "SSL_PEER_CERT_CN",
+ "SSL_CIPHER",
+ 0
+ } ;
+ for (char const *const *var = vars ; *var ; var++)
+ {
+ size_t len = strlen(*var) ;
+ char const *x ;
+ char bakvar[8 + len] ;
+ memcpy(bakvar, "tlsbak_", 7) ;
+ memcpy(bakvar + 7, *var, len+1) ;
+ x = getenv(bakvar) ;
+ if (!x) strerr_dief1x(100, "--after-tlsd can only be used after an invocation with --before-tlsd") ;
+ if (!env_mexec(bakvar, 0) || !env_mexec(*var, x)) dienomem() ;
+ }
+}
int main (int argc, char const *const *argv)
{
@@ -319,6 +346,8 @@ int main (int argc, char const *const *argv)
{
{ .so = '1', .lo = "disable-v2", .set = 0, .mask = 1 << MAIN_GOLB_V2 },
{ .so = '2', .lo = "disable-v1", .set = 0, .mask = 1 << MAIN_GOLB_V1 },
+ { .so = 0, .lo = "before-tlsd", .set = 1, .mask = 1 << MAIN_GOLB_BEFORE },
+ { .so = 0, .lo = "after-tlsd", .set = 1, .mask = 1 << MAIN_GOLB_AFTER },
} ;
static gol_arg const main_gola[MAIN_GOLA_N] =
{
@@ -326,7 +355,6 @@ int main (int argc, char const *const *argv)
{ .so = 'v', .lo = "verbosity", .i = MAIN_GOLA_VERBOSITY }
} ;
- uint64_t golb = 1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2 ;
PROG = NAME ;
{
@@ -350,10 +378,13 @@ int main (int argc, char const *const *argv)
PROG_pid_fill(prog_storage, NAME) ;
PROG = prog_storage ;
- uint64_t ver = golb & (1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2) ;
- if (ver == (1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2)) both() ;
- else if (ver == 1 << MAIN_GOLB_V2) v2() ;
- else if (ver == 1 << MAIN_GOLB_V1) v1() ;
- else if (verbosity) strerr_warnw1x("both versions disabled, no proxy protocol expected") ;
+ if (golb & 1 << MAIN_GOLB_AFTER) after() ;
+ else switch (golb & (1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2))
+ {
+ case 1 << MAIN_GOLB_V1 | 1 << MAIN_GOLB_V2 : both() ; break ;
+ case 1 << MAIN_GOLB_V2 : v2() ; break ;
+ case 1 << MAIN_GOLB_V1 : v1() ; break ;
+ default : if (verbosity) strerr_warnw1x("both versions disabled, no proxy protocol expected") ;
+ }
xmexec(argv) ;
}
diff --git a/src/tls/s6-tlsserver.c b/src/tls/s6-tlsserver.c
index 5f9c7dd..ee9516c 100644
--- a/src/tls/s6-tlsserver.c
+++ b/src/tls/s6-tlsserver.c
@@ -13,6 +13,7 @@
#include <s6-networking/config.h>
#define USAGE "s6-tlsserver [ options ] ip port prog...\n" \
+"proxy-server options: [ -L ]" \
"s6-tcpserver options: [ -q | -Q | -v ] [ -1 ] [ -c maxconn ] [ -C localmaxconn ] [ -b backlog ] [ -G gidlist ] [ -g gid ] [ -u uid ] [ -U ]\n" \
"s6-tcpserver-access options: [ -W | -w ] [ -D | -d ] [ -H ] [ -h ] [ -R | -r ] [ -P | -p ] [ -l localname ] [ -B banner ] [ -t timeout ] [ -i rulesdir | -x rulesfile ]\n" \
"s6-tlsd options: [ -S | -s ] [ -J | -j ] [ -Y | -y ] [ -K timeout ] [ -Z | -z ] [ -k snilevel ]"
@@ -36,6 +37,7 @@ struct options_s
unsigned int kimeout ;
unsigned int snilevel ;
unsigned int verbosity : 2 ;
+ unsigned int flagL : 1 ;
unsigned int flag1 : 1 ;
unsigned int flagU : 1 ;
unsigned int flagw : 1 ;
@@ -66,8 +68,9 @@ struct options_s
.localmaxconn = 0, \
.timeout = 0, \
.kimeout = 0, \
- .verbosity = 1, \
.snilevel = 0, \
+ .verbosity = 1, \
+ .flagL = 0, \
.flag1 = 0, \
.flagU = 0, \
.flagw = 0, \
@@ -93,7 +96,7 @@ int main (int argc, char const *const *argv)
subgetopt l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "qQv1c:C:b:G:g:u:UWwDdHhRrPpl:B:t:i:x:SsJjYyK:Zzk:", &l) ;
+ int opt = subgetopt_r(argc, argv, "qQv1c:C:b:G:g:u:LUWwDdHhRrPpl:B:t:i:x:SsJjYyK:Zzk:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -101,6 +104,7 @@ int main (int argc, char const *const *argv)
case 'Q' : o.verbosity = 1 ; break ;
case 'v' : o.verbosity = 2 ; break ;
case '1' : o.flag1 = 1 ; break ;
+ case 'L' : o.flagL = 1 ; break ;
case 'c' : if (!uint0_scan(l.arg, &o.maxconn)) dieusage() ; if (!o.maxconn) o.maxconn = 1 ; break ;
case 'C' : if (!uint0_scan(l.arg, &o.localmaxconn)) dieusage() ; if (!o.localmaxconn) o.localmaxconn = 1 ; break ;
case 'b' : if (!uint0_scan(l.arg, &o.backlog)) dieusage() ; break ;
@@ -144,7 +148,7 @@ int main (int argc, char const *const *argv)
size_t pos = 0 ;
unsigned int m = 0 ;
char fmt[UINT_FMT * 6 + UID_FMT + GID_FMT * (NGROUPS_MAX + 1)] ;
- char const *newargv[51 + argc] ;
+ char const *newargv[57 + argc] ;
int doaccess = o.flagw || o.flagD || !o.flagH || o.flagr || o.flagp || o.localname || o.banner || o.timeout || o.rules ;
newargv[m++] = S6_NETWORKING_BINPREFIX "s6-tcpserver" ;
if (o.verbosity != 1)
@@ -216,6 +220,12 @@ int main (int argc, char const *const *argv)
}
newargv[m++] = "--" ;
}
+ if (o.flagL)
+ {
+ newargv[m++] = S6_NETWORKING_BINPREFIX "proxy-server" ;
+ newargv[m++] = "--before-tlsd" ;
+ newargv[m++] = "--" ;
+ }
newargv[m++] = S6_NETWORKING_BINPREFIX "s6-tlsd" ;
if (o.verbosity != 1)
{
@@ -264,6 +274,12 @@ int main (int argc, char const *const *argv)
if (o.flagU) newargv[m++] = "-Uz" ;
newargv[m++] = "--" ;
}
+ if (o.flagL)
+ {
+ newargv[m++] = S6_NETWORKING_BINPREFIX "proxy-server" ;
+ newargv[m++] = "--after-tlsd" ;
+ newargv[m++] = "--" ;
+ }
while (*argv) newargv[m++] = *argv++ ;
newargv[m++] = 0 ;
xexec(newargv) ;