1
0
mirror of https://github.com/moparisthebest/sslh synced 2024-11-21 08:35:01 -05:00

v1.11: 21APR2012

WARNING: defaults have been removed for --user and
	--pidfile options, update your start-up scripts!

	No longer stop sslh when reverse DNS requests fail
	for logging.

	Added HTTP probe.

	No longer create new session if running in
	foreground.

	No longer default to changing user to 'nobody'. If
	--user isn't specified, just run as current user.

	No longer create PID file by default, it should be
	explicitely set with --pidfile.

	No longer log to syslog if in foreground. Logs are
	instead output to stderr.

	The four changes above make it straightforward to
	integrate sslh with systemd, and should help with
	launchd.
This commit is contained in:
Yves Rutschle 2013-07-10 23:14:48 +02:00
parent ae008179f0
commit 26b4bcd089
10 changed files with 103 additions and 44 deletions

View File

@ -1,4 +1,29 @@
v1.10: v1.11: 21APR2012
WARNING: defaults have been removed for --user and
--pidfile options, update your start-up scripts!
No longer stop sslh when reverse DNS requests fail
for logging.
Added HTTP probe.
No longer create new session if running in
foreground.
No longer default to changing user to 'nobody'. If
--user isn't specified, just run as current user.
No longer create PID file by default, it should be
explicitely set with --pidfile.
No longer log to syslog if in foreground. Logs are
instead output to stderr.
The four changes above make it straightforward to
integrate sslh with systemd, and should help with
launchd.
v1.10: 27NOV2011
Fixed calls referring to sockaddr length so they work Fixed calls referring to sockaddr length so they work
with FreeBSD. with FreeBSD.

View File

@ -1,6 +1,6 @@
# Configuration # Configuration
VERSION="v1.10" VERSION="v1.11"
USELIBWRAP= # Use libwrap? USELIBWRAP= # Use libwrap?
COV_TEST= # Perform test coverage? COV_TEST= # Perform test coverage?
PREFIX=/usr/local PREFIX=/usr/local

10
README
View File

@ -1,10 +1,10 @@
===== sslh -- A ssl/ssh multiplexer. ===== ===== sslh -- A ssl/ssh multiplexer. =====
sslh accepts HTTPS, SSH, OpenVPN, tinc and XMPP connections sslh accepts HTTP, HTTPS, SSH, OpenVPN, tinc and XMPP
on the same port. This makes it possible to connect to any connections on the same port. This makes it possible to
of these servers on port 443 (e.g. from inside a corporate connect to any of these servers on port 443 (e.g. from
firewall, which almost never block port 443) while still inside a corporate firewall, which almost never block port
serving HTTPS on that port. 443) while still serving HTTPS on that port.
==== Compile and install ==== ==== Compile and install ====

View File

@ -35,6 +35,7 @@ int is_ssh_protocol(const char *p, int len);
int is_openvpn_protocol(const char *p, int len); int is_openvpn_protocol(const char *p, int len);
int is_tinc_protocol(const char *p, int len); int is_tinc_protocol(const char *p, int len);
int is_xmpp_protocol(const char *p, int len); int is_xmpp_protocol(const char *p, int len);
int is_http_protocol(const char *p, int len);
int is_true(const char *p, int len) { return 1; } int is_true(const char *p, int len) { return 1; }
/* Table of all the protocols we know how to connect to. /* Table of all the protocols we know how to connect to.
@ -51,6 +52,7 @@ struct proto protocols[] = {
{ 0, "openvpn", NULL, {0}, is_openvpn_protocol }, { 0, "openvpn", NULL, {0}, is_openvpn_protocol },
{ 0, "tinc", NULL, {0}, is_tinc_protocol }, { 0, "tinc", NULL, {0}, is_tinc_protocol },
{ 0, "xmpp", NULL, {0}, is_xmpp_protocol }, { 0, "xmpp", NULL, {0}, is_xmpp_protocol },
{ 0, "http", NULL, {0}, is_http_protocol },
/* probe for SSL always successes: it's the default, and must be tried last /* probe for SSL always successes: it's the default, and must be tried last
**/ **/
{ 0, "ssl", NULL, {0}, is_true } { 0, "ssl", NULL, {0}, is_true }
@ -338,6 +340,32 @@ int is_xmpp_protocol( const char *p, int len)
return strstr(p, "jabber") ? 1 : 0; return strstr(p, "jabber") ? 1 : 0;
} }
int probe_http_method(const char *p, const char *opt)
{
return !strncmp(p, opt, strlen(opt)-1);
}
/* Is the buffer the beginnin of an HTTP connection? */
int is_http_protocol(const char *p, int len)
{
/* If it's got HTTP in the request (HTTP/1.1) then it's HTTP */
if (strstr(p, "HTTP"))
return 1;
/* Otherwise it could be HTTP/1.0 without version: check if it's got an
* HTTP method (RFC2616 5.1.1) */
probe_http_method(p, "OPTIONS");
probe_http_method(p, "GET");
probe_http_method(p, "HEAD");
probe_http_method(p, "POST");
probe_http_method(p, "PUT");
probe_http_method(p, "DELETE");
probe_http_method(p, "TRACE");
probe_http_method(p, "CONNECT");
return 0;
}
/* /*
* Read the beginning of data coming from the client connection and check if * Read the beginning of data coming from the client connection and check if
@ -392,8 +420,18 @@ char* sprintaddr(char* buf, size_t size, struct addrinfo *a)
numeric ? NI_NUMERICHOST | NI_NUMERICSERV : 0 ); numeric ? NI_NUMERICHOST | NI_NUMERICSERV : 0 );
if (res) { if (res) {
fprintf(stderr, "sprintaddr:getnameinfo: %s\n", gai_strerror(res)); log_message(LOG_ERR, "sprintaddr:getnameinfo: %s\n", gai_strerror(res));
exit(1); /* Name resolution failed: do it numerically instead */
res = getnameinfo(a->ai_addr, a->ai_addrlen,
host, sizeof(host),
serv, sizeof(serv),
NI_NUMERICHOST | NI_NUMERICSERV);
/* should not fail but... */
if (res) {
log_message(LOG_ERR, "sprintaddr:getnameinfo(NUM): %s\n", gai_strerror(res));
strcpy(host, "?");
strcpy(serv, "?");
}
} }
snprintf(buf, size, "%s:%s", host, serv); snprintf(buf, size, "%s:%s", host, serv);
@ -436,18 +474,16 @@ void resolve_name(struct addrinfo **out, char* fullname)
} }
} }
/* Log to syslog, and to stderr if foreground */ /* Log to syslog or stderr if foreground */
void log_message(int type, char* msg, ...) void log_message(int type, char* msg, ...)
{ {
va_list ap; va_list ap;
va_start(ap, msg);
vsyslog(type, msg, ap);
va_end(ap);
va_start(ap, msg); va_start(ap, msg);
if (foreground) if (foreground)
vfprintf(stderr, msg, ap); vfprintf(stderr, msg, ap);
else
vsyslog(type, msg, ap);
va_end(ap); va_end(ap);
} }

View File

@ -1,3 +1,5 @@
LISTEN=ifname:443 LISTEN=ifname:443
SSH=localhost:22 SSH=localhost:22
SSL=localhost:443 SSL=localhost:443
USER=nobody
PID=/var/run/sslh.pid

View File

@ -13,11 +13,6 @@ facility=user.info
# /etc/init.d/sslh: start and stop the sslh proxy daemon # /etc/init.d/sslh: start and stop the sslh proxy daemon
# Defaults -- can be overridden in /etc/default/sslh
LISTEN=thelonious:443
SSH=localhost:22
SSL=localhost:443
if test -f /etc/default/sslh; then if test -f /etc/default/sslh; then
. /etc/default/sslh . /etc/default/sslh
fi fi
@ -30,7 +25,7 @@ DAEMON=$PREFIX/sbin/sslh
start() start()
{ {
echo "Start services: sslh" echo "Start services: sslh"
$DAEMON --user nobody --listen ${LISTEN} --ssh ${SSH} --ssl ${SSL} $DAEMON --user ${USER} --pidfile ${PID} --listen ${LISTEN} --ssh ${SSH} --ssl ${SSL}
logger -t ${tag} -p ${facility} -i 'Started sslh' logger -t ${tag} -p ${facility} -i 'Started sslh'
} }

View File

@ -20,7 +20,7 @@
SSLH="/usr/local/sbin/sslh" SSLH="/usr/local/sbin/sslh"
PIDFILE="/var/run/sslh" PIDFILE="/var/run/sslh"
OPTIONS="-p 0.0.0.0:8443 --ssl 127.0.0.1:443 --ssh 127.0.0.1:22" OPTIONS="--user nobody --pidfile $PIDFILE -p 0.0.0.0:8443 --ssl 127.0.0.1:443 --ssh 127.0.0.1:22"
if [ -f /etc/sysconfig/sslh ]; then if [ -f /etc/sysconfig/sslh ]; then
. /etc/sysconfig/sslh . /etc/sysconfig/sslh

View File

@ -138,6 +138,7 @@ void main_loop(int listen_sockets[], int num_addr_listen)
int in_socket, i, res; int in_socket, i, res;
struct sigaction action; struct sigaction action;
listener_pid_number = num_addr_listen;
listener_pid = malloc(listener_pid_number * sizeof(listener_pid[0])); listener_pid = malloc(listener_pid_number * sizeof(listener_pid[0]));
/* Start one process for each listening address */ /* Start one process for each listening address */
@ -170,7 +171,6 @@ void main_loop(int listen_sockets[], int num_addr_listen)
res = sigaction(SIGTERM, &action, NULL); res = sigaction(SIGTERM, &action, NULL);
CHECK_RES_DIE(res, "sigaction"); CHECK_RES_DIE(res, "sigaction");
listener_pid_number = num_addr_listen;
wait(NULL); wait(NULL);
} }

View File

@ -154,8 +154,8 @@ int main(int argc, char *argv[])
int *listen_sockets; int *listen_sockets;
/* Init defaults */ /* Init defaults */
pid_file = "/var/run/sslh.pid"; pid_file = NULL;
user_name = "nobody"; user_name = NULL;
foreground = 0; foreground = 0;
parse_cmdline(argc, argv); parse_cmdline(argc, argv);
@ -172,20 +172,23 @@ int main(int argc, char *argv[])
num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen); num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen);
if (!foreground) if (!foreground) {
if (fork() > 0) exit(0); /* Detach */ if (fork() > 0) exit(0); /* Detach */
/* New session -- become group leader */
if (getuid() == 0) {
res = setsid();
CHECK_RES_DIE(res, "setsid: already process leader");
}
}
setup_signals(); setup_signals();
drop_privileges(user_name); if (user_name)
drop_privileges(user_name);
/* New session -- become group leader */ if (pid_file)
if (getuid() == 0) { write_pid_file(pid_file);
res = setsid();
CHECK_RES_DIE(res, "setsid: already process leader");
}
write_pid_file(pid_file);
/* Open syslog connection */ /* Open syslog connection */
setup_syslog(argv[0]); setup_syslog(argv[0]);

View File

@ -6,15 +6,15 @@
=head1 SYNOPSIS =head1 SYNOPSIS
sslh [ B<-t> I<num> ] [B<-p> I<listening address> [B<-p> I<listening address> ...] [B<--ssl> I<target address for SSL>] [B<--ssh> I<target address for SSH>] [B<--openvpn> I<target address for OpenVPN>] [B<-u> I<username>] [B<-P> I<pidfile>] [-v] [-i] [-V] [-f] [-n] sslh [ B<-t> I<num> ] [B<-p> I<listening address> [B<-p> I<listening address> ...] [B<--ssl> I<target address for SSL>] [B<--ssh> I<target address for SSH>] [B<--openvpn> I<target address for OpenVPN>] [B<--http> I<target address for HTTP>] [B<-u> I<username>] [B<-P> I<pidfile>] [-v] [-i] [-V] [-f] [-n]
=head1 DESCRIPTION =head1 DESCRIPTION
B<sslh> accepts HTTPS, SSH, OpenVPN, tinc and XMPP connections B<sslh> accepts HTTP, HTTPS, SSH, OpenVPN, tinc and XMPP
on the same port. This makes it possible to connect to any connections on the same port. This makes it possible to
of these servers on port 443 (e.g. from inside a corporate connect to any of these servers on port 443 (e.g. from
firewall, which almost never block port 443) while still inside a corporate firewall, which almost never block port
serving HTTPS on that port. 443) while still serving HTTPS on that port.
The idea is to have B<sslh> listen to the external 443 port, The idea is to have B<sslh> listen to the external 443 port,
@ -123,14 +123,12 @@ Prints B<sslh> version.
=item B<-u> I<username>, B<--user> I<username> =item B<-u> I<username>, B<--user> I<username>
Requires to run under the specified username. Defaults to Requires to run under the specified username.
I<nobody> (which is not perfect -- ideally B<sslh> should
run under its own UID).
=item B<-P> I<pidfile>, B<--pid-file> I<pidfile> =item B<-P> I<pidfile>, B<--pid-file> I<pidfile>
Specifies the file in which to write the PID of the main Specifies a file in which to write the PID of the main
server. Defaults to I</var/run/sslh.pid>. server.
=item B<-i>, B<--inetd> =item B<-i>, B<--inetd>