v1.5: 10DEC2008

Fixed zombie generation.
        Added support scripts (), Makefile.
        Changed all 'connexions' to 'connections' to please
        pesky users. Damn users.
This commit is contained in:
Yves Rutschle 2013-07-10 23:09:40 +02:00
parent 3386a64a4d
commit b965d735b8
5 changed files with 218 additions and 42 deletions

23
Makefile Normal file
View File

@ -0,0 +1,23 @@
# Configuration
USELIBWRAP=1 # Use libwrap?
# End of configuration -- the rest should take care of
# itself
CC = gcc
#LIBS=-lnet
LIBS=
ifneq ($(strip $(USELIBWRAP)),)
LIBS:=$(LIBS) -lwrap
CFLAGS=-DLIBWRAP
endif
all:
$(CC) $(CFLAGS) -o sslh sslh.c $(LIBS)
strip sslh

83
README Normal file
View File

@ -0,0 +1,83 @@
sslh -- A ssl/ssh multiplexer.
sslh lets one accept both HTTPS and SSH connections on the
same port. It makes it possible to connect to an SSH server
on port 443 (e.g. from inside a corporate firewall) while
still serving HTTPS on that port.
Compilation instructions:
Solaris:
cc -o sslh sslh.c -lresolv -lsocket -lnsl
LynxOS:
gcc -o tcproxy tcproxy.c -lnetinet
Linux:
cc -o sslh sslh.c -lnet
or:
cc -o sslh sslh.c
To compile with libwrap support:
cc -o sslh -DLIBWRAP sslh.c -lwrap
To install:
make
cp sslh /usr/local/sbin
cp scripts/etc.init.d.sslh /etc/init.d/sslh
cp scripts/etc.default.sslh /etc/default/sslh
You can edit settings in /etc/default/sslh:
PIDFILE=/var/run/sslh.pid
LISTEN=ifname:443
SSH=localhost:22
SSL=localhost:443
A good scheme is to use the external name of the machine in
$LISTEN, and bind httpd to localhost:443: that way, https
connections coming from inside your network don't need to go
through sslh, and sslh is only there as a frontal for
connections coming from the internet.
Sslh can optionnaly perform libwrap checks for the sshd
service: because the connection to sshd will be coming
locally from sslh, sshd cannot determine the IP of the
client.
Comments? questions? sslh@rutschle.net
HISTORY
v1.5: 10DEC2008
Fixed zombie generation.
Added support scripts (), Makefile.
Changed all 'connexions' to 'connections' to please
pesky users. Damn users.
v1.4: 13JUL2008
Added libwrap support for ssh service (Christian Weinberger)
Only SSH is libwraped, not SSL.
v1.3: 14MAY2008
Added parsing for local interface to listen on
Changed default SSL connection to port 442 (443 doesn't make
sense as a default as we're already listening on 443)
Syslog incoming connections
v1.2: 12MAY2008
Fixed compilation warning for AMD64 (Thx Daniel Lange)
v1.1: 21MAY2007
Making sslhc more like a real daemon:
* If $PIDFILE is defined, write first PID to it upon startup
* Fork at startup (detach from terminal)
(thanks to http://www.enderunix.org/docs/eng/daemon.php -- good checklist)
* Less memory usage (?)
v1.0:
* Basic functionality: privilege dropping, target hostnames and ports
configurable.

4
scripts/etc.default.sslh Executable file
View File

@ -0,0 +1,4 @@
PIDFILE=/var/run/sslh.pid
LISTEN=ifname:443
SSH=localhost:22
SSL=localhost:443

62
scripts/etc.init.d.sslh Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: sslh
# Default-Start: 2 3 4 5
# Default-Stop: 1
# Short-Description: sslh proxy ssl & ssh connections
### END INIT INFO
set -e
tag=sslh
facility=user.info
# /etc/init.d/sslh: start and stop the sslh proxy daemon
# Defaults -- can be overridden in /etc/default/sslh
PIDFILE=/var/run/sslh.pid
LISTEN=thelonious:443
SSH=localhost:22
SSL=localhost:443
if test -f /etc/default/sslh; then
. /etc/default/sslh
export PIDFILE=${PIDFILE}
fi
DAEMON=/usr/local/sbin/sslh
start()
{
echo "Start services: sslh"
$DAEMON -u nobody -p ${LISTEN} -s ${SSH} -l ${SSL}
logger -t ${tag} -p ${facility} -i 'Started sslh'
}
stop()
{
echo "Stop services: sslh"
killall $DAEMON
rm ${PIDFILE}
logger -t ${tag} -p ${facility} -i 'Stopped sslh'
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 5
start
;;
*)
echo "Usage: /etc/init.d/sslh {start|stop|restart}" >&2
;;
esac
exit 0

88
sslh.c
View File

@ -18,44 +18,9 @@
# The full text for the General Public License is here:
# http://www.gnu.org/licenses/gpl.html
Comments? questions? sslh@rutschle.net
Compilation instructions:
Solaris:
cc -o sslh sslh.c -lresolv -lsocket -lnsl
LynxOS:
gcc -o tcproxy tcproxy.c -lnetinet
Linux:
cc -o sslh sslh.c -lnet
HISTORY
v1.3: 14MAY2008
Added parsing for local interface to listen on
Changed default SSL connexion to port 442 (443 doesn't make
sense as a default as we're already listening on 443)
Syslog incoming connexions
v1.2: 12MAY2008
Fixed compilation warning for AMD64 (Thx Daniel Lange)
v1.1: 21MAY2007
Making sslhc more like a real daemon:
* If $PIDFILE is defined, write first PID to it upon startup
* Fork at startup (detach from terminal)
(thanks to http://www.enderunix.org/docs/eng/daemon.php -- good checklist)
* Less memory usage (?)
v1.0:
* Basic functionality: privilege dropping, target hostnames and ports
configurable.
*/
#define VERSION "1.3"
#define VERSION "1.5"
#include <sys/types.h>
#include <fcntl.h>
@ -72,6 +37,12 @@ v1.0:
#include <pwd.h>
#include <syslog.h>
#ifdef LIBWRAP
#include <tcpd.h>
int allow_severity =0, deny_severity = 0;
#endif
#define CHECK_RES_DIE(res, str) \
if (res == -1) { \
perror(str); \
@ -86,8 +57,8 @@ if (res == -1) { \
"\t\t-s [sshhost:]port -l [sslhost:]port [-v]\n\n" \
"-v: verbose\n" \
"-p: address and port to listen on. default: 0.0.0.0:443\n" \
"-s: SSH address: where to connect an SSH connexion. default: localhost:22\n" \
"-l: SSL address: where to connect an SSL connexion.\n" \
"-s: SSH address: where to connect an SSH connection. default: localhost:22\n" \
"-l: SSL address: where to connect an SSL connection.\n" \
""
int verbose = 0; /* That's really quite global */
@ -227,7 +198,7 @@ void resolve_name(struct sockaddr *sock, char* fullname) {
}
/* syslogs who connected to where */
void log_connexion(int socket, char* target)
void log_connection(int socket, char* target)
{
struct sockaddr peeraddr;
socklen_t size = sizeof(peeraddr);
@ -237,7 +208,7 @@ void log_connexion(int socket, char* target)
res = getpeername(socket, &peeraddr, &size);
CHECK_RES_DIE(res, "getpeername");
syslog(LOG_INFO, "connexion from %s forwarded to %s\n",
syslog(LOG_INFO, "connection from %s forwarded to %s\n",
sprintaddr(buf, sizeof(buf), &peeraddr), target);
}
@ -251,6 +222,36 @@ int timeout = 2;
struct sockaddr addr_listen;
struct sockaddr addr_ssl, addr_ssh;
/* libwrap (tcpd): check the ssh connection is legal. This is necessary because
* the actual sshd will only see a connection coming from localhost and can't
* apply the rules itself.
*/
void check_access_rights(int in_socket)
{
#ifdef LIBWRAP
struct sockaddr peeraddr;
socklen_t size = sizeof(peeraddr);
char addr_str[1024];
struct hostent *host;
struct in_addr addr;
int res;
res = getpeername(in_socket, &peeraddr, &size);
CHECK_RES_DIE(res, "getpeername");
inet_ntop(AF_INET, &((struct sockaddr_in*)&peeraddr)->sin_addr, addr_str, sizeof(addr_str));
addr.s_addr = inet_addr(addr_str);
host = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
if (!hosts_ctl("sshd", (host ? host->h_name : STRING_UNKNOWN), addr_str, STRING_UNKNOWN)) {
if (verbose)
fprintf(stderr, "access denied\n");
log_connection(in_socket, "access denied");
close(in_socket);
exit(0);
}
#endif
}
/* Child process that finds out what to connect to and proxies
*/
@ -280,9 +281,12 @@ void start_shoveler(int in_socket)
/* The client hasn't written anything and we timed out: connect to SSH */
saddr = &addr_ssh;
target = "SSH";
/* do hosts_access check if built with libwrap support */
check_access_rights(in_socket);
}
log_connexion(in_socket, target);
log_connection(in_socket, target);
/* Connect the target socket */
out_socket = socket(AF_INET, SOCK_STREAM, 0);
@ -442,7 +446,7 @@ int main(int argc, char *argv[])
res = setsid();
CHECK_RES_DIE(res, "setsid: already process leader");
/* Open syslog connexion */
/* Open syslog connection */
openlog(argv[0], LOG_CONS, LOG_AUTH);
/* Main server loop: accept connections, find what they are, fork shovelers */