From cac7f48fa729d2c6ff288ab8f72baed0f64c6700 Mon Sep 17 00:00:00 2001 From: Yves Rutschle Date: Sun, 22 Dec 2024 16:17:47 +0100 Subject: [PATCH] new is_unix field to connect to unix socket target servers --- common.c | 27 ++++++++++++++++++++++- example.cfg | 7 +++++- sslh-conf.c | 61 ++++++++++++++++++++++++++++++++++------------------ sslh-conf.h | 3 ++- sslh-main.c | 31 +++++++++++++++++++------- sslhconf.cfg | 1 + test.cfg | 2 +- version.h | 2 +- 8 files changed, 100 insertions(+), 34 deletions(-) diff --git a/common.c b/common.c index c4d0178..9ea69d4 100644 --- a/common.c +++ b/common.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "common.h" #include "probe.h" @@ -404,6 +405,24 @@ static int connect_inet(struct connection *cnx, int fd_from, connect_blocking bl return -1; } +/* Connects to AF_UNIX domain sockets */ +static int connect_unix(struct connection *cnx, int fd_from, connect_blocking blocking) +{ + struct sockaddr_storage ss; + struct sockaddr_un* sun = (struct sockaddr_un*)&ss; + + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + sun->sun_family = AF_UNIX; + strcpy(sun->sun_path, cnx->proto->host); + + int res = connect(fd, (struct sockaddr*)sun, sizeof(*sun)); + CHECK_RES_RETURN(res, "connect", res); + + if (blocking == NON_BLOCKING) { + set_nonblock(fd); + } + return fd; +} /* Connect to first address that works and returns a file descriptor, or -1 if * none work. @@ -411,7 +430,13 @@ static int connect_inet(struct connection *cnx, int fd_from, connect_blocking bl * of new file descriptor. */ int connect_addr(struct connection *cnx, int fd_from, connect_blocking blocking) { - int fd = connect_inet(cnx, fd_from, blocking); + int fd; + + if (cnx->proto->is_unix) { + fd = connect_unix(cnx, fd_from, blocking); + } else { + fd = connect_inet(cnx, fd_from, blocking); + } return fd; } diff --git a/example.cfg b/example.cfg index fe2f3ab..ac727b3 100644 --- a/example.cfg +++ b/example.cfg @@ -76,6 +76,9 @@ listen: # transparent: Set to true to proxy this protocol # transparently (server sees the remote client IP # address). Same as the global option, but per-protocol +# is_unix: [true|false] connect to a UNIX socket. The host +# field becomes the pathname to the socket, and the port +# field is unused (but necessary). # # Probe-specific options: # (sslh will try each probe in order they are declared, and @@ -109,7 +112,9 @@ protocols: ( { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; keepalive: true; fork: true; tfo_ok: true }, - { name: "http"; host: "localhost"; port: "80"; }, + +# UNIX socket to a local NGINX. The socket name is in 'host'; 'port' is necessary but not used. + { name: "http"; is_unix: true; host: "/tmp/nginx.sock"; port: ""; }, # match BOTH ALPN/SNI { name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; sni_hostnames: [ "im.somethingelse.net" ]; log_level: 0; tfo_ok: true }, diff --git a/sslh-conf.c b/sslh-conf.c index ed4ab75..6602466 100644 --- a/sslh-conf.c +++ b/sslh-conf.c @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sun Dec 22 00:05:31 2024. + * on Sun Dec 22 16:13:50 2024. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2024 Yves Rutschle @@ -500,7 +500,7 @@ struct arg_file* sslhcfg_conffile; struct arg_str* sslhcfg_anyprot; struct arg_end* sslhcfg_end; - + static struct config_desc table_sslhcfg_protocols[] = { @@ -568,6 +568,22 @@ static struct config_desc table_sslhcfg_protocols[] = { /* default_val*/ .default_val.def_string = NULL }, + { + /* name */ "is_unix", + /* type */ CFG_BOOL, + /* sub_group*/ NULL, + /* arg_cl */ NULL, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_protocols_item, is_unix), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_bool = 0 + }, + { /* name */ "is_udp", /* type */ CFG_BOOL, @@ -1287,7 +1303,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[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1295,7 +1311,7 @@ static struct compound_cl_target sslhcfg_msrdp_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "msrdp" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1303,7 +1319,7 @@ static struct compound_cl_target sslhcfg_syslog_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "syslog" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1311,7 +1327,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[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1319,7 +1335,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[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1327,7 +1343,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[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1335,7 +1351,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[10], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, { 0 } }; @@ -1343,8 +1359,8 @@ static struct compound_cl_target sslhcfg_wireguard_targets [] = { { & table_sslhcfg_protocols[0], 0, .value.def_string = "wireguard" }, { & table_sslhcfg_protocols[1], 1, .value.def_string = "0" }, { & table_sslhcfg_protocols[2], 2, .value.def_string = "0" }, - { & table_sslhcfg_protocols[10], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -1352,8 +1368,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[10], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -1361,8 +1377,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[10], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -1370,8 +1386,8 @@ static struct compound_cl_target sslhcfg_ssl_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[10], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -1379,8 +1395,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[10], 0, .value.def_int = 1 }, - { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -1388,9 +1404,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[6], 0, .value.def_bool = 1 }, - { & table_sslhcfg_protocols[10], 0, .value.def_int = 1 }, { & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 }, + { & table_sslhcfg_protocols[11], 0, .value.def_int = 1 }, + { & table_sslhcfg_protocols[8], 0, .value.def_bool = 1 }, { 0 } }; @@ -2346,6 +2362,9 @@ static void sslhcfg_protocols_fprint( fprintf(out, " "); fprintf(out, "\n"); indent(out, depth); + fprintf(out, "is_unix: %d", sslhcfg_protocols->is_unix); + fprintf(out, "\n"); + indent(out, depth); fprintf(out, "is_udp: %d", sslhcfg_protocols->is_udp); fprintf(out, "\n"); indent(out, depth); diff --git a/sslh-conf.h b/sslh-conf.h index 205a306..b107e04 100644 --- a/sslh-conf.h +++ b/sslh-conf.h @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sun Dec 22 00:05:31 2024. + * on Sun Dec 22 16:13:50 2024. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2024 Yves Rutschle @@ -53,6 +53,7 @@ struct sslhcfg_protocols_item { char* port; int service_is_present; char* service; + int is_unix; int is_udp; int udp_timeout; int fork; diff --git a/sslh-main.c b/sslh-main.c index 292854e..7c91400 100644 --- a/sslh-main.c +++ b/sslh-main.c @@ -67,13 +67,17 @@ static void printsettings(void) for (i = 0; i < cfg.protocols_len; i++ ) { p = &cfg.protocols[i]; - strcpy(buf, "resolve on forward"); - if (!p->resolve_on_forward) { - sprintaddr(buf, sizeof(buf), p->saddr); - size_t len = strlen(buf); - sprintf(buf+len, " family %d %d", - p->saddr->ai_family, - p->saddr->ai_addr->sa_family); + if (p->is_unix) { + sprintf(buf, "unix socket: %s", p->host); + } else { + strcpy(buf, "resolve on forward"); + if (!p->resolve_on_forward) { + sprintaddr(buf, sizeof(buf), p->saddr); + size_t len = strlen(buf); + sprintf(buf+len, " family %d %d", + p->saddr->ai_family, + p->saddr->ai_addr->sa_family); + } } print_message(msg_config, "%s addr: %s. libwrap service: %s log_level: %d [%s] [%s] [%s]\n", @@ -149,6 +153,15 @@ void config_finish(struct sslhcfg_item* cfg) } } +/* Checks that the UNIX socket specified exists and is accessible + * Dies otherwise + */ +static void check_access_unix_socket(struct sslhcfg_protocols_item* p) +{ + /* TODO */ + return; +} + /* For each protocol in the configuration, resolve address and set up protocol * options if required @@ -159,7 +172,9 @@ static void config_protocols() for (i = 0; i < cfg.protocols_len; i++) { struct sslhcfg_protocols_item* p = &(cfg.protocols[i]); - if ( + if (p->is_unix) { + check_access_unix_socket(p); + } else if ( !p->resolve_on_forward && resolve_split_name(&(p->saddr), p->host, p->port) ) { diff --git a/sslhconf.cfg b/sslhconf.cfg index e64b49f..a5eac71 100644 --- a/sslhconf.cfg +++ b/sslhconf.cfg @@ -110,6 +110,7 @@ config: { { name: "host"; type: "string"; var: true; }, { name: "port"; type: "string"; var: true; }, { name: "service"; type: "string"; optional: true; }, + { name: "is_unix"; type: "bool"; default: false }, { name: "is_udp"; type: "bool"; default: false }, { name: "udp_timeout"; type: "int"; default: 60 }, { name: "fork"; type: "bool"; default: false }, diff --git a/test.cfg b/test.cfg index 26c7a47..bd09297 100644 --- a/test.cfg +++ b/test.cfg @@ -44,7 +44,7 @@ protocols: ( { name: "ssh"; host: "localhost"; port: "9000"; fork: true; transparent: true; resolve_on_forward: true; }, { name: "socks5"; host: "localhost"; port: "9001"; }, - { name: "http"; host: "localhost"; port: "9002"; }, + { name: "http"; is_unix: true; host: "/tmp/nginx.sock"; port: ""; }, { name: "tinc"; host: "localhost"; port: "9003"; }, { name: "openvpn"; host: "localhost"; port: "9004"; }, { name: "xmpp"; host: "localhost"; port: "9009"; }, diff --git a/version.h b/version.h index 5b41ac4..cccb9cd 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION "v2.1.4-21-g16ef412-dirty" +#define VERSION "v2.1.4-22-g9e6b4fa-dirty" #endif