wsproxy: multiprocess capable.

Add -m, --multiprocess option which forks a handler for each
connection allowing multiple connections to the same target using the
same proxy instance.

Cleaned up the output of the handler process. Each process' output is
prefixed with an ordinal value.

Changed both the C and python versions of the proxy.
This commit is contained in:
Joel Martin 2010-09-10 13:05:48 -05:00
parent 465faf19db
commit a0315ab1dc
5 changed files with 172 additions and 69 deletions

View File

@ -39,13 +39,16 @@ const char policy_response[] = "<cross-domain-policy><allow-access-from domain=\
* Warning: not thread safe * Warning: not thread safe
*/ */
int ssl_initialized = 0; int ssl_initialized = 0;
int pipe_error = 0;
char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp; char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
unsigned int bufsize, dbufsize; unsigned int bufsize, dbufsize;
settings_t settings; settings_t settings;
void traffic(char * token) { void traffic(char * token) {
fprintf(stdout, "%s", token); if ((! settings.daemon) && (! settings.multiprocess)) {
fflush(stdout); fprintf(stdout, "%s", token);
fflush(stdout);
}
} }
void error(char *msg) void error(char *msg)
@ -89,7 +92,7 @@ int resolve_host(struct in_addr *sin_addr, const char *hostname)
ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len) { ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len) {
if (ctx->ssl) { if (ctx->ssl) {
//printf("SSL recv\n"); //handler_msg("SSL recv\n");
return SSL_read(ctx->ssl, buf, len); return SSL_read(ctx->ssl, buf, len);
} else { } else {
return recv(ctx->sockfd, buf, len, 0); return recv(ctx->sockfd, buf, len, 0);
@ -98,7 +101,7 @@ ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len) {
ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len) { ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len) {
if (ctx->ssl) { if (ctx->ssl) {
//printf("SSL send\n"); //handler_msg("SSL send\n");
return SSL_write(ctx->ssl, buf, len); return SSL_write(ctx->ssl, buf, len);
} else { } else {
return send(ctx->sockfd, buf, len, 0); return send(ctx->sockfd, buf, len, 0);
@ -202,7 +205,7 @@ int decode(char *src, size_t srclength, u_char *target, size_t targsize) {
int i, len, framecount = 0, retlen = 0; int i, len, framecount = 0, retlen = 0;
unsigned char chr; unsigned char chr;
if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) { if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) {
fprintf(stderr, "WebSocket framing error\n"); handler_emsg("WebSocket framing error\n");
return -1; return -1;
} }
start = src+1; // Skip '\x00' start start = src+1; // Skip '\x00' start
@ -337,13 +340,13 @@ ws_ctx_t *do_handshake(int sock) {
len = recv(sock, handshake, 1024, MSG_PEEK); len = recv(sock, handshake, 1024, MSG_PEEK);
handshake[len] = 0; handshake[len] = 0;
if (len == 0) { if (len == 0) {
printf("Ignoring empty handshake\n"); handler_msg("ignoring empty handshake\n");
close(sock); close(sock);
return NULL; return NULL;
} else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) { } else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) {
len = recv(sock, handshake, 1024, 0); len = recv(sock, handshake, 1024, 0);
handshake[len] = 0; handshake[len] = 0;
printf("Sending flash policy response\n"); handler_msg("sending flash policy response\n");
send(sock, policy_response, sizeof(policy_response), 0); send(sock, policy_response, sizeof(policy_response), 0);
close(sock); close(sock);
return NULL; return NULL;
@ -353,22 +356,22 @@ ws_ctx_t *do_handshake(int sock) {
ws_ctx = ws_socket_ssl(sock, settings.cert); ws_ctx = ws_socket_ssl(sock, settings.cert);
if (! ws_ctx) { return NULL; } if (! ws_ctx) { return NULL; }
scheme = "wss"; scheme = "wss";
printf(" using SSL socket\n"); handler_msg("using SSL socket\n");
} else if (settings.ssl_only) { } else if (settings.ssl_only) {
printf("Non-SSL connection disallowed\n"); handler_msg("non-SSL connection disallowed\n");
close(sock); close(sock);
return NULL; return NULL;
} else { } else {
ws_ctx = ws_socket(sock); ws_ctx = ws_socket(sock);
if (! ws_ctx) { return NULL; } if (! ws_ctx) { return NULL; }
scheme = "ws"; scheme = "ws";
printf(" using plain (not SSL) socket\n"); handler_msg("using plain (not SSL) socket\n");
} }
len = ws_recv(ws_ctx, handshake, 4096); len = ws_recv(ws_ctx, handshake, 4096);
handshake[len] = 0; handshake[len] = 0;
if (!parse_handshake(handshake, &headers)) { if (!parse_handshake(handshake, &headers)) {
fprintf(stderr, "Invalid WS request\n"); handler_emsg("Invalid WS request\n");
close(sock); close(sock);
return NULL; return NULL;
} }
@ -376,16 +379,16 @@ ws_ctx_t *do_handshake(int sock) {
if (headers.key3[0] != '\0') { if (headers.key3[0] != '\0') {
gen_md5(&headers, trailer); gen_md5(&headers, trailer);
pre = "Sec-"; pre = "Sec-";
printf(" using protocol version 76\n"); handler_msg("using protocol version 76\n");
} else { } else {
trailer[0] = '\0'; trailer[0] = '\0';
pre = ""; pre = "";
printf(" using protocol version 75\n"); handler_msg("using protocol version 75\n");
} }
sprintf(response, server_handshake, pre, headers.origin, pre, scheme, sprintf(response, server_handshake, pre, headers.origin, pre, scheme,
headers.host, headers.path, pre, trailer); headers.host, headers.path, pre, trailer);
//printf("response: %s\n", response); //handler_msg("response: %s\n", response);
ws_send(ws_ctx, response, strlen(response)); ws_send(ws_ctx, response, strlen(response));
return ws_ctx; return ws_ctx;
@ -393,7 +396,8 @@ ws_ctx_t *do_handshake(int sock) {
void signal_handler(sig) { void signal_handler(sig) {
switch (sig) { switch (sig) {
case SIGHUP: break; // ignore case SIGHUP: break; // ignore for now
case SIGPIPE: pipe_error = 1; break; // handle inline
case SIGTERM: exit(0); break; case SIGTERM: exit(0); break;
} }
} }
@ -434,7 +438,7 @@ void daemonize(int keepfd) {
void start_server() { void start_server() {
int lsock, csock, clilen, sopt = 1, i; int lsock, csock, pid, clilen, sopt = 1, i;
struct sockaddr_in serv_addr, cli_addr; struct sockaddr_in serv_addr, cli_addr;
ws_ctx_t *ws_ctx; ws_ctx_t *ws_ctx;
@ -470,18 +474,26 @@ void start_server() {
} }
listen(lsock,100); listen(lsock,100);
signal(SIGPIPE, signal_handler); // catch pipe
if (settings.daemon) { if (settings.daemon) {
daemonize(lsock); daemonize(lsock);
} }
if (settings.multiprocess) {
printf("Waiting for connections on %s:%d\n",
settings.listen_host, settings.listen_port);
// Reep zombies
signal(SIGCHLD, SIG_IGN);
}
while (1) { while (1) {
clilen = sizeof(cli_addr); clilen = sizeof(cli_addr);
if (settings.listen_host && settings.listen_host[0] != '\0') { pipe_error = 0;
printf("waiting for connection on %s:%d\n", pid = 0;
if (! settings.multiprocess) {
printf("Waiting for connection on %s:%d\n",
settings.listen_host, settings.listen_port); settings.listen_host, settings.listen_port);
} else {
printf("waiting for connection on port %d\n",
settings.listen_port);
} }
csock = accept(lsock, csock = accept(lsock,
(struct sockaddr *) &cli_addr, (struct sockaddr *) &cli_addr,
@ -490,7 +502,8 @@ void start_server() {
error("ERROR on accept"); error("ERROR on accept");
continue; continue;
} }
printf("Got client connection from %s\n", inet_ntoa(cli_addr.sin_addr)); handler_msg("got client connection from %s\n",
inet_ntoa(cli_addr.sin_addr));
ws_ctx = do_handshake(csock); ws_ctx = do_handshake(csock);
if (ws_ctx == NULL) { if (ws_ctx == NULL) {
close(csock); close(csock);
@ -501,8 +514,24 @@ void start_server() {
* 20 for WS '\x00' / '\xff' and good measure */ * 20 for WS '\x00' / '\xff' and good measure */
dbufsize = (bufsize * 3)/4 - 20; dbufsize = (bufsize * 3)/4 - 20;
settings.handler(ws_ctx); if (settings.multiprocess) {
close(csock); handler_msg("forking handler process\n");
pid = fork();
}
if (pid == 0) { // handler process
settings.handler(ws_ctx);
if (pipe_error) {
handler_emsg("Closing due to SIGPIPE\n");
}
close(csock);
if (settings.multiprocess) {
handler_msg("handler exit\n");
break; // Child process exits
}
} else { // parent process
settings.handler_id += 1;
}
} }
} }

View File

@ -10,8 +10,10 @@ typedef struct {
char listen_host[256]; char listen_host[256];
int listen_port; int listen_port;
void (*handler)(ws_ctx_t*); void (*handler)(ws_ctx_t*);
int handler_id;
int ssl_only; int ssl_only;
int daemon; int daemon;
int multiprocess;
char *record; char *record;
char *cert; char *cert;
} settings_t; } settings_t;
@ -34,3 +36,16 @@ ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
//int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize); //int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
//int b64_pton(char const *src, u_char *target, size_t targsize); //int b64_pton(char const *src, u_char *target, size_t targsize);
#define gen_handler_msg(stream, ...) \
if (! settings.daemon) { \
if (settings.multiprocess) { \
fprintf(stream, " %d: ", settings.handler_id); \
} else { \
fprintf(stream, " "); \
} \
fprintf(stream, __VA_ARGS__); \
}
#define handler_msg(...) gen_handler_msg(stdout, __VA_ARGS__);
#define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__);

View File

@ -25,9 +25,11 @@ settings = {
'listen_host' : '', 'listen_host' : '',
'listen_port' : None, 'listen_port' : None,
'handler' : None, 'handler' : None,
'handler_id' : 1,
'cert' : None, 'cert' : None,
'ssl_only' : False, 'ssl_only' : False,
'daemon' : True, 'daemon' : True,
'multiprocess': False,
'record' : None, } 'record' : None, }
server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r
@ -41,9 +43,20 @@ Connection: Upgrade\r
policy_response = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\n""" policy_response = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>\n"""
class EClose(Exception):
pass
def traffic(token="."): def traffic(token="."):
sys.stdout.write(token) if not settings['daemon'] and not settings['multiprocess']:
sys.stdout.flush() sys.stdout.write(token)
sys.stdout.flush()
def handler_msg(msg):
if not settings['daemon']:
if settings['multiprocess']:
print " %d: %s" % (settings['handler_id'], msg)
else:
print " %s" % msg
def encode(buf): def encode(buf):
buf = b64encode(buf) buf = b64encode(buf)
@ -89,14 +102,14 @@ def do_handshake(sock):
# Peek, but don't read the data # Peek, but don't read the data
handshake = sock.recv(1024, socket.MSG_PEEK) handshake = sock.recv(1024, socket.MSG_PEEK)
#print "Handshake [%s]" % repr(handshake) #handler_msg("Handshake [%s]" % repr(handshake))
if handshake == "": if handshake == "":
print "Ignoring empty handshake" handler_msg("ignoring empty handshake")
sock.close() sock.close()
return False return False
elif handshake.startswith("<policy-file-request/>"): elif handshake.startswith("<policy-file-request/>"):
handshake = sock.recv(1024) handshake = sock.recv(1024)
print "Sending flash policy response" handler_msg("Sending flash policy response")
sock.send(policy_response) sock.send(policy_response)
sock.close() sock.close()
return False return False
@ -107,32 +120,32 @@ def do_handshake(sock):
certfile=settings['cert'], certfile=settings['cert'],
ssl_version=ssl.PROTOCOL_TLSv1) ssl_version=ssl.PROTOCOL_TLSv1)
scheme = "wss" scheme = "wss"
print " using SSL/TLS" handler_msg("using SSL/TLS")
elif settings['ssl_only']: elif settings['ssl_only']:
print "Non-SSL connection disallowed" handler_msg("non-SSL connection disallowed")
sock.close() sock.close()
return False return False
else: else:
retsock = sock retsock = sock
scheme = "ws" scheme = "ws"
print " using plain (not SSL) socket" handler_msg("using plain (not SSL) socket")
handshake = retsock.recv(4096) handshake = retsock.recv(4096)
#print "handshake: " + repr(handshake) #handler_msg("handshake: " + repr(handshake))
h = parse_handshake(handshake) h = parse_handshake(handshake)
if h.get('key3'): if h.get('key3'):
trailer = gen_md5(h) trailer = gen_md5(h)
pre = "Sec-" pre = "Sec-"
print " using protocol version 76" handler_msg("using protocol version 76")
else: else:
trailer = "" trailer = ""
pre = "" pre = ""
print " using protocol version 75" handler_msg("using protocol version 75")
response = server_handshake % (pre, h['Origin'], pre, scheme, response = server_handshake % (pre, h['Origin'], pre, scheme,
h['Host'], h['path'], pre, trailer) h['Host'], h['path'], pre, trailer)
#print "sending response:", repr(response) #handler_msg("sending response:", repr(response))
retsock.send(response) retsock.send(response)
return retsock return retsock
@ -177,21 +190,44 @@ def start_server():
lsock.bind((settings['listen_host'], settings['listen_port'])) lsock.bind((settings['listen_host'], settings['listen_port']))
lsock.listen(100) lsock.listen(100)
if settings['daemon']: daemonize(keepfd=lsock.fileno()) if settings['daemon']:
daemonize(keepfd=lsock.fileno())
if settings['multiprocess']:
print 'Waiting for connections on %s:%s' % (
settings['listen_host'], settings['listen_port'])
# Reep zombies
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
while True: while True:
try: try:
csock = startsock = None csock = startsock = None
print 'waiting for connection on port %s' % settings['listen_port'] pid = 0
if not settings['multiprocess']:
print 'Waiting for connection on %s:%s' % (
settings['listen_host'], settings['listen_port'])
startsock, address = lsock.accept() startsock, address = lsock.accept()
print 'Got client connection from %s' % address[0] handler_msg('got client connection from %s' % address[0])
csock = do_handshake(startsock) csock = do_handshake(startsock)
if not csock: continue if not csock: continue
settings['handler'](csock) if settings['multiprocess']:
handler_msg("forking handler process")
pid = os.fork()
except Exception: if pid == 0: # handler process
print "Ignoring exception:" settings['handler'](csock)
print traceback.format_exc() else: # parent process
settings['handler_id'] += 1
except EClose, exc:
handler_msg("handler exit: %s" % exc.args)
except Exception, exc:
handler_msg("handler exception: %s" % str(exc))
#handler_msg(traceback.format_exc())
if pid == 0:
if csock: csock.close() if csock: csock.close()
if startsock and startsock != csock: startsock.close() if startsock and startsock != csock: startsock.close()
if settings['multiprocess']: break # Child process exits

View File

@ -45,6 +45,7 @@ char USAGE[] = "Usage: [options] " \
char target_host[256]; char target_host[256];
int target_port; int target_port;
extern pipe_error;
extern settings_t settings; extern settings_t settings;
extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp; extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
extern unsigned int bufsize, dbufsize; extern unsigned int bufsize, dbufsize;
@ -86,29 +87,32 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
} }
ret = select(maxfd, &rlist, &wlist, &elist, &tv); ret = select(maxfd, &rlist, &wlist, &elist, &tv);
if (pipe_error) { break; }
if (FD_ISSET(target, &elist)) { if (FD_ISSET(target, &elist)) {
fprintf(stderr, "target exception\n"); handler_emsg("target exception\n");
break; break;
} }
if (FD_ISSET(client, &elist)) { if (FD_ISSET(client, &elist)) {
fprintf(stderr, "client exception\n"); handler_emsg("client exception\n");
break; break;
} }
if (ret == -1) { if (ret == -1) {
error("select()"); handler_emsg("select(): %s\n", strerror(errno));
break; break;
} else if (ret == 0) { } else if (ret == 0) {
//fprintf(stderr, "select timeout\n"); //handler_emsg("select timeout\n");
continue; continue;
} }
if (FD_ISSET(target, &wlist)) { if (FD_ISSET(target, &wlist)) {
len = tend-tstart; len = tend-tstart;
bytes = send(target, tbuf + tstart, len, 0); bytes = send(target, tbuf + tstart, len, 0);
if (pipe_error) { break; }
if (bytes < 0) { if (bytes < 0) {
error("target connection error"); handler_emsg("target connection error: %s\n",
strerror(errno));
break; break;
} }
tstart += bytes; tstart += bytes;
@ -123,8 +127,9 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
if (FD_ISSET(client, &wlist)) { if (FD_ISSET(client, &wlist)) {
len = cend-cstart; len = cend-cstart;
bytes = ws_send(ws_ctx, cbuf + cstart, len); bytes = ws_send(ws_ctx, cbuf + cstart, len);
if (pipe_error) { break; }
if (len < 3) { if (len < 3) {
fprintf(stderr, "len: %d, bytes: %d: %d\n", len, bytes, *(cbuf + cstart)); handler_emsg("len: %d, bytes: %d: %d\n", len, bytes, *(cbuf + cstart));
} }
cstart += bytes; cstart += bytes;
if (cstart >= cend) { if (cstart >= cend) {
@ -137,8 +142,9 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
if (FD_ISSET(target, &rlist)) { if (FD_ISSET(target, &rlist)) {
bytes = recv(target, cbuf_tmp, dbufsize , 0); bytes = recv(target, cbuf_tmp, dbufsize , 0);
if (pipe_error) { break; }
if (bytes <= 0) { if (bytes <= 0) {
fprintf(stderr, "target closed connection"); handler_emsg("target closed connection\n");
break; break;
} }
cstart = 0; cstart = 0;
@ -151,7 +157,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
printf("\n"); printf("\n");
*/ */
if (cend < 0) { if (cend < 0) {
fprintf(stderr, "encoding error\n"); handler_emsg("encoding error\n");
break; break;
} }
traffic("{"); traffic("{");
@ -159,13 +165,14 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
if (FD_ISSET(client, &rlist)) { if (FD_ISSET(client, &rlist)) {
bytes = ws_recv(ws_ctx, tbuf_tmp, bufsize-1); bytes = ws_recv(ws_ctx, tbuf_tmp, bufsize-1);
if (pipe_error) { break; }
if (bytes <= 0) { if (bytes <= 0) {
fprintf(stderr, "client closed connection\n"); handler_emsg("client closed connection\n");
break; break;
} else if ((bytes == 2) && } else if ((bytes == 2) &&
(tbuf_tmp[0] == '\xff') && (tbuf_tmp[0] == '\xff') &&
(tbuf_tmp[1] == '\x00')) { (tbuf_tmp[1] == '\x00')) {
fprintf(stderr, "client sent orderly close frame"); handler_emsg("client sent orderly close frame\n");
break; break;
} }
/* /*
@ -184,7 +191,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
printf("\n"); printf("\n");
*/ */
if (len < 0) { if (len < 0) {
fprintf(stderr, "decoding error\n"); handler_emsg("decoding error\n");
break; break;
} }
traffic("}"); traffic("}");
@ -198,11 +205,12 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
int tsock = 0; int tsock = 0;
struct sockaddr_in taddr; struct sockaddr_in taddr;
printf("Connecting to: %s:%d\n", target_host, target_port); handler_msg("connecting to: %s:%d\n", target_host, target_port);
tsock = socket(AF_INET, SOCK_STREAM, 0); tsock = socket(AF_INET, SOCK_STREAM, 0);
if (tsock < 0) { if (tsock < 0) {
error("Could not create target socket"); handler_emsg("Could not create target socket: %s\n",
strerror(errno));
return; return;
} }
bzero((char *) &taddr, sizeof(taddr)); bzero((char *) &taddr, sizeof(taddr));
@ -211,16 +219,20 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
/* Resolve target address */ /* Resolve target address */
if (resolve_host(&taddr.sin_addr, target_host) < -1) { if (resolve_host(&taddr.sin_addr, target_host) < -1) {
error("Could not resolve target address"); handler_emsg("Could not resolve target address: %s\n",
strerror(errno));
} }
if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) { if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
error("Could not connect to target"); handler_emsg("Could not connect to target: %s\n",
strerror(errno));
close(tsock); close(tsock);
return; return;
} }
printf("%s", traffic_legend); if ((! settings.daemon) && (! settings.multiprocess)) {
printf("%s", traffic_legend);
}
do_proxy(ws_ctx, tsock); do_proxy(ws_ctx, tsock);
@ -230,11 +242,12 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int fd, c, option_index = 0; int fd, c, option_index = 0;
static int ssl_only = 0, foreground = 0; static int ssl_only = 0, foreground = 0, multi = 0;
char *found; char *found;
static struct option long_options[] = { static struct option long_options[] = {
{"ssl-only", no_argument, &ssl_only, 1 }, {"ssl-only", no_argument, &ssl_only, 1 },
{"foreground", no_argument, &foreground, 'f'}, {"foreground", no_argument, &foreground, 'f'},
{"multiprocess", no_argument, &multi, 'm'},
/* ---- */ /* ---- */
{"cert", required_argument, 0, 'c'}, {"cert", required_argument, 0, 'c'},
{0, 0, 0, 0} {0, 0, 0, 0}
@ -243,7 +256,7 @@ int main(int argc, char *argv[])
settings.cert = realpath("self.pem", NULL); settings.cert = realpath("self.pem", NULL);
while (1) { while (1) {
c = getopt_long (argc, argv, "fr:c:", c = getopt_long (argc, argv, "fmc:",
long_options, &option_index); long_options, &option_index);
/* Detect the end */ /* Detect the end */
@ -257,6 +270,9 @@ int main(int argc, char *argv[])
case 'f': case 'f':
foreground = 1; foreground = 1;
break; break;
case 'm':
multi = 1;
break;
case 'r': case 'r':
if ((fd = open(optarg, O_CREAT, if ((fd = open(optarg, O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < -1) { S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < -1) {
@ -274,8 +290,9 @@ int main(int argc, char *argv[])
usage(""); usage("");
} }
} }
settings.ssl_only = ssl_only; settings.ssl_only = ssl_only;
settings.daemon = foreground ? 0: 1; settings.daemon = foreground ? 0: 1;
settings.multiprocess = multi;
if ((argc-optind) != 2) { if ((argc-optind) != 2) {
usage("Invalid number of arguments\n"); usage("Invalid number of arguments\n");
@ -314,6 +331,7 @@ int main(int argc, char *argv[])
//printf(" ssl_only: %d\n", settings.ssl_only); //printf(" ssl_only: %d\n", settings.ssl_only);
//printf(" daemon: %d\n", settings.daemon); //printf(" daemon: %d\n", settings.daemon);
//printf(" multiproces: %d\n", settings.multiprocess);
//printf(" cert: %s\n", settings.cert); //printf(" cert: %s\n", settings.cert);
settings.handler = proxy_handler; settings.handler = proxy_handler;

View File

@ -72,7 +72,7 @@ def do_proxy(client, target):
if target in ins: if target in ins:
buf = target.recv(buffer_size) buf = target.recv(buffer_size)
if len(buf) == 0: raise Exception("Target closed") if len(buf) == 0: raise EClose("Target closed")
cqueue.append(encode(buf)) cqueue.append(encode(buf))
traffic("{") traffic("{")
@ -80,10 +80,10 @@ def do_proxy(client, target):
if client in ins: if client in ins:
buf = client.recv(buffer_size) buf = client.recv(buffer_size)
if len(buf) == 0: raise Exception("Client closed") if len(buf) == 0: raise EClose("Client closed")
if buf == '\xff\x00': if buf == '\xff\x00':
raise Exception("Client sent orderly close frame") raise EClose("Client sent orderly close frame")
elif buf[-1] == '\xff': elif buf[-1] == '\xff':
if buf.count('\xff') > 1: if buf.count('\xff') > 1:
traffic(str(buf.count('\xff'))) traffic(str(buf.count('\xff')))
@ -104,15 +104,16 @@ def proxy_handler(client):
global target_host, target_port, options, rec global target_host, target_port, options, rec
if settings['record']: if settings['record']:
print "Opening record file: %s" % settings['record'] handler_msg("opening record file: %s" % settings['record'])
rec = open(settings['record'], 'w+') rec = open(settings['record'], 'w+')
rec.write("var VNC_frame_data = [\n") rec.write("var VNC_frame_data = [\n")
print "Connecting to: %s:%s" % (target_host, target_port) handler_msg("connecting to: %s:%s" % (target_host, target_port))
tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tsock.connect((target_host, target_port)) tsock.connect((target_host, target_port))
print traffic_legend if not settings['daemon'] and not settings['multiprocess']:
print traffic_legend
try: try:
do_proxy(client, tsock) do_proxy(client, tsock)
@ -132,6 +133,9 @@ if __name__ == '__main__':
parser.add_option("--foreground", "-f", parser.add_option("--foreground", "-f",
dest="daemon", default=True, action="store_false", dest="daemon", default=True, action="store_false",
help="stay in foreground, do not daemonize") help="stay in foreground, do not daemonize")
parser.add_option("--multiprocess", "-m",
dest="multiprocess", action="store_true",
help="fork handler processes")
parser.add_option("--ssl-only", action="store_true", parser.add_option("--ssl-only", action="store_true",
help="disallow non-encrypted connections") help="disallow non-encrypted connections")
parser.add_option("--cert", default="self.pem", parser.add_option("--cert", default="self.pem",
@ -162,6 +166,7 @@ if __name__ == '__main__':
settings['cert'] = os.path.abspath(options.cert) settings['cert'] = os.path.abspath(options.cert)
settings['ssl_only'] = options.ssl_only settings['ssl_only'] = options.ssl_only
settings['daemon'] = options.daemon settings['daemon'] = options.daemon
settings['multiprocess'] = options.multiprocess
if options.record: if options.record:
settings['record'] = os.path.abspath(options.record) settings['record'] = os.path.abspath(options.record)
start_server() start_server()