提交 beb23252 编写于 作者: G Geoff Thorpe

Some minor changes to the "tunala" demo.

* Seal off some buffer functions so that only the higher-level IO functions
  are exposed.

* Using the above change to buffer, add support to tunala for displaying
  traffic totals when a tunnel closes. Useful in debugging and analysis -
  you get to see the total encrypted traffic versus the total tunneled
  traffic. This shows not only how much expansion your data suffers from
  SSL (a lot if you send/receive a few bytes at a time), but also the
  overhead of SSL handshaking relative to the payload sent through the
  tunnel. This is controlled by the "-out_totals" switch to tunala.

* Fix and tweak some bits in the README.

Eg. sample output of "-out_totals" from a tunnel client when tunneling a brief
"telnet" session.

Tunnel closing, traffic stats follow
    SSL (network) traffic to/from server;     7305 bytes in,     3475 bytes out
    tunnelled data to/from server;            4295 bytes in,      186 bytes out
上级 3ba25ee8
...@@ -137,8 +137,8 @@ Possible things include: ...@@ -137,8 +137,8 @@ Possible things include:
* A few other things you can already do in s_client and s_server :-) * A few other things you can already do in s_client and s_server :-)
* Support (and control over) session resuming, particular when functioning as * Support (and control over) session resuming, particularly when functioning
an SSL client. as an SSL client.
If you have a particular environment where this model might work to let you "do If you have a particular environment where this model might work to let you "do
SSL" without having OpenSSL be aware of the transport, then you should find you SSL" without having OpenSSL be aware of the transport, then you should find you
...@@ -184,15 +184,17 @@ Here is an example of how to use "tunala" ... ...@@ -184,15 +184,17 @@ Here is an example of how to use "tunala" ...
First, it's assumed that OpenSSL has already built, and that you are building First, it's assumed that OpenSSL has already built, and that you are building
inside the ./demos/tunala/ directory. If not - please correct the paths and inside the ./demos/tunala/ directory. If not - please correct the paths and
flags inside the Makefile. flags inside the Makefile. Likewise, if you want to tweak the building, it's
best to try and do so in the makefile (eg. removing the debug flags and adding
optimisation flags).
Secondly, this code so far has only ever been built and run on Linux - network Secondly, this code so far has only ever been built and run on Linux - network
specifics are more than likely to create little glitches on other unixen, specifics are more than likely to create little glitches on other unixen,
particularly Solaris in my experience. If you're not on Linux, please read the particularly Solaris in my experience. If you're not on Linux, please read the
code wherever compilation flares up and try to make the necessary changes - code wherever compilation flares up and try to make the necessary changes -
usually the man-page associated with the relevant function is enough (eg. all usually the man-page associated with the relevant function is enough (eg. all
that AF_INET/PF_INET stuff, subtely different parameters to various IPv4-related that AF_INET/PF_INET stuff, subtlely different parameters to various
functions like socket(), bind(), fcntl(), etc). IPv4-related functions like socket(), bind(), fcntl(), etc).
Thirdly, if you are Win32, you probably need to do some *major* rewriting of Thirdly, if you are Win32, you probably need to do some *major* rewriting of
ip.c to stand a hope in hell. Good luck, and please mail me the diff if you do ip.c to stand a hope in hell. Good luck, and please mail me the diff if you do
...@@ -207,12 +209,12 @@ Rinse and repeat. ...@@ -207,12 +209,12 @@ Rinse and repeat.
Inside one console, try typing; Inside one console, try typing;
(i) ./tunala -listen localhost:8080 -proxy localhost:8081 -cacert CA.pem \ (i) ./tunala -listen localhost:8080 -proxy localhost:8081 -cacert CA.pem \
-cert A-client.pem -cert A-client.pem -out_totals -v_peer -v_strict
In another console, type; In another console, type;
(ii) ./tunala -listen localhost:8081 -proxy localhost:23 -cacert CA.pem \ (ii) ./tunala -listen localhost:8081 -proxy localhost:23 -cacert CA.pem \
-cert A-server.pem -server 1 -cert A-server.pem -server 1 -out_totals -v_peer -v_strict
Now if you open another console and "telnet localhost 8080", you should be Now if you open another console and "telnet localhost 8080", you should be
tunneled through to the telnet service on your local machine. Feel free to tunneled through to the telnet service on your local machine. Feel free to
......
...@@ -5,12 +5,13 @@ ...@@ -5,12 +5,13 @@
void buffer_init(buffer_t *buf) void buffer_init(buffer_t *buf)
{ {
buf->used = 0; buf->used = 0;
buf->total_in = buf->total_out = 0;
} }
void buffer_close(buffer_t *buf) void buffer_close(buffer_t *buf)
{ {
/* Our data is static - nothing needs "release", just reset */ /* Our data is static - nothing needs "release", just reset it */
buffer_init(buf); buf->used = 0;
} }
/* Code these simple ones in compact form */ /* Code these simple ones in compact form */
...@@ -26,8 +27,16 @@ int buffer_empty(buffer_t *buf) { ...@@ -26,8 +27,16 @@ int buffer_empty(buffer_t *buf) {
return (buf->used == 0 ? 1 : 0); } return (buf->used == 0 ? 1 : 0); }
int buffer_notempty(buffer_t *buf) { int buffer_notempty(buffer_t *buf) {
return (buf->used > 0 ? 1 : 0); } return (buf->used > 0 ? 1 : 0); }
unsigned long buffer_total_in(buffer_t *buf) {
unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr, return buf->total_in; }
unsigned long buffer_total_out(buffer_t *buf) {
return buf->total_out; }
/* These 3 static (internal) functions don't adjust the "total" variables as
* it's not sure when they're called how it should be interpreted. Only the
* higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
* values. */
static unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
unsigned int size) unsigned int size)
{ {
unsigned int added = MAX_DATA_SIZE - buf->used; unsigned int added = MAX_DATA_SIZE - buf->used;
...@@ -37,10 +46,11 @@ unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr, ...@@ -37,10 +46,11 @@ unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
return 0; return 0;
memcpy(buf->data + buf->used, ptr, added); memcpy(buf->data + buf->used, ptr, added);
buf->used += added; buf->used += added;
buf->total_in += added;
return added; return added;
} }
unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr, static unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
unsigned int size) unsigned int size)
{ {
unsigned int taken = buf->used; unsigned int taken = buf->used;
...@@ -57,7 +67,7 @@ unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr, ...@@ -57,7 +67,7 @@ unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
return taken; return taken;
} }
unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap) static unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap)
{ {
unsigned int moved, tomove = from->used; unsigned int moved, tomove = from->used;
if((int)tomove > cap) if((int)tomove > cap)
...@@ -80,8 +90,10 @@ int buffer_from_fd(buffer_t *buf, int fd) ...@@ -80,8 +90,10 @@ int buffer_from_fd(buffer_t *buf, int fd)
/* Shouldn't be called in this case! */ /* Shouldn't be called in this case! */
abort(); abort();
toread = read(fd, buf->data + buf->used, toread); toread = read(fd, buf->data + buf->used, toread);
if(toread > 0) if(toread > 0) {
buf->used += toread; buf->used += toread;
buf->total_in += toread;
}
return toread; return toread;
} }
...@@ -92,8 +104,10 @@ int buffer_to_fd(buffer_t *buf, int fd) ...@@ -92,8 +104,10 @@ int buffer_to_fd(buffer_t *buf, int fd)
/* Shouldn't be called in this case! */ /* Shouldn't be called in this case! */
abort(); abort();
towrite = write(fd, buf->data, towrite); towrite = write(fd, buf->data, towrite);
if(towrite > 0) if(towrite > 0) {
buffer_takedata(buf, NULL, towrite); buffer_takedata(buf, NULL, towrite);
buf->total_out += towrite;
}
return towrite; return towrite;
} }
...@@ -138,8 +152,10 @@ void buffer_from_SSL(buffer_t *buf, SSL *ssl) ...@@ -138,8 +152,10 @@ void buffer_from_SSL(buffer_t *buf, SSL *ssl)
if(!ssl || buffer_full(buf)) if(!ssl || buffer_full(buf))
return; return;
ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf)); ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
if(ret > 0) if(ret > 0) {
buf->used += ret; buf->used += ret;
buf->total_in += ret;
}
if(ret < 0) if(ret < 0)
int_ssl_check(ssl, ret); int_ssl_check(ssl, ret);
} }
...@@ -150,8 +166,10 @@ void buffer_to_SSL(buffer_t *buf, SSL *ssl) ...@@ -150,8 +166,10 @@ void buffer_to_SSL(buffer_t *buf, SSL *ssl)
if(!ssl || buffer_empty(buf)) if(!ssl || buffer_empty(buf))
return; return;
ret = SSL_write(ssl, buf->data, buf->used); ret = SSL_write(ssl, buf->data, buf->used);
if(ret > 0) if(ret > 0) {
buffer_takedata(buf, NULL, ret); buffer_takedata(buf, NULL, ret);
buf->total_out += ret;
}
if(ret < 0) if(ret < 0)
int_ssl_check(ssl, ret); int_ssl_check(ssl, ret);
} }
...@@ -162,8 +180,10 @@ void buffer_from_BIO(buffer_t *buf, BIO *bio) ...@@ -162,8 +180,10 @@ void buffer_from_BIO(buffer_t *buf, BIO *bio)
if(!bio || buffer_full(buf)) if(!bio || buffer_full(buf))
return; return;
ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf)); ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
if(ret > 0) if(ret > 0) {
buf->used += ret; buf->used += ret;
buf->total_in += ret;
}
} }
void buffer_to_BIO(buffer_t *buf, BIO *bio) void buffer_to_BIO(buffer_t *buf, BIO *bio)
...@@ -172,8 +192,10 @@ void buffer_to_BIO(buffer_t *buf, BIO *bio) ...@@ -172,8 +192,10 @@ void buffer_to_BIO(buffer_t *buf, BIO *bio)
if(!bio || buffer_empty(buf)) if(!bio || buffer_empty(buf))
return; return;
ret = BIO_write(bio, buf->data, buf->used); ret = BIO_write(bio, buf->data, buf->used);
if(ret > 0) if(ret > 0) {
buffer_takedata(buf, NULL, ret); buffer_takedata(buf, NULL, ret);
buf->total_out += ret;
}
} }
#endif /* !defined(NO_OPENSSL) */ #endif /* !defined(NO_OPENSSL) */
......
...@@ -100,6 +100,7 @@ static int def_server_mode = 0; ...@@ -100,6 +100,7 @@ static int def_server_mode = 0;
static const char *def_cipher_list = NULL; static const char *def_cipher_list = NULL;
static int def_out_state = 0; static int def_out_state = 0;
static unsigned int def_out_verify = 0; static unsigned int def_out_verify = 0;
static int def_out_totals = 0;
static int def_verify_mode = 0; static int def_verify_mode = 0;
static unsigned int def_verify_depth = 10; static unsigned int def_verify_depth = 10;
...@@ -119,6 +120,7 @@ static const char *helpstring = ...@@ -119,6 +120,7 @@ static const char *helpstring =
" -cipher <list> (specifies cipher list to use)\n" " -cipher <list> (specifies cipher list to use)\n"
" -out_state (prints SSL handshake states)\n" " -out_state (prints SSL handshake states)\n"
" -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n" " -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n"
" -out_totals (prints out byte-totals when a tunnel closes)\n"
" -v_peer (verify the peer certificate)\n" " -v_peer (verify the peer certificate)\n"
" -v_strict (do not continue if peer doesn't authenticate)\n" " -v_strict (do not continue if peer doesn't authenticate)\n"
" -v_once (no verification in renegotiates)\n" " -v_once (no verification in renegotiates)\n"
...@@ -208,6 +210,16 @@ static int parse_verify_depth(const char *s, unsigned int *verify_depth) ...@@ -208,6 +210,16 @@ static int parse_verify_depth(const char *s, unsigned int *verify_depth)
return 1; return 1;
} }
/* Some fprintf format strings used when tunnels close */
static const char *io_stats_client_dirty =
" SSL (network) traffic to/from server; %8lu bytes in, %8lu bytes out\n";
static const char *io_stats_client_clean =
" tunnelled data to/from server; %8lu bytes in, %8lu bytes out\n";
static const char *io_stats_server_dirty =
" SSL (network) traffic to/from client; %8lu bytes in, %8lu bytes out\n";
static const char *io_stats_server_clean =
" tunnelled data to/from client; %8lu bytes in, %8lu bytes out\n";
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
unsigned int loop; unsigned int loop;
...@@ -230,6 +242,7 @@ int main(int argc, char *argv[]) ...@@ -230,6 +242,7 @@ int main(int argc, char *argv[])
const char *cipher_list = def_cipher_list; const char *cipher_list = def_cipher_list;
int out_state = def_out_state; int out_state = def_out_state;
unsigned int out_verify = def_out_verify; unsigned int out_verify = def_out_verify;
int out_totals = def_out_totals;
int verify_mode = def_verify_mode; int verify_mode = def_verify_mode;
unsigned int verify_depth = def_verify_depth; unsigned int verify_depth = def_verify_depth;
...@@ -330,6 +343,9 @@ next_arg: ...@@ -330,6 +343,9 @@ next_arg:
if(!parse_verify_level(*argv, &out_verify)) if(!parse_verify_level(*argv, &out_verify))
return 1; return 1;
goto next_arg; goto next_arg;
} else if(strcmp(*argv, "-out_totals") == 0) {
out_totals = 1;
goto next_arg;
} else if(strcmp(*argv, "-v_peer") == 0) { } else if(strcmp(*argv, "-v_peer") == 0) {
verify_mode |= SSL_VERIFY_PEER; verify_mode |= SSL_VERIFY_PEER;
goto next_arg; goto next_arg;
...@@ -427,6 +443,27 @@ main_loop: ...@@ -427,6 +443,27 @@ main_loop:
/* We're closing whether for reasons of an error or a /* We're closing whether for reasons of an error or a
* natural close. Don't increment loop or t_item because * natural close. Don't increment loop or t_item because
* the next item is moving to us! */ * the next item is moving to us! */
if(!out_totals)
goto skip_totals;
fprintf(stderr, "Tunnel closing, traffic stats follow\n");
/* Display the encrypted (over the network) stats */
fprintf(stderr, (server_mode ? io_stats_server_dirty :
io_stats_client_dirty),
buffer_total_in(state_machine_get_buffer(
&t_item->sm,SM_DIRTY_IN)),
buffer_total_out(state_machine_get_buffer(
&t_item->sm,SM_DIRTY_OUT)));
/* Display the local (tunnelled) stats. NB: Data we
* *receive* is data sent *out* of the state_machine on
* its 'clean' side. Hence the apparent back-to-front
* OUT/IN mixup here :-) */
fprintf(stderr, (server_mode ? io_stats_server_clean :
io_stats_client_clean),
buffer_total_out(state_machine_get_buffer(
&t_item->sm,SM_CLEAN_OUT)),
buffer_total_in(state_machine_get_buffer(
&t_item->sm,SM_CLEAN_IN)));
skip_totals:
tunala_world_del_item(&world, loop); tunala_world_del_item(&world, loop);
fprintf(stderr, "Info, tunnel closed, down to %d\n", fprintf(stderr, "Info, tunnel closed, down to %d\n",
world.tunnels_used); world.tunnels_used);
......
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
typedef struct _buffer_t { typedef struct _buffer_t {
unsigned char data[MAX_DATA_SIZE]; unsigned char data[MAX_DATA_SIZE];
unsigned int used; unsigned int used;
/* Statistical values - counts the total number of bytes read in and
* read out (respectively) since "buffer_init()" */
unsigned long total_in, total_out;
} buffer_t; } buffer_t;
/* Initialise a buffer structure before use */ /* Initialise a buffer structure before use */
...@@ -59,7 +62,11 @@ int buffer_full(buffer_t *buf); /* Boolean, is it full? */ ...@@ -59,7 +62,11 @@ int buffer_full(buffer_t *buf); /* Boolean, is it full? */
int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */ int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */
int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */ int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */
int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */ int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */
unsigned long buffer_total_in(buffer_t *buf); /* Total bytes written to buffer */
unsigned long buffer_total_out(buffer_t *buf); /* Total bytes read from buffer */
#if 0 /* Currently used only within buffer.c - better to expose only
* higher-level functions anyway */
/* Add data to the tail of the buffer, returns the amount that was actually /* Add data to the tail of the buffer, returns the amount that was actually
* added (so, you need to check if return value is less than size) */ * added (so, you need to check if return value is less than size) */
unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr, unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
...@@ -76,6 +83,7 @@ unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr, ...@@ -76,6 +83,7 @@ unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
* buffer. Return value is the amount moved. The amount moved can be restricted * buffer. Return value is the amount moved. The amount moved can be restricted
* to a maximum by specifying "cap" - setting it to -1 means no limit. */ * to a maximum by specifying "cap" - setting it to -1 means no limit. */
unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap); unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap);
#endif
#ifndef NO_IP #ifndef NO_IP
/* Read or write between a file-descriptor and a buffer */ /* Read or write between a file-descriptor and a buffer */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册