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
This commit is contained in:
parent
3ba25ee86a
commit
beb23252a6
@ -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" ...
|
|||||||
|
|
||||||
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.
|
|||||||
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 @@
|
|||||||
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) {
|
|||||||
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) {
|
||||||
|
return buf->total_in; }
|
||||||
|
unsigned long buffer_total_out(buffer_t *buf) {
|
||||||
|
return buf->total_out; }
|
||||||
|
|
||||||
unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
|
/* 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
|||||||
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 =
|
|||||||
" -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)
|
|||||||
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[])
|
|||||||
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:
|
|||||||
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:
|
|||||||
/* 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 @@
|
|||||||
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? */
|
|||||||
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,
|
|||||||
* 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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user