tlsgate

TLS reverse proxy
git clone git://git.akobets.xyz/tlsgate
Log | Files | Refs | README | LICENSE

commit cdaa9c71fa4af2608b9b56299c7e76d8945ae636
parent fe985a999500c65f9ca4a9bad7ab19c69b702b95
Author: Artem Kobets <artem@akobets.xyz>
Date:   Sat, 19 Sep 2020 21:17:44 +0300

add -u proxy unix domain socket argument

Diffstat:
Mmain.c | 44+++++++++++++++++++++++++++++++++++---------
Msock.c | 34++++++++++++++++++++++++++++++++++
Msock.h | 2++
Mtlsgate.1 | 3+++
4 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/main.c b/main.c @@ -3,6 +3,7 @@ #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/wait.h> #include <unistd.h> @@ -16,9 +17,10 @@ #define REQUEST_TIMEOUT 30000 static void serve(struct tls *ctx, int cfd); +static void cleanup(void); static void sigchld(int unused); static void sigcleanup(int sig); -static void handle_termsignals(void(*func)(int)); +static void handle_termsignals(void (*func)(int)); static void usage(void); char *argv0; @@ -28,6 +30,7 @@ static char *key_file = NULL; static char *ca_file = NULL; static char *proxy_host = NULL; static char *proxy_port = NULL; +static char *proxy_udsfile = NULL; static char *server_host = NULL; static char *server_port = NULL; static char *server_udsfile = NULL; @@ -198,11 +201,18 @@ sigchld(int unused) } static void +cleanup() +{ + if (proxy_udsfile != NULL) + sock_remove_uds(proxy_udsfile); +} + +static void sigcleanup(int sig) { struct sigaction act; - // cleanup(); + cleanup(); kill(0, sig); act.sa_handler = SIG_DFL; @@ -212,7 +222,7 @@ sigcleanup(int sig) } static void -handle_termsignals(void(*func)(int)) +handle_termsignals(void (*func)(int)) { struct sigaction act; @@ -229,7 +239,8 @@ usage(void) fprintf( stderr, "usage: %s [-v] -c cert -k key [-C ca]\n" - " [-h host] [-p port] [-H host] [-P port] [-U file]\n", + " [-h host] [-p port] [-u file]\n" + " [-H host] [-P port] [-U file]\n", argv0 ); exit(1); @@ -246,7 +257,7 @@ main(int argc, char **argv) argv0 = argv[0]; - while ((opt = getopt(argc, argv, "c:k:C:h:p:H:P:U:v")) != -1) { + while ((opt = getopt(argc, argv, "c:k:C:h:p:u:H:P:U:v")) != -1) { switch (opt) { case 'c': cert_file = optarg; @@ -263,6 +274,9 @@ main(int argc, char **argv) case 'p': proxy_port = optarg; break; + case 'u': + proxy_udsfile = optarg; + break; case 'H': server_host = optarg; break; @@ -285,8 +299,11 @@ main(int argc, char **argv) // cert and private key files are required if (cert_file == NULL || key_file == NULL) usage(); - // proxy host can be NULL, port is required - if (proxy_port == NULL) + // allow IPS or UDS proxy + if ( + (proxy_host != NULL && proxy_udsfile != NULL) || + !(proxy_port != NULL || proxy_udsfile != NULL) + ) usage(); // allow IPS or UDS server if ( @@ -295,6 +312,13 @@ main(int argc, char **argv) ) usage(); + if ( + proxy_udsfile != NULL && + (access(proxy_udsfile, F_OK) == 0 || errno != ENOENT) + ) + errx("UNIX domain socket '%s': %s", proxy_udsfile, + errno ? strerror(errno) : "File exists"); + // setup tls if ((ctx = tls_server()) == NULL) err("tls_server"); @@ -318,7 +342,9 @@ main(int argc, char **argv) handle_termsignals(sigcleanup); // setup proxy socket - fd = sock_proxy_ips(proxy_host, proxy_port); + fd = proxy_udsfile + ? sock_proxy_uds(proxy_udsfile) + : sock_proxy_ips(proxy_host, proxy_port); switch (fork()) { case 0: @@ -365,6 +391,6 @@ main(int argc, char **argv) break; } - // cleanup(); + cleanup(); return 1; } diff --git a/sock.c b/sock.c @@ -1,4 +1,5 @@ #include <fcntl.h> +#include <errno.h> #include <stdio.h> #include <sys/time.h> #include <unistd.h> @@ -55,6 +56,39 @@ sock_proxy_ips(const char *host, const char *port) } int +sock_proxy_uds(const char *file) +{ + int fd; + struct sockaddr_un addr; + int saved_errno; + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) + err("socket"); + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", file); + + if (bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) + err("bind"); + + if (listen(fd, SOMAXCONN) == -1) { + saved_errno = errno; + sock_remove_uds(file); + errno = saved_errno; + err("listen"); + } + + return fd; +} + +void +sock_remove_uds(const char *file) +{ + if (unlink(file) == -1) + err("unlink"); +} + +int sock_server_ips(const char *host, const char *port) { struct addrinfo hints = { diff --git a/sock.h b/sock.h @@ -1,4 +1,6 @@ int sock_proxy_ips(const char *host, const char *port); +int sock_proxy_uds(const char *file); +void sock_remove_uds(const char *file); int sock_server_ips(const char *host, const char *port); int sock_server_uds(const char *file); int sock_set_nonblock(int fd); diff --git a/tlsgate.1 b/tlsgate.1 @@ -29,6 +29,9 @@ TLS proxy hostname. .B \-p port TLS proxy port number. .TP +.B \-u file +TLS UNIX domain socket path. +.TP .B \-H host Server hostname. .TP