From ebeabb6c1895ad49e01467b3c9a48f58c5f270ff Mon Sep 17 00:00:00 2001 From: yrutschle Date: Sat, 7 Nov 2020 21:29:09 +0100 Subject: [PATCH] add is_udp option and listen to UDP ports --- common.c | 21 ++++++++-------- example.cfg | 6 ++++- sslh-conf.c | 70 ++++++++++++++++++++++++++++++++++++++++------------ sslh-conf.h | 4 ++- sslhconf.cfg | 2 ++ test.cfg | 4 ++- 6 files changed, 78 insertions(+), 29 deletions(-) diff --git a/common.c b/common.c index f38baec..1fc976d 100644 --- a/common.c +++ b/common.c @@ -113,14 +113,14 @@ int make_listen_tfo(int s) /* Starts listening on a single address * Returns a socket filehandle, or dies with message in case of major error */ -int listen_single_addr(struct addrinfo* addr) +int listen_single_addr(struct addrinfo* addr, int keepalive, int udp) { struct sockaddr_storage *saddr; int sockfd, one, res; saddr = (struct sockaddr_storage*)addr->ai_addr; - sockfd = socket(saddr->ss_family, SOCK_STREAM, 0); + sockfd = socket(saddr->ss_family, udp ? SOCK_DGRAM : SOCK_STREAM, 0); check_res_dump(CR_DIE, sockfd, addr, "socket"); one = 1; @@ -130,7 +130,7 @@ int listen_single_addr(struct addrinfo* addr) res = make_listen_tfo(sockfd); check_res_dump(CR_WARN, res, addr, "setsockopt(TCP_FASTOPEN)"); - if (addr->ai_flags & SO_KEEPALIVE) { + if (keepalive) { res = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(one)); check_res_dump(CR_DIE, res, addr, "setsockopt(SO_KEEPALIVE)"); } @@ -148,8 +148,10 @@ int listen_single_addr(struct addrinfo* addr) res = bind(sockfd, addr->ai_addr, addr->ai_addrlen); check_res_dump(CR_DIE, res, addr, "bind"); - res = listen (sockfd, 50); - check_res_dump(CR_DIE, res, addr, "listen"); + if (!udp) { + res = listen (sockfd, 50); + check_res_dump(CR_DIE, res, addr, "listen"); + } return sockfd; } @@ -164,7 +166,7 @@ int start_listen_sockets(int *sockfd[]) struct addrinfo *addr, *start_addr; char buf[NI_MAXHOST]; int i, res; - int num_addr = 0; + int num_addr = 0, keepalive = 0, udp = 0; int sd_socks = 0; sd_socks = get_fd_sockets(sockfd); @@ -182,13 +184,12 @@ int start_listen_sockets(int *sockfd[]) if (res) exit(4); for (addr = start_addr; addr; addr = addr->ai_next) { - if (cfg.listen[i].keepalive) - addr->ai_flags = SO_KEEPALIVE; + keepalive = cfg.listen[i].keepalive; + udp = cfg.listen[i].is_udp; num_addr++; *sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd)); - (*sockfd)[num_addr-1] = listen_single_addr(addr); -/* printf("%d = %d\n", num_addr-1, (*sockfd)[num_addr-1]); */ + (*sockfd)[num_addr-1] = listen_single_addr(addr, keepalive, udp); if (cfg.verbose) fprintf(stderr, "\t%s\t[%s]\n", sprintaddr(buf, sizeof(buf), addr), cfg.listen[i].keepalive ? "keepalive" : ""); diff --git a/example.cfg b/example.cfg index 51d085c..c494d9b 100644 --- a/example.cfg +++ b/example.cfg @@ -25,7 +25,8 @@ syslog_facility: "auth"; listen: ( { host: "thelonious"; port: "443"; }, - { host: "thelonious"; port: "8080"; keepalive: true; } + { host: "thelonious"; port: "8080"; keepalive: true; }, + { host: "thelonious"; is_udp: true; port: "443" } ); # List of protocols @@ -89,6 +90,9 @@ protocols: # catch anything else TLS { name: "tls"; host: "localhost"; port: "443"; tfo_ok: true }, +# Forward UDP + { name: "regex"; host: "localhost"; is_udp: true; port: "123"; regex_patterns: [ "hello" ]; }, + # Regex examples -- better use the built-in probes for real-world use! # OpenVPN { name: "regex"; host: "localhost"; port: "1194"; regex_patterns: [ "^\x00[\x0D-\xFF]$", "^\x00[\x0D-\xFF]\x38" ]; }, diff --git a/sslh-conf.c b/sslh-conf.c index 862f580..55a7e2d 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 09:31:10 2020. + * on Sat Nov 7 18:59:37 2020. # 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[] = { @@ -490,6 +490,22 @@ static struct config_desc table_sslhcfg_protocols[] = { /* default_val*/ .default_val.def_string = NULL }, + { + /* name */ "is_udp", + /* type */ CFG_BOOL, + /* sub_group*/ NULL, + /* arg_cl */ NULL, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_protocols_item, is_udp), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_bool = 0 + }, + { /* name */ "fork", /* type */ CFG_BOOL, @@ -619,7 +635,7 @@ static struct config_desc table_sslhcfg_protocols[] = { }, { 0 } }; - + static struct config_desc table_sslhcfg_listen[] = { @@ -655,6 +671,22 @@ static struct config_desc table_sslhcfg_listen[] = { /* default_val*/ .default_val.def_string = NULL }, + { + /* name */ "is_udp", + /* type */ CFG_BOOL, + /* sub_group*/ NULL, + /* arg_cl */ NULL, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_listen_item, is_udp), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_bool = 0 + }, + { /* name */ "keepalive", /* type */ CFG_BOOL, @@ -905,7 +937,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[6], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, { 0 } }; @@ -913,7 +945,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[6], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, { 0 } }; @@ -921,7 +953,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[6], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, { 0 } }; @@ -929,7 +961,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[6], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, { 0 } }; @@ -937,7 +969,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[6], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, { 0 } }; @@ -945,8 +977,8 @@ 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[6], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[5], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -954,8 +986,8 @@ 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[6], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[5], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -963,8 +995,8 @@ 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[6], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[5], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -972,9 +1004,9 @@ static struct compound_cl_target sslhcfg_ssh_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "ssh" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[4], 0, .value.def_bool = 1 }, - { & table_sslhcfg_protocols[6], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[5], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[7], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[6], 0, .value.def_bool = 1 }, { 0 } }; @@ -1795,6 +1827,9 @@ static void sslhcfg_protocols_fprint( fprintf(out, " "); fprintf(out, "\n"); indent(out, depth); + fprintf(out, "is_udp: %d", sslhcfg_protocols->is_udp); + fprintf(out, "\n"); + indent(out, depth); fprintf(out, "fork: %d", sslhcfg_protocols->fork); fprintf(out, "\n"); indent(out, depth); @@ -1844,6 +1879,9 @@ static void sslhcfg_listen_fprint( fprintf(out, "port: %s", sslhcfg_listen->port); fprintf(out, "\n"); indent(out, depth); + fprintf(out, "is_udp: %d", sslhcfg_listen->is_udp); + fprintf(out, "\n"); + indent(out, depth); fprintf(out, "keepalive: %d", sslhcfg_listen->keepalive); fprintf(out, "\n"); } diff --git a/sslh-conf.h b/sslh-conf.h index 6edb704..54eeb22 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 09:31:10 2020. + * on Sat Nov 7 18:59:37 2020. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle @@ -43,6 +43,7 @@ struct sslhcfg_listen_item { char* host; char* port; + int is_udp; int keepalive; }; @@ -52,6 +53,7 @@ struct sslhcfg_protocols_item { char* port; int service_is_present; char* service; + int is_udp; int fork; int tfo_ok; int log_level; diff --git a/sslhconf.cfg b/sslhconf.cfg index 6062424..fefa47c 100644 --- a/sslhconf.cfg +++ b/sslhconf.cfg @@ -63,6 +63,7 @@ config: { items: ( { name: "host"; type: "string"; var: true; }, { name: "port"; type: "string"; var: true; }, + { name: "is_udp"; type: "bool"; default: false }, { name: "keepalive"; type: "bool"; default: false; } ) }, @@ -75,6 +76,7 @@ config: { { name: "host"; type: "string"; var: true; }, { name: "port"; type: "string"; var: true; }, { name: "service"; type: "string"; optional: true; }, + { name: "is_udp"; type: "bool"; default: false }, { name: "fork"; type: "bool"; default: false }, { name: "tfo_ok"; type: "bool"; default: false; description: "Set to true if this protocol supports TCP FAST OPEN" }, diff --git a/test.cfg b/test.cfg index d08c565..a958e0a 100644 --- a/test.cfg +++ b/test.cfg @@ -17,7 +17,8 @@ syslog_facility: "auth"; listen: ( { host: "localhost"; port: "8080"; keepalive: true; }, - { host: "localhost"; port: "8081"; keepalive: true; } + { host: "localhost"; port: "8081"; keepalive: true; }, + { host: "localhost"; is_udp: true; port: "4443"; } ); @@ -30,6 +31,7 @@ protocols: { name: "openvpn"; host: "localhost"; port: "9004"; }, { name: "xmpp"; host: "localhost"; port: "9009"; }, { name: "adb"; host: "localhost"; port: "9010"; }, + { name: "regex"; host: "localhost"; is_udp: true; port: "2020"; }, { name: "regex"; host: "localhost"; port: "9011"; regex_patterns: [ "^foo", "^bar" ]; minlength: 4;