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

Upstart job and uninstall option #128

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man

UPSTARTDIR = /etc/init
CONFDIR = /etc/stud
CONFFILE = stud.cfg

CFLAGS = -O2 -g -std=c99 -fno-strict-aliasing -Wall -W -D_GNU_SOURCE -I/usr/local/include
LDFLAGS = -lssl -lcrypto -lev -L/usr/local/lib
OBJS = stud.o ringbuffer.o configuration.o
Expand Down Expand Up @@ -45,6 +49,22 @@ install: $(ALL)
install -d $(DESTDIR)$(MANDIR)/man8
install -m 644 stud.8 $(DESTDIR)$(MANDIR)/man8

install -d $(UPSTARTDIR)
install upstart/stud.conf $(UPSTARTDIR)

install -d $(CONFDIR)
stud --default-config > $(CONFDIR)/$(CONFFILE)

uninstall:
rm -f $(DESTDIR)$(BINDIR)/stud
rm -f $(DESTDIR)$(MANDIR)/man8/stud.8
rmdir $(DESTDIR)$(MANDIR)/man8 --ignore-fail-on-non-empty

rm -f $(UPSTARTDIR)/stud.conf

rm -f $(CONFDIR)/$(CONFFILE)
rmdir $(CONFDIR) --ignore-fail-on-non-empty

clean:
rm -f stud $(OBJS)

Expand Down
14 changes: 14 additions & 0 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define CFG_DAEMON "daemon"
#define CFG_WRITE_IP "write-ip"
#define CFG_WRITE_PROXY "write-proxy"
#define CFG_WRITE_XFF "write-xff"
#define CFG_PEM_FILE "pem-file"
#define CFG_PROXY_PROXY "proxy-proxy"

Expand Down Expand Up @@ -115,6 +116,7 @@ stud_config * config_new (void) {
r->PMODE = SSL_SERVER;
r->WRITE_IP_OCTET = 0;
r->WRITE_PROXY_LINE = 0;
r->WRITE_XFF_LINE = 0;
r->PROXY_PROXY_LINE = 0;
r->CHROOT = NULL;
r->UID = 0;
Expand Down Expand Up @@ -684,6 +686,9 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
else if (strcmp(k, CFG_WRITE_PROXY) == 0) {
r = config_param_val_bool(v, &cfg->WRITE_PROXY_LINE);
}
else if (strcmp(k, CFG_WRITE_XFF) == 0) {
r = config_param_val_bool(v, &cfg->WRITE_XFF_LINE);
}
else if (strcmp(k, CFG_PROXY_PROXY) == 0) {
r = config_param_val_bool(v, &cfg->PROXY_PROXY_LINE);
}
Expand Down Expand Up @@ -922,6 +927,8 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " --write-proxy Write HaProxy's PROXY (IPv4 or IPv6) protocol line\n" );
fprintf(out, " before actual data\n");
fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->WRITE_PROXY_LINE));
fprintf(out, " --write-xff Write X-Forwarded-For header before actual data\n" );
fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->WRITE_XFF_LINE));
fprintf(out, " --proxy-proxy Proxy HaProxy's PROXY (IPv4 or IPv6) protocol line\n" );
fprintf(out, " before actual data\n");
fprintf(out, " (Default: %s)\n", config_disp_bool(cfg->PROXY_PROXY_LINE));
Expand Down Expand Up @@ -1109,6 +1116,12 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, FMT_STR, CFG_WRITE_PROXY, config_disp_bool(cfg->WRITE_PROXY_LINE));
fprintf(fd, "\n");

fprintf(fd, "# Report client address using X-Forwarded-For header.\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: boolean\n");
fprintf(fd, FMT_STR, CFG_WRITE_XFF, config_disp_bool(cfg->WRITE_XFF_LINE));
fprintf(fd, "\n");

fprintf(fd, "# Proxy an existing SENDPROXY protocol header through this request.\n");
fprintf(fd, "#\n");
fprintf(fd, "# NOTE: This option is mutually exclusive with option %s and %s.\n", CFG_WRITE_IP, CFG_WRITE_PROXY);
Expand Down Expand Up @@ -1163,6 +1176,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ CFG_DAEMON, 0, &cfg->DAEMONIZE, 1 },
{ CFG_WRITE_IP, 0, &cfg->WRITE_IP_OCTET, 1 },
{ CFG_WRITE_PROXY, 0, &cfg->WRITE_PROXY_LINE, 1 },
{ CFG_WRITE_XFF, 0, &cfg->WRITE_XFF_LINE, 1 },
{ CFG_PROXY_PROXY, 0, &cfg->PROXY_PROXY_LINE, 1 },

{ "test", 0, NULL, 't' },
Expand Down
1 change: 1 addition & 0 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct __stud_config {
PROXY_MODE PMODE;
int WRITE_IP_OCTET;
int WRITE_PROXY_LINE;
int WRITE_XFF_LINE;
int PROXY_PROXY_LINE;
char *CHROOT;
uid_t UID;
Expand Down
3 changes: 3 additions & 0 deletions stud.8
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
.Op Fl qs
.Op Fl -write-ip
.Op Fl -write-proxy
.Op Fl -write-xff
.Ar certificate.pem
.Sh DESCRIPTION
.Nm
Expand Down Expand Up @@ -117,6 +118,8 @@ data.
.It Fl -write-proxy
Write HaProxy's PROXY (IPv4 or IPv6) protocol line
before actual data.
.It Fl -write-xff
Write X-Forwarded-For header before actual data.
.El
.Sh SEE ALSO
.Xr ciphers 1SSL ,
Expand Down
79 changes: 78 additions & 1 deletion stud.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ typedef struct proxystate {
int clear_connected:1; /* Clear stream is connected */
int renegotiation:1; /* Renegotation is occuring */

int sent_xff:1; /* Have sent X-Forwarded-For header */

SSL *ssl; /* OpenSSL SSL state */

struct sockaddr_storage remote_ip; /* Remote ip returned from `accept` */
Expand Down Expand Up @@ -803,6 +805,37 @@ static void prepare_proxy_line(struct sockaddr* ai_addr) {
}
}

char *prepare_xff_line(struct sockaddr* ai_addr) {
static char xff_line[128];
xff_line[0] = 0;
char tcp6_address_string[INET6_ADDRSTRLEN];

if (ai_addr->sa_family == AF_INET) {
struct sockaddr_in* addr = (struct sockaddr_in*)ai_addr;
size_t res = snprintf(xff_line,
sizeof(xff_line),
"X-Forwarded-For: %s\r\n",
inet_ntoa(addr->sin_addr));
assert(res < sizeof(xff_line));
return xff_line;
}
else if (ai_addr->sa_family == AF_INET6 ) {
struct sockaddr_in6* addr = (struct sockaddr_in6*)ai_addr;
inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN);
size_t res = snprintf(xff_line,
sizeof(xff_line),
"X-Forwarded-For:%s\r\n",
tcp6_address_string);
assert(res < sizeof(xff_line));
return xff_line;
}
else {
ERR("The --write-xff mode is not implemented for this address family.\n");
exit(1);
}
return NULL;
}

/* Create the bound socket in the parent process */
static int create_main_socket() {
struct addrinfo *ai, hints;
Expand Down Expand Up @@ -973,7 +1006,50 @@ static void clear_write(struct ev_loop *loop, ev_io *w, int revents) {
assert(!ringbuffer_is_empty(&ps->ring_ssl2clear));

char *next = ringbuffer_read_next(&ps->ring_ssl2clear, &sz);
t = send(fd, next, sz, MSG_NOSIGNAL);


if (ps->sent_xff == 0 && CONFIG->WRITE_XFF_LINE) {
for(int i = 0; i < sz; i++) {
if(next[i] == '\n') {
const char *xff_line = prepare_xff_line((struct sockaddr *)&(ps->remote_ip));
/* Send the request through because we don't know where it's
* from */
if(xff_line == NULL) {
ps->sent_xff = 1;
break;
}
int temporary_buffer_length = sz + strlen(xff_line);
char *temporary_buffer = (char *)malloc(temporary_buffer_length);
/* Send the request through because we don't have enough
* RAM to fiddle with the headers */
if(temporary_buffer == NULL) {
ps->sent_xff = 1;
break;
}
/* Create a temporary buffer with the original HTTP line, the
* XFF header, and the remainer of the ringbuffer */
int http_line_length = i+1;
int xff_line_length = strlen(xff_line);
memcpy(temporary_buffer, next, http_line_length);
memcpy(temporary_buffer+http_line_length, xff_line, xff_line_length);
memcpy(temporary_buffer+http_line_length+xff_line_length, next+http_line_length, sz-http_line_length);

ringbuffer_read_pop(&ps->ring_ssl2clear);

char *write_ptr = ringbuffer_write_ptr(&ps->ring_ssl2clear);
memcpy(write_ptr, temporary_buffer, temporary_buffer_length);
ringbuffer_write_append(&ps->ring_ssl2clear, temporary_buffer_length);
next = write_ptr;
sz = temporary_buffer_length;
free(temporary_buffer);

ps->sent_xff = 1;
break;
}
}
}

t = send(fd, next, sz, MSG_NOSIGNAL);

if (t > 0) {
if (t == sz) {
Expand Down Expand Up @@ -1361,6 +1437,7 @@ static void handle_accept(struct ev_loop *loop, ev_io *w, int revents) {
ps->clear_connected = 0;
ps->handshaked = 0;
ps->renegotiation = 0;
ps->sent_xff = 0;
ps->remote_ip = addr;
ringbuffer_init(&ps->ring_clear2ssl);
ringbuffer_init(&ps->ring_ssl2clear);
Expand Down
16 changes: 16 additions & 0 deletions upstart/stud.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
description "Scalable TLS Unwrapping Daemon (stud)"
author "Bump Technologies (upstart script contributed by axsh Co.)"

stop on runlevel [S016]
start on runlevel [23]

respawn
respawn limit unlimited

script
# If this job is failed, upstart supervisor will run again soon. It's too fast.
# Therefore a proper sleep is needed.
sleep ${SLEEP_SEC:-1}

exec stud --config /etc/stud/stud.cfg
end script