Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.

Enable several backends #136

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ Detail about the entire set of options can be found by invoking `stud -h`:
-n --workers=NUM Number of worker processes (Default: 1)
-B --backlog=NUM Set listen backlog size (Default: 100)
-k --keepalive=SECS TCP keepalive on client socket (Default: 3600)

--tcp-user-timeout=MSECS Milliseconds to wait for ACK packets. Only available
in Linux since 2.6.37. Disabled = 0 (Default: 0)

SECURITY:

-r --chroot=DIR Sets chroot directory (Default: "")
Expand Down
135 changes: 126 additions & 9 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <grp.h>
#include <sys/stat.h>
#include <syslog.h>
#ifdef __linux__
#include <sys/utsname.h>
#endif

#include "configuration.h"
#include "version.h"
Expand All @@ -30,11 +33,15 @@
#define CFG_CIPHERS "ciphers"
#define CFG_SSL_ENGINE "ssl-engine"
#define CFG_PREFER_SERVER_CIPHERS "prefer-server-ciphers"
#define CFG_NAMED_CURVE "named-curve"
#define CFG_SESSION_TIMEOUT "session-timeout"
#define CFG_SSL_CACHE_SIZE "openssl-cache-size"
#define CFG_BACKEND "backend"
#define CFG_FRONTEND "frontend"
#define CFG_WORKERS "workers"
#define CFG_BACKLOG "backlog"
#define CFG_KEEPALIVE "keepalive"
#define CFG_TCP_USER_TIMEOUT "tcp-user-timeout"
#define CFG_CHROOT "chroot"
#define CFG_USER "user"
#define CFG_GROUP "group"
Expand Down Expand Up @@ -121,13 +128,17 @@ stud_config * config_new (void) {
r->GID = 0;
r->FRONT_IP = NULL;
r->FRONT_PORT = strdup("8443");
r->BACK_IP = strdup("127.0.0.1");
r->BACK_PORT = strdup("8000");
r->BACKENDS_COUNT = 0;
r->BACKENDS[0].BACK_IP = strdup("127.0.0.1");
r->BACKENDS[0].BACK_PORT = strdup("8000");
r->NCORES = 1;
r->CERT_FILES = NULL;
r->CIPHER_SUITE = NULL;
r->NAMED_CURVE = NULL;
r->ENGINE = NULL;
r->BACKLOG = 100;
r->SESSION_TIMEOUT = -1;
r->SSL_CACHE_SIZE = -1;

#ifdef USE_SHARED_CACHE
r->SHARED_CACHE = 0;
Expand All @@ -145,6 +156,7 @@ stud_config * config_new (void) {
r->SYSLOG = 0;
r->SYSLOG_FACILITY = LOG_DAEMON;
r->TCP_KEEPALIVE_TIME = 3600;
r->TCP_USER_TIMEOUT_MS= 0;
r->DAEMONIZE = 0;
r->PREFER_SERVER_CIPHERS = 0;

Expand All @@ -159,8 +171,10 @@ void config_destroy (stud_config *cfg) {
if (cfg->CHROOT != NULL) free(cfg->CHROOT);
if (cfg->FRONT_IP != NULL) free(cfg->FRONT_IP);
if (cfg->FRONT_PORT != NULL) free(cfg->FRONT_PORT);
if (cfg->BACK_IP != NULL) free(cfg->BACK_IP);
if (cfg->BACK_PORT != NULL) free(cfg->BACK_PORT);
for (int i = 0; i < cfg->BACKENDS_COUNT; i++) {
if (cfg->BACKENDS[i].BACK_IP != NULL) free(cfg->BACKENDS[i].BACK_IP);
if (cfg->BACKENDS[i].BACK_PORT != NULL) free(cfg->BACKENDS[i].BACK_PORT);
}
if (cfg->CERT_FILES != NULL) {
struct cert_files *curr = cfg->CERT_FILES, *next;
while (cfg->CERT_FILES != NULL) {
Expand All @@ -170,6 +184,7 @@ void config_destroy (stud_config *cfg) {
}
}
if (cfg->CIPHER_SUITE != NULL) free(cfg->CIPHER_SUITE);
if (cfg->NAMED_CURVE != NULL) free(cfg->NAMED_CURVE);
if (cfg->ENGINE != NULL) free(cfg->ENGINE);

#ifdef USE_SHARED_CACHE
Expand Down Expand Up @@ -548,19 +563,32 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
config_assign_str(&cfg->CIPHER_SUITE, v);
}
}
else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
else if (strcmp(k, CFG_NAMED_CURVE) == 0) {
if (v != NULL && strlen(v) > 0) {
config_assign_str(&cfg->NAMED_CURVE, v);
}
} else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
if (v != NULL && strlen(v) > 0) {
config_assign_str(&cfg->ENGINE, v);
}
}
else if (strcmp(k, CFG_PREFER_SERVER_CIPHERS) == 0) {
r = config_param_val_bool(v, &cfg->PREFER_SERVER_CIPHERS);
}
else if (strcmp(k, CFG_SESSION_TIMEOUT) == 0) {
r = config_param_val_intl(v, &cfg->SESSION_TIMEOUT);
if (r && cfg->SESSION_TIMEOUT < -1) cfg->SESSION_TIMEOUT = -1;
}
else if (strcmp(k, CFG_SSL_CACHE_SIZE) == 0) {
r = config_param_val_int(v, &cfg->SSL_CACHE_SIZE);
if (r && cfg->SSL_CACHE_SIZE < -1) cfg->SSL_CACHE_SIZE = -1;
}
else if (strcmp(k, CFG_FRONTEND) == 0) {
r = config_param_host_port_wildcard(v, &cfg->FRONT_IP, &cfg->FRONT_PORT, 1);
}
else if (strcmp(k, CFG_BACKEND) == 0) {
r = config_param_host_port(v, &cfg->BACK_IP, &cfg->BACK_PORT);
r = config_param_host_port(v, &cfg->BACKENDS[cfg->BACKENDS_COUNT].BACK_IP, &cfg->BACKENDS[cfg->BACKENDS_COUNT].BACK_PORT);
cfg->BACKENDS_COUNT++;
}
else if (strcmp(k, CFG_WORKERS) == 0) {
r = config_param_val_intl_pos(v, &cfg->NCORES);
Expand All @@ -572,6 +600,56 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
else if (strcmp(k, CFG_KEEPALIVE) == 0) {
r = config_param_val_int_pos(v, &cfg->TCP_KEEPALIVE_TIME);
}
else if (strcmp(k, CFG_TCP_USER_TIMEOUT) == 0) {
#ifdef __linux__
int can_use_option = 0;
struct utsname info;

/* This option is supported in Linux since 2.6.37 */
if (uname(&info) == 0) {
int major, minor, patch;
if (sscanf(info.release, "%d.%d.%d", &major, &minor, &patch) == 3) {
if (major > 2) {
can_use_option = 1;
}
else if (major == 2) {
if (minor > 6) {
can_use_option = 1;
}
else if (minor == 6) {
if (patch >= 37) {
can_use_option = 1;
}
}
}
}
}

r = config_param_val_int(v, &cfg->TCP_USER_TIMEOUT_MS);

if (cfg->TCP_USER_TIMEOUT_MS < 0) {
config_error_set("The option TCP_USER_TIMEOUT must be positive");
r = 0;
}
else if (r && !can_use_option && cfg->TCP_USER_TIMEOUT_MS != 0) {
/* As this is only a warning, not an error, it won't be shown using config_error_set, so we print it to stderr directly */
fprintf(stderr, "TCP_USER_TIMEOUT option can only be used in Linux since 2.6.37, your version is %s. Option disabled.\n", info.release);
cfg->TCP_USER_TIMEOUT_MS = 0;
}
#else
r = config_param_val_int(v, &cfg->TCP_USER_TIMEOUT_MS);

if (cfg->TCP_USER_TIMEOUT_MS < 0) {
config_error_set("The option TCP_USER_TIMEOUT must be positive");
r = 0;
}
else if (r && cfg->TCP_USER_TIMEOUT_MS != 0) {
/* As this is only a warning, not an error, it won't be shown using config_error_set, so we print it to stderr directly */
fprintf(stderr, "TCP_USER_TIMEOUT option can only be used in Linux since 2.6.37. Option disabled.\n");
cfg->TCP_USER_TIMEOUT_MS = 0;
}
#endif
}
#ifdef USE_SHARED_CACHE
else if (strcmp(k, CFG_SHARED_CACHE) == 0) {
r = config_param_val_int(v, &cfg->SHARED_CACHE);
Expand Down Expand Up @@ -870,11 +948,14 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " -c --ciphers=SUITE Sets allowed ciphers (Default: \"%s\")\n", config_disp_str(cfg->CIPHER_SUITE));
fprintf(out, " -e --ssl-engine=NAME Sets OpenSSL engine (Default: \"%s\")\n", config_disp_str(cfg->ENGINE));
fprintf(out, " -O --prefer-server-ciphers Prefer server list order\n");
fprintf(out, " -N --named-curve=NAME Named curve for ECDH (Default: prime256v1, see openssl ecparams -list_curves)\n");
fprintf(out, " -x --session-timeout=SECONDS Session timeout in seconds\n");
fprintf(out, " -y --openssl-cache-size Sets OpenSSL library cache size (0 to disable it)\n");
fprintf(out, "\n");
fprintf(out, "SOCKET:\n");
fprintf(out, "\n");
fprintf(out, " --client Enable client proxy mode\n");
fprintf(out, " -b --backend=HOST,PORT Backend [connect] (default is \"%s\")\n", config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT));
fprintf(out, " -b --backend=HOST,PORT Backend [connect] (can be given multiple times) (default is \"%s\")\n", config_disp_hostport(cfg->BACKENDS[0].BACK_IP, cfg->BACKENDS[0].BACK_PORT));
fprintf(out, " -f --frontend=HOST,PORT Frontend [bind] (default is \"%s\")\n", config_disp_hostport(cfg->FRONT_IP, cfg->FRONT_PORT));

#ifdef USE_SHARED_CACHE
Expand All @@ -895,6 +976,8 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " -n --workers=NUM Number of worker processes (Default: %ld)\n", cfg->NCORES);
fprintf(out, " -B --backlog=NUM Set listen backlog size (Default: %d)\n", cfg->BACKLOG);
fprintf(out, " -k --keepalive=SECS TCP keepalive on client socket (Default: %d)\n", cfg->TCP_KEEPALIVE_TIME);
fprintf(out, " --tcp-user-timeout=MSECS Milliseconds to wait for ACK packets. Only available\n");
fprintf(out, " in Linux since 2.6.37. Disabled = 0 (Default: %d)\n", cfg->TCP_USER_TIMEOUT_MS);

#ifdef USE_SHARED_CACHE
fprintf(out, " -C --session-cache=NUM Enable and set SSL session cache to specified number\n");
Expand Down Expand Up @@ -953,7 +1036,12 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, "#\n");
fprintf(fd, "# type: string\n");
fprintf(fd, "# syntax: [HOST]:PORT.\n");
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT));
if (cfg->BACKENDS_COUNT == 0) {
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACKENDS[0].BACK_IP, cfg->BACKENDS[0].BACK_PORT));
} else {
for (int i = 0; i < cfg->BACKENDS_COUNT; i++)
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACKENDS[i].BACK_IP, cfg->BACKENDS[i].BACK_PORT));
}
fprintf(fd, "\n");

fprintf(fd, "# SSL x509 certificate file. REQUIRED.\n");
Expand Down Expand Up @@ -1006,6 +1094,15 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, "# type: integer\n");
fprintf(fd, FMT_ISTR, CFG_KEEPALIVE, cfg->TCP_KEEPALIVE_TIME);
fprintf(fd, "\n");

#ifdef __linux__
fprintf(fd, "# TCP socket TCP_USER_TIMEOUT option in milliseconds\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: integer\n");
fprintf(fd, "# Value 0 means disabled\n");
fprintf(fd, FMT_ISTR, CFG_TCP_USER_TIMEOUT, cfg->TCP_USER_TIMEOUT_MS);
fprintf(fd, "\n");
#endif

#ifdef USE_SHARED_CACHE
fprintf(fd, "# SSL session cache size\n");
Expand Down Expand Up @@ -1143,7 +1240,10 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ "client", 0, &client, 1},
{ CFG_CIPHERS, 1, NULL, 'c' },
{ CFG_PREFER_SERVER_CIPHERS, 0, NULL, 'O' },
{ CFG_NAMED_CURVE, 1, NULL, 'N' },
{ CFG_BACKEND, 1, NULL, 'b' },
{ CFG_SESSION_TIMEOUT, required_argument, NULL, 'x'},
{ CFG_SSL_CACHE_SIZE, required_argument, NULL, 'y'},
{ CFG_FRONTEND, 1, NULL, 'f' },
{ CFG_WORKERS, 1, NULL, 'n' },
{ CFG_BACKLOG, 1, NULL, 'B' },
Expand All @@ -1154,6 +1254,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ CFG_SHARED_CACHE_MCASTIF, 1, NULL, 'M' },
#endif
{ CFG_KEEPALIVE, 1, NULL, 'k' },
{ CFG_TCP_USER_TIMEOUT, 1, NULL, 'T'},
{ CFG_CHROOT, 1, NULL, 'r' },
{ CFG_USER, 1, NULL, 'u' },
{ CFG_GROUP, 1, NULL, 'g' },
Expand All @@ -1175,7 +1276,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
int option_index = 0;
c = getopt_long(
argc, argv,
"c:e:Ob:f:n:B:C:U:P:M:k:r:u:g:qstVh",
"c:N:e:Ob:f:n:B:C:U:P:M:k:r:u:g:x:y:qstVh",
long_options, &option_index
);

Expand All @@ -1201,12 +1302,21 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
case 'c':
config_param_validate(CFG_CIPHERS, optarg, cfg, NULL, 0);
break;
case 'N':
config_param_validate(CFG_NAMED_CURVE, optarg, cfg, NULL, 0);
break;
case 'e':
config_param_validate(CFG_SSL_ENGINE, optarg, cfg, NULL, 0);
break;
case 'O':
config_param_validate(CFG_PREFER_SERVER_CIPHERS, CFG_BOOL_ON, cfg, NULL, 0);
break;
case 'x':
config_param_validate(CFG_SESSION_TIMEOUT, optarg, cfg, NULL, 0);
break;
case 'y':
config_param_validate(CFG_SSL_CACHE_SIZE, optarg, cfg, NULL, 0);
break;
case 'b':
config_param_validate(CFG_BACKEND, optarg, cfg, NULL, 0);
break;
Expand Down Expand Up @@ -1236,6 +1346,9 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
case 'k':
config_param_validate(CFG_KEEPALIVE, optarg, cfg, NULL, 0);
break;
case 'T':
config_param_validate(CFG_TCP_USER_TIMEOUT, optarg, cfg, NULL, 0);
break;
case 'r':
config_param_validate(CFG_CHROOT, optarg, cfg, NULL, 0);
break;
Expand Down Expand Up @@ -1321,4 +1434,8 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
printf("%s configuration looks ok.\n", basename(prog));
exit(0);
}

// if no backend option given, use default
if (cfg->BACKENDS_COUNT == 0)
cfg->BACKENDS_COUNT = 1;
}
17 changes: 15 additions & 2 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ typedef struct shcupd_peer_opt {

#endif

#define BACKENDS_MAX 32

typedef enum {
ENC_TLS,
ENC_SSL
Expand All @@ -36,6 +38,13 @@ struct cert_files {
struct cert_files *NEXT;
};

struct __stud_backend {
char *BACK_IP;
char *BACK_PORT;
};

typedef struct __stud_backend stud_backend;

/* configuration structure */
struct __stud_config {
ENC_TYPE ETYPE;
Expand All @@ -48,13 +57,16 @@ struct __stud_config {
gid_t GID;
char *FRONT_IP;
char *FRONT_PORT;
char *BACK_IP;
char *BACK_PORT;
int BACKENDS_COUNT;
stud_backend BACKENDS[BACKENDS_MAX];
long NCORES;
struct cert_files *CERT_FILES;
char *CIPHER_SUITE;
char *NAMED_CURVE;
char *ENGINE;
int BACKLOG;
long SESSION_TIMEOUT;
int SSL_CACHE_SIZE;
#ifdef USE_SHARED_CACHE
int SHARED_CACHE;
char *SHCUPD_IP;
Expand All @@ -67,6 +79,7 @@ struct __stud_config {
int SYSLOG;
int SYSLOG_FACILITY;
int TCP_KEEPALIVE_TIME;
int TCP_USER_TIMEOUT_MS;
int DAEMONIZE;
int PREFER_SERVER_CIPHERS;
};
Expand Down
Loading