Commit 0658982705270b6f79c5387db43e95e7c1f67465
v1.6: 25APR2009
Added -V, version option. Install target directory configurable in Makefile Changed syslog prefix in auth.log to "sslh[%pid]" Man page new 'make install' and 'make install-debian' targets PID file now specified using -P command line option Actually fixed zombie generation (the v1.5 patch got lost, doh!)Yves Rutschle committed on 7/10/2013, 9:10:43 PM
Parent: b965d735b8cede5dfc93947da5c59e562aceb559
Files changed
Makefile | changed |
README | changed |
scripts/etc.default.sslh | changed |
scripts/etc.init.d.sslh | changed |
sslh.c | changed |
sslh.pod | added |
Makefile | ||
---|---|---|
@@ -1,23 +1,49 @@ | ||
1 | 1 | # Configuration |
2 | 2 | |
3 | +VERSION="v1.6i" | |
3 | 4 | USELIBWRAP=1 # Use libwrap? |
5 | +PREFIX=/usr/local | |
4 | 6 | |
7 | +MAN=sslh.8.gz # man page name | |
5 | 8 | |
6 | 9 | # End of configuration -- the rest should take care of |
7 | 10 | # itself |
8 | 11 | |
9 | 12 | CC = gcc |
13 | +CFLAGS=-Wall | |
10 | 14 | |
11 | 15 | #LIBS=-lnet |
12 | 16 | LIBS= |
13 | 17 | |
14 | 18 | ifneq ($(strip $(USELIBWRAP)),) |
15 | 19 | LIBS:=$(LIBS) -lwrap |
16 | - CFLAGS=-DLIBWRAP | |
20 | + CFLAGS:=$(CFLAGS) -DLIBWRAP | |
17 | 21 | endif |
18 | 22 | |
19 | -all: | |
20 | - $(CC) $(CFLAGS) -o sslh sslh.c $(LIBS) | |
23 | +all: sslh $(MAN) | |
24 | + | |
25 | +sslh: sslh.c Makefile | |
26 | + $(CC) $(CFLAGS) -D'VERSION=$(VERSION)' -o sslh sslh.c $(LIBS) | |
21 | 27 | strip sslh |
22 | 28 | |
29 | +$(MAN): sslh.pod Makefile | |
30 | + pod2man --section=8 --release=$(VERSION) --center=" " sslh.pod | gzip -9 - > $(MAN) | |
23 | 31 | |
32 | +# generic install: install binary and man page | |
33 | +install: sslh $(MAN) | |
34 | + install -D sslh $(PREFIX)/sbin/sslh | |
35 | + install -D -m 0644 $(MAN) $(PREFIX)/share/man/man8/$(MAN) | |
36 | + | |
37 | +# "extended" install for Debian: install startup script | |
38 | +install-debian: install sslh $(MAN) | |
39 | + sed -e "s+^PREFIX=+PREFIX=$(PREFIX)+" scripts/etc.init.d.sslh > /etc/init.d/sslh | |
40 | + chmod 755 /etc/init.d/sslh | |
41 | + cp scripts/etc.default.sslh /etc/default/sslh | |
42 | + update-rc.d sslh defaults | |
43 | + | |
44 | +uninstall: | |
45 | + rm -f $(PREFIX)/sbin/sslh $(PREFIX)/share/man/man8/$(MAN) /etc/init.d/sslh /etc/default/sslh | |
46 | + update-rc.d sslh remove | |
47 | + | |
48 | +clean: | |
49 | + rm -f sslh $(MAN) |
README | ||
---|---|---|
@@ -1,12 +1,22 @@ | ||
1 | -sslh -- A ssl/ssh multiplexer. | |
1 | +===== sslh -- A ssl/ssh multiplexer. ===== | |
2 | 2 | |
3 | 3 | sslh lets one accept both HTTPS and SSH connections on the |
4 | 4 | same port. It makes it possible to connect to an SSH server |
5 | 5 | on port 443 (e.g. from inside a corporate firewall) while |
6 | 6 | still serving HTTPS on that port. |
7 | 7 | |
8 | +==== Compile and install ==== | |
8 | 9 | |
10 | +If you're lucky, the Makefile will work for you: | |
11 | + | |
12 | +make install | |
13 | + | |
14 | +(see below for configuration hints) | |
15 | + | |
16 | + | |
17 | +Otherwise: | |
18 | + | |
9 | 19 | Compilation instructions: |
10 | 20 | |
11 | 21 | Solaris: |
12 | 22 | cc -o sslh sslh.c -lresolv -lsocket -lnsl |
@@ -28,21 +38,32 @@ | ||
28 | 38 | cp sslh /usr/local/sbin |
29 | 39 | cp scripts/etc.init.d.sslh /etc/init.d/sslh |
30 | 40 | cp scripts/etc.default.sslh /etc/default/sslh |
31 | 41 | |
42 | +and probably create links in /etc/rc<x>.d so that the server | |
43 | +start automatically at boot-up, e.g. under Debian: | |
44 | +update-rc.d sslh defaults | |
45 | + | |
46 | + | |
47 | + | |
48 | +==== Configuration ==== | |
49 | + | |
32 | 50 | You can edit settings in /etc/default/sslh: |
33 | 51 | |
34 | -PIDFILE=/var/run/sslh.pid | |
35 | 52 | LISTEN=ifname:443 |
36 | 53 | SSH=localhost:22 |
37 | 54 | SSL=localhost:443 |
38 | 55 | |
39 | 56 | A good scheme is to use the external name of the machine in |
40 | -$LISTEN, and bind httpd to localhost:443: that way, https | |
41 | -connections coming from inside your network don't need to go | |
42 | -through sslh, and sslh is only there as a frontal for | |
43 | -connections coming from the internet. | |
57 | +$LISTEN, and bind httpd to localhost:443 (instead of all | |
58 | +binding to all interfaces): that way, https connections | |
59 | +coming from inside your network don't need to go through | |
60 | +sslh, and sslh is only there as a frontal for connections | |
61 | +coming from the internet. | |
44 | 62 | |
63 | + | |
64 | +==== Libwrap support ==== | |
65 | + | |
45 | 66 | Sslh can optionnaly perform libwrap checks for the sshd |
46 | 67 | service: because the connection to sshd will be coming |
47 | 68 | locally from sslh, sshd cannot determine the IP of the |
48 | 69 | client. |
@@ -50,8 +71,19 @@ | ||
50 | 71 | Comments? questions? sslh@rutschle.net |
51 | 72 | |
52 | 73 | HISTORY |
53 | 74 | |
75 | +v1.6: 25APR2009 | |
76 | + Added -V, version option. | |
77 | + Install target directory configurable in Makefile | |
78 | + Changed syslog prefix in auth.log to "sslh[%pid]" | |
79 | + Man page | |
80 | + new 'make install' and 'make install-debian' targets | |
81 | + PID file now specified using -P command line option | |
82 | + Actually fixed zombie generation (the v1.5 patch got | |
83 | + lost, doh!) | |
84 | + | |
85 | + | |
54 | 86 | v1.5: 10DEC2008 |
55 | 87 | Fixed zombie generation. |
56 | 88 | Added support scripts (), Makefile. |
57 | 89 | Changed all 'connexions' to 'connections' to please |
scripts/etc.default.sslh | ||
---|---|---|
@@ -1,4 +1,3 @@ | ||
1 | -PIDFILE=/var/run/sslh.pid | |
2 | 1 | LISTEN=ifname:443 |
3 | 2 | SSH=localhost:22 |
4 | 3 | SSL=localhost:443 |
scripts/etc.init.d.sslh | ||
---|---|---|
@@ -13,19 +13,20 @@ | ||
13 | 13 | |
14 | 14 | # /etc/init.d/sslh: start and stop the sslh proxy daemon |
15 | 15 | |
16 | 16 | # Defaults -- can be overridden in /etc/default/sslh |
17 | -PIDFILE=/var/run/sslh.pid | |
18 | 17 | LISTEN=thelonious:443 |
19 | 18 | SSH=localhost:22 |
20 | 19 | SSL=localhost:443 |
21 | 20 | |
22 | 21 | if test -f /etc/default/sslh; then |
23 | 22 | . /etc/default/sslh |
24 | - export PIDFILE=${PIDFILE} | |
25 | 23 | fi |
26 | 24 | |
27 | -DAEMON=/usr/local/sbin/sslh | |
25 | +# The prefix is normally filled by make install. If | |
26 | +# installing by hand, fill it in yourself! | |
27 | +PREFIX= | |
28 | +DAEMON=$PREFIX/sbin/sslh | |
28 | 29 | |
29 | 30 | start() |
30 | 31 | { |
31 | 32 | echo "Start services: sslh" |
sslh.c | ||
---|---|---|
@@ -19,10 +19,9 @@ | ||
19 | 19 | |
20 | 20 | |
21 | 21 | */ |
22 | 22 | |
23 | - | |
24 | - | |
23 | + | |
25 | 24 | |
26 | 25 | |
27 | 26 | |
28 | 27 | |
@@ -35,8 +34,9 @@ | ||
35 | 34 | |
36 | 35 | |
37 | 36 | |
38 | 37 | |
38 | + | |
39 | 39 | |
40 | 40 | |
41 | 41 | |
42 | 42 | int allow_severity =0, deny_severity = 0; |
@@ -49,17 +49,18 @@ | ||
49 | 49 | exit(1); \ |
50 | 50 | } |
51 | 51 | |
52 | 52 | |
53 | -"sslh v" VERSION "\n" \ | |
53 | +"sslh " VERSION "\n" \ | |
54 | 54 | "usage:\n" \ |
55 | -"\texport PIDFILE=/var/run/sslhc.pid\n" \ | |
56 | 55 | "\tsslh [-t <timeout>] -u <username> -p [listenaddr:]<listenport> \n" \ |
57 | -"\t\t-s [sshhost:]port -l [sslhost:]port [-v]\n\n" \ | |
56 | +"\t\t-s [sshhost:]port -l [sslhost:]port [-P pidfile] [-v] [-V]\n\n" \ | |
58 | 57 | "-v: verbose\n" \ |
58 | +"-V: version\n" \ | |
59 | 59 | "-p: address and port to listen on. default: 0.0.0.0:443\n" \ |
60 | 60 | "-s: SSH address: where to connect an SSH connection. default: localhost:22\n" \ |
61 | 61 | "-l: SSL address: where to connect an SSL connection.\n" \ |
62 | +"-P: PID file. Default: /var/run/sslh.pid\n" \ | |
62 | 63 | "" |
63 | 64 | |
64 | 65 | int verbose = 0; /* That's really quite global */ |
65 | 66 | |
@@ -187,9 +188,9 @@ | ||
187 | 188 | hint.ai_socktype = SOCK_STREAM; |
188 | 189 | |
189 | 190 | res = getaddrinfo(host, serv, &hint, &addr); |
190 | 191 | if (res) { |
191 | - fprintf(stderr, "%s\n", gai_strerror(res)); | |
192 | + fprintf(stderr, "%s `%s'\n", gai_strerror(res), fullname); | |
192 | 193 | if (res == EAI_SERVICE) |
193 | 194 | fprintf(stderr, "(Check you have specified all ports)\n"); |
194 | 195 | exit(1); |
195 | 196 | } |
@@ -305,28 +306,34 @@ | ||
305 | 306 | |
306 | 307 | exit(0); |
307 | 308 | } |
308 | 309 | |
309 | -/* SIGCHLD handling: | |
310 | - * we need to reap our children | |
311 | - */ | |
312 | -void child_handler(int signo) | |
313 | -{ | |
314 | - signal(SIGCHLD, &child_handler); | |
315 | - wait(NULL); | |
316 | -} | |
317 | 310 | void setup_signals(void) |
318 | 311 | { |
319 | - void* res; | |
312 | + int res; | |
313 | + struct sigaction action; | |
320 | 314 | |
321 | - res = signal(SIGCHLD, &child_handler); | |
322 | - if (res == SIG_ERR) { | |
323 | - perror("signal"); | |
324 | - exit(1); | |
325 | - } | |
315 | + /* Request no SIGCHLD is sent upon termination of | |
316 | + * the children */ | |
317 | + memset(&action, 0, sizeof(action)); | |
318 | + action.sa_handler = NULL; | |
319 | + action.sa_flags = SA_NOCLDWAIT; | |
320 | + res = sigaction(SIGCHLD, &action, NULL); | |
321 | + CHECK_RES_DIE(res, "sigaction"); | |
326 | 322 | } |
327 | 323 | |
324 | +/* Open syslog connection with appropriate banner; | |
325 | + * banner is made up of basename(bin_name)+"[pid]" */ | |
326 | +void setup_syslog(char* bin_name) { | |
327 | + char *name1, *name2; | |
328 | 328 | |
329 | + name1 = strdup(bin_name); | |
330 | + asprintf(&name2, "%s[%d]", basename(name1), getpid()); | |
331 | + openlog(name2, LOG_CONS, LOG_AUTH); | |
332 | + free(name1); | |
333 | + /* Don't free name2, as openlog(3) uses it (at least in glibc) */ | |
334 | +} | |
335 | + | |
329 | 336 | /* We don't want to run as root -- drop priviledges if required */ |
330 | 337 | void drop_privileges(char* user_name) |
331 | 338 | { |
332 | 339 | int res; |
@@ -344,16 +351,12 @@ | ||
344 | 351 | CHECK_RES_DIE(res, "setuid"); |
345 | 352 | } |
346 | 353 | |
347 | 354 | /* Writes my PID if $PIDFILE is defined */ |
348 | -void write_pid_file(void) | |
355 | +void write_pid_file(char* pidfile) | |
349 | 356 | { |
350 | - char *pidfile = getenv("PIDFILE"); | |
351 | 357 | FILE *f; |
352 | 358 | |
353 | - if (!pidfile) | |
354 | - return; | |
355 | - | |
356 | 359 | f = fopen(pidfile, "w"); |
357 | 360 | if (!f) { |
358 | 361 | perror(pidfile); |
359 | 362 | exit(1); |
@@ -390,14 +393,15 @@ | ||
390 | 393 | char *user_name = "nobody"; |
391 | 394 | char listen_str[] = "0.0.0.0:443"; |
392 | 395 | char ssl_str[] = "localhost:442"; |
393 | 396 | char ssh_str[] = "localhost:22"; |
397 | + char *pid_file = "/var/run/sslh.pid"; | |
394 | 398 | |
395 | 399 | resolve_name(&addr_listen, listen_str); |
396 | 400 | resolve_name(&addr_ssl, ssl_str); |
397 | 401 | resolve_name(&addr_ssh, ssh_str); |
398 | 402 | |
399 | - while ((c = getopt(argc, argv, "t:l:s:p:vu:")) != EOF) { | |
403 | + while ((c = getopt(argc, argv, "t:l:s:p:P:vVu:")) != EOF) { | |
400 | 404 | switch (c) { |
401 | 405 | |
402 | 406 | case 't': |
403 | 407 | timeout = atoi(optarg); |
@@ -418,12 +422,20 @@ | ||
418 | 422 | case 'v': |
419 | 423 | verbose += 1; |
420 | 424 | break; |
421 | 425 | |
426 | + case 'V': | |
427 | + printf("sslh %s\n", VERSION); | |
428 | + exit(0); | |
429 | + | |
422 | 430 | case 'u': |
423 | 431 | user_name = optarg; |
424 | 432 | break; |
425 | 433 | |
434 | + case 'P': | |
435 | + pid_file = optarg; | |
436 | + break; | |
437 | + | |
426 | 438 | default: |
427 | 439 | fprintf(stderr, USAGE_STRING); |
428 | 440 | exit(2); |
429 | 441 | } |
@@ -437,18 +449,18 @@ | ||
437 | 449 | listen_socket = start_listen_socket(&addr_listen); |
438 | 450 | |
439 | 451 | if (fork() > 0) exit(0); /* Detach */ |
440 | 452 | |
441 | - write_pid_file(); | |
453 | + write_pid_file(pid_file); | |
442 | 454 | |
443 | 455 | drop_privileges(user_name); |
444 | 456 | |
445 | 457 | /* New session -- become group leader */ |
446 | 458 | res = setsid(); |
447 | 459 | CHECK_RES_DIE(res, "setsid: already process leader"); |
448 | 460 | |
449 | 461 | /* Open syslog connection */ |
450 | - openlog(argv[0], LOG_CONS, LOG_AUTH); | |
462 | + setup_syslog(argv[0]); | |
451 | 463 | |
452 | 464 | /* Main server loop: accept connections, find what they are, fork shovelers */ |
453 | 465 | while (1) |
454 | 466 | { |
sslh.pod | ||
---|---|---|
@@ -1,0 +1,128 @@ | ||
1 | +# I'm just not gonna write troff :-) | |
2 | + | |
3 | +=head1 NAME | |
4 | + | |
5 | + sslh - ssl/ssh multiplexer | |
6 | + | |
7 | +=head1 SYNOPSIS | |
8 | + | |
9 | +sslh [ B<-t> I<num> ] [B<-p> I<listening address>] [B<-l> I<target address for SSL>] [B<-s> I<target address for SSH>] [B<-u> I<username>] [B<-P> I<pidfile>] [-v] [-V] | |
10 | + | |
11 | +=head1 DESCRIPTION | |
12 | + | |
13 | +B<sslh> lets one accept both HTTPS and SSH connections on | |
14 | +the same port. It makes it possible to connect to an SSH | |
15 | +server on port 443 (e.g. from inside a corporate firewall, | |
16 | +which almost never block port 443) while still serving HTTPS | |
17 | +on that port. | |
18 | + | |
19 | +The idea is to have B<sslh> listen to the external 443 port, | |
20 | +accept the incoming connections, work out what type of | |
21 | +connection it is, and then fordward to the appropriate | |
22 | +server. | |
23 | + | |
24 | +=head2 Protocol detection | |
25 | + | |
26 | +The protocol detection is made based on a small difference | |
27 | +between SSL and SSH: an SSL client connecting to a server | |
28 | +speaks first, whereas an SSH client expects the SSH server | |
29 | +to speak first (announcing itself with a banner). B<sslh> | |
30 | +waits for some time for the incoming connection to send data. | |
31 | +If it does before the timeout occurs, it is supposed to be | |
32 | +an SSL connection. Otherwise, it is supposed to be an SSH | |
33 | +connection. | |
34 | + | |
35 | +=head2 Libwrap support | |
36 | + | |
37 | +One drawback of B<sslh> is that the B<ssh> and B<httpd> | |
38 | +servers do not see the original IP address of the client | |
39 | +anymore, as the connection is forwarded through B<sslh>. | |
40 | +B<sslh> provides enough logging to circumvent that problem. | |
41 | +However it is common to limit access to B<ssh> using | |
42 | +B<libwrap> or B<tcpd>. For this reason, B<sslh> can be | |
43 | +compiled to check SSH accesses against SSH access lists as | |
44 | +defined in F</etc/hosts.allow> and F</etc/hosts.deny>. | |
45 | + | |
46 | +=head1 OPTIONS | |
47 | + | |
48 | +=over 4 | |
49 | + | |
50 | +=item B<-t> I<num> | |
51 | + | |
52 | +Timeout before a connection is considered to be SSH. Default | |
53 | +is 2s. | |
54 | + | |
55 | +=item B<-p> I<listening address> | |
56 | + | |
57 | +Interface and port on which to listen, e.g. I<foobar:443>, | |
58 | +where I<foobar> is the name of an interface (typically the | |
59 | +IP address on which the Internet connection ends up). | |
60 | + | |
61 | +Defaults to I<0.0.0.0:443> (listen to port 443 on all | |
62 | +available interfaces). | |
63 | + | |
64 | +=item B<-l> I<target address for SSL> | |
65 | + | |
66 | +Interface and port on which to forward SSL connection, | |
67 | +typically I<localhost:443>. | |
68 | + | |
69 | +Defaults to I<localhost:442> (this assumes you would | |
70 | +configure your B<httpd> process to listen to port 443). | |
71 | + | |
72 | +Note that you can set B<sslh> to listen on I<ext_ip:443> and | |
73 | +B<httpd> to listen on I<localhost:443>: this allows clients | |
74 | +inside your network to just connect directly to B<httpd>. | |
75 | + | |
76 | +=item B<-s> I<target address for SSH> | |
77 | + | |
78 | +Interface and port on which to forward SSH connection, | |
79 | +defaults to I<localhost:22>. | |
80 | + | |
81 | +=item B<-v> | |
82 | + | |
83 | +Increase verboseness. | |
84 | + | |
85 | +=item B<-V> | |
86 | + | |
87 | +Prints B<sslh> version. | |
88 | + | |
89 | +=item B<-u> I<username> | |
90 | + | |
91 | +Requires to run under the specified username. Defaults to | |
92 | +I<nobody> (which is not perfect -- ideally B<sslh> should | |
93 | +run under its own UID). | |
94 | + | |
95 | +=item B<-P> I<pidfile> | |
96 | + | |
97 | +Specifies the file in which to write the PID of the main | |
98 | +server. Defaults to I</var/run/sslh.pid>. | |
99 | + | |
100 | +=back | |
101 | + | |
102 | +=head1 FILES | |
103 | + | |
104 | +=over 4 | |
105 | + | |
106 | +=item F</etc/init.d/sslh> | |
107 | + | |
108 | +Start-up script. The standard actions B<start>, B<stop> and | |
109 | +B<restart> are supported. | |
110 | + | |
111 | +=item F</etc/default/sslh> | |
112 | + | |
113 | +Server configuration. These are environement variables | |
114 | +loaded by the start-up script and passed to B<sslh> as | |
115 | +command-line arguments. Refer to the OPTIONS section for a | |
116 | +detailed explanation of the variables used by B<sslh>. | |
117 | + | |
118 | +=back | |
119 | + | |
120 | +=head1 SEE ALSO | |
121 | + | |
122 | +Last version available from | |
123 | +L<http://www.rutschle.net/tech/sslh>, and can be tracked | |
124 | +from L<http://freshmeat.net/projects/sslh/>. | |
125 | + | |
126 | +=head1 AUTHOR | |
127 | + | |
128 | +Written by Yves Rutschle |
Built with git-ssb-web