From adb27aa4a391410d278a5590fcce644f32e33e8c Mon Sep 17 00:00:00 2001 From: yrutschle Date: Sun, 21 Feb 2021 21:03:01 +0100 Subject: [PATCH] add a per-protocol transparent proxy option --- ChangeLog | 2 ++ common.c | 5 +++-- example.cfg | 3 +++ sslh-conf.c | 41 ++++++++++++++++++++++++++++++----------- sslh-conf.h | 3 ++- sslh-main.c | 6 ++++-- sslhconf.cfg | 2 ++ test.cfg | 2 +- 8 files changed, 47 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 59d1e21..58293f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,8 @@ vNEXT: Warn about unknown settings in the configuration file. + Added per-protocol `transparent` option. + v1.21: 11JUL2020 WARNING: Moved configuration and command-line management to diff --git a/common.c b/common.c index 5b90dc9..a4593cb 100644 --- a/common.c +++ b/common.c @@ -295,6 +295,7 @@ int connect_addr(struct connection *cnx, int fd_from) struct sockaddr_storage ss; char buf[NI_MAXHOST]; int fd, res, one; + int transparent = cnx->proto->transparent || cfg.transparent; memset(&from, 0, sizeof(from)); from.ai_addr = (struct sockaddr*)&ss; @@ -305,7 +306,7 @@ int connect_addr(struct connection *cnx, int fd_from) for (a = cnx->proto->saddr; a; a = a->ai_next) { /* When transparent, make sure both connections use the same address family */ - if (cfg.transparent && a->ai_family != from.ai_addr->sa_family) + if (transparent && a->ai_family != from.ai_addr->sa_family) continue; if (cfg.verbose) fprintf(stderr, "connecting to %s family %d len %d\n", @@ -322,7 +323,7 @@ int connect_addr(struct connection *cnx, int fd_from) setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &one, sizeof(one)); /* no need to check return value; if it's not supported, that's okay */ - if (cfg.transparent) { + if (transparent) { res = bind_peer(fd, fd_from); CHECK_RES_RETURN(res, "bind_peer", res); } diff --git a/example.cfg b/example.cfg index c494d9b..c25b095 100644 --- a/example.cfg +++ b/example.cfg @@ -44,6 +44,9 @@ listen: # fork: Should a new process be forked for this protocol? # (only useful for sslh-select) # tfo_ok: Set to true if the server supports TCP FAST OPEN +# transparent: Set to true to proxy this protocol +# transparently (server sees the remote client IP +# address). Same as the global option, but per-protocol # # Probe-specific options: # (sslh will try each probe in order they are declared, and diff --git a/sslh-conf.c b/sslh-conf.c index 55a7e2d..db0c338 100644 --- a/sslh-conf.c +++ b/sslh-conf.c @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sat Nov 7 18:59:37 2020. + * on Sun Feb 21 20:56:51 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle @@ -422,7 +422,7 @@ struct arg_file* sslhcfg_conffile; struct arg_str* sslhcfg_anyprot; struct arg_end* sslhcfg_end; - + static struct config_desc table_sslhcfg_protocols[] = { @@ -538,6 +538,22 @@ static struct config_desc table_sslhcfg_protocols[] = { /* default_val*/ .default_val.def_bool = 0 }, + { + /* name */ "transparent", + /* type */ CFG_BOOL, + /* sub_group*/ NULL, + /* arg_cl */ NULL, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_protocols_item, transparent), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_bool = 0 + }, + { /* name */ "log_level", /* type */ CFG_INT, @@ -937,7 +953,7 @@ static struct compound_cl_target sslhcfg_anyprot_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "anyprot" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { 0 } }; @@ -945,7 +961,7 @@ static struct compound_cl_target sslhcfg_socks5_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "socks5" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { 0 } }; @@ -953,7 +969,7 @@ static struct compound_cl_target sslhcfg_adb_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "adb" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { 0 } }; @@ -961,7 +977,7 @@ static struct compound_cl_target sslhcfg_http_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "http" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { 0 } }; @@ -969,7 +985,7 @@ static struct compound_cl_target sslhcfg_xmpp_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "xmpp" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { 0 } }; @@ -977,7 +993,7 @@ static struct compound_cl_target sslhcfg_tinc_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "tinc" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -986,7 +1002,7 @@ static struct compound_cl_target sslhcfg_openvpn_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "openvpn" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -995,7 +1011,7 @@ static struct compound_cl_target sslhcfg_tls_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "tls" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -1005,7 +1021,7 @@ static struct compound_cl_target sslhcfg_ssh_targets [] = { { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, { & table_sslhcfg_protocols[5], 0, .value.def_bool = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -1836,6 +1852,9 @@ static void sslhcfg_protocols_fprint( fprintf(out, "tfo_ok: %d", sslhcfg_protocols->tfo_ok); fprintf(out, "\n"); indent(out, depth); + fprintf(out, "transparent: %d", sslhcfg_protocols->transparent); + fprintf(out, "\n"); + indent(out, depth); fprintf(out, "log_level: %d", sslhcfg_protocols->log_level); fprintf(out, "\n"); indent(out, depth); diff --git a/sslh-conf.h b/sslh-conf.h index 54eeb22..9295c2a 100644 --- a/sslh-conf.h +++ b/sslh-conf.h @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sat Nov 7 18:59:37 2020. + * on Sun Feb 21 20:56:51 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle @@ -56,6 +56,7 @@ struct sslhcfg_protocols_item { int is_udp; int fork; int tfo_ok; + int transparent; int log_level; int keepalive; size_t sni_hostnames_len; diff --git a/sslh-main.c b/sslh-main.c index 178a770..5f8a566 100644 --- a/sslh-main.c +++ b/sslh-main.c @@ -92,7 +92,7 @@ static void printsettings(void) for (i = 0; i < cfg.protocols_len; i++ ) { p = &cfg.protocols[i]; fprintf(stderr, - "%s addr: %s. libwrap service: %s log_level: %d family %d %d [%s] [%s]\n", + "%s addr: %s. libwrap service: %s log_level: %d family %d %d [%s] [%s] [%s]\n", p->name, sprintaddr(buf, sizeof(buf), p->saddr), p->service, @@ -100,7 +100,9 @@ static void printsettings(void) p->saddr->ai_family, p->saddr->ai_addr->sa_family, p->keepalive ? "keepalive" : "", - p->fork ? "fork" : ""); + p->fork ? "fork" : "", + p->transparent ? "transparent" : "" + ); } fprintf(stderr, "timeout: %d\non-timeout: %s\n", cfg.timeout, timeout_protocol()->name); diff --git a/sslhconf.cfg b/sslhconf.cfg index fefa47c..523dce5 100644 --- a/sslhconf.cfg +++ b/sslhconf.cfg @@ -80,6 +80,8 @@ config: { { name: "fork"; type: "bool"; default: false }, { name: "tfo_ok"; type: "bool"; default: false; description: "Set to true if this protocol supports TCP FAST OPEN" }, + { name: "transparent"; type: "bool"; default: false; + description: "Set to proxy this protocol transparently" }, { name: "log_level"; type: "int"; default: 1 }, { name: "keepalive"; type: "bool"; default: false }, { name: "sni_hostnames", diff --git a/test.cfg b/test.cfg index 44a23d9..34a5aee 100644 --- a/test.cfg +++ b/test.cfg @@ -24,7 +24,7 @@ listen: protocols: ( - { name: "ssh"; host: "localhost"; port: "9000"; fork: true; }, + { name: "ssh"; host: "localhost"; port: "9000"; fork: true; transparent: true; }, { name: "socks5"; host: "localhost"; port: "9001"; }, { name: "http"; host: "localhost"; port: "9002"; }, { name: "tinc"; host: "localhost"; port: "9003"; },