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 :-)
|
||||
|
||||
* Support (and control over) session resuming, particular when functioning as
|
||||
an SSL client.
|
||||
* Support (and control over) session resuming, particularly when functioning
|
||||
as an SSL client.
|
||||
|
||||
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
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
that AF_INET/PF_INET stuff, subtely different parameters to various IPv4-related
|
||||
functions like socket(), bind(), fcntl(), etc).
|
||||
that AF_INET/PF_INET stuff, subtlely different parameters to various
|
||||
IPv4-related functions like socket(), bind(), fcntl(), etc).
|
||||
|
||||
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
|
||||
@ -207,12 +209,12 @@ Rinse and repeat.
|
||||
Inside one console, try typing;
|
||||
|
||||
(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;
|
||||
|
||||
(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
|
||||
tunneled through to the telnet service on your local machine. Feel free to
|
||||
|
@ -5,12 +5,13 @@
|
||||
void buffer_init(buffer_t *buf)
|
||||
{
|
||||
buf->used = 0;
|
||||
buf->total_in = buf->total_out = 0;
|
||||
}
|
||||
|
||||
void buffer_close(buffer_t *buf)
|
||||
{
|
||||
/* Our data is static - nothing needs "release", just reset */
|
||||
buffer_init(buf);
|
||||
/* Our data is static - nothing needs "release", just reset it */
|
||||
buf->used = 0;
|
||||
}
|
||||
|
||||
/* Code these simple ones in compact form */
|
||||
@ -26,8 +27,16 @@ int buffer_empty(buffer_t *buf) {
|
||||
return (buf->used == 0 ? 1 : 0); }
|
||||
int buffer_notempty(buffer_t *buf) {
|
||||
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 added = MAX_DATA_SIZE - buf->used;
|
||||
@ -37,10 +46,11 @@ unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
|
||||
return 0;
|
||||
memcpy(buf->data + buf->used, ptr, added);
|
||||
buf->used += added;
|
||||
buf->total_in += 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 taken = buf->used;
|
||||
@ -57,7 +67,7 @@ unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
|
||||
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;
|
||||
if((int)tomove > cap)
|
||||
@ -80,8 +90,10 @@ int buffer_from_fd(buffer_t *buf, int fd)
|
||||
/* Shouldn't be called in this case! */
|
||||
abort();
|
||||
toread = read(fd, buf->data + buf->used, toread);
|
||||
if(toread > 0)
|
||||
if(toread > 0) {
|
||||
buf->used += toread;
|
||||
buf->total_in += toread;
|
||||
}
|
||||
return toread;
|
||||
}
|
||||
|
||||
@ -92,8 +104,10 @@ int buffer_to_fd(buffer_t *buf, int fd)
|
||||
/* Shouldn't be called in this case! */
|
||||
abort();
|
||||
towrite = write(fd, buf->data, towrite);
|
||||
if(towrite > 0)
|
||||
if(towrite > 0) {
|
||||
buffer_takedata(buf, NULL, towrite);
|
||||
buf->total_out += towrite;
|
||||
}
|
||||
return towrite;
|
||||
}
|
||||
|
||||
@ -138,8 +152,10 @@ void buffer_from_SSL(buffer_t *buf, SSL *ssl)
|
||||
if(!ssl || buffer_full(buf))
|
||||
return;
|
||||
ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
|
||||
if(ret > 0)
|
||||
if(ret > 0) {
|
||||
buf->used += ret;
|
||||
buf->total_in += ret;
|
||||
}
|
||||
if(ret < 0)
|
||||
int_ssl_check(ssl, ret);
|
||||
}
|
||||
@ -150,8 +166,10 @@ void buffer_to_SSL(buffer_t *buf, SSL *ssl)
|
||||
if(!ssl || buffer_empty(buf))
|
||||
return;
|
||||
ret = SSL_write(ssl, buf->data, buf->used);
|
||||
if(ret > 0)
|
||||
if(ret > 0) {
|
||||
buffer_takedata(buf, NULL, ret);
|
||||
buf->total_out += ret;
|
||||
}
|
||||
if(ret < 0)
|
||||
int_ssl_check(ssl, ret);
|
||||
}
|
||||
@ -162,8 +180,10 @@ void buffer_from_BIO(buffer_t *buf, BIO *bio)
|
||||
if(!bio || buffer_full(buf))
|
||||
return;
|
||||
ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
|
||||
if(ret > 0)
|
||||
if(ret > 0) {
|
||||
buf->used += ret;
|
||||
buf->total_in += ret;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
ret = BIO_write(bio, buf->data, buf->used);
|
||||
if(ret > 0)
|
||||
if(ret > 0) {
|
||||
buffer_takedata(buf, NULL, ret);
|
||||
buf->total_out += ret;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined(NO_OPENSSL) */
|
||||
|
@ -100,6 +100,7 @@ static int def_server_mode = 0;
|
||||
static const char *def_cipher_list = NULL;
|
||||
static int def_out_state = 0;
|
||||
static unsigned int def_out_verify = 0;
|
||||
static int def_out_totals = 0;
|
||||
static int def_verify_mode = 0;
|
||||
static unsigned int def_verify_depth = 10;
|
||||
|
||||
@ -119,6 +120,7 @@ static const char *helpstring =
|
||||
" -cipher <list> (specifies cipher list to use)\n"
|
||||
" -out_state (prints SSL handshake states)\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_strict (do not continue if peer doesn't authenticate)\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;
|
||||
}
|
||||
|
||||
/* 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[])
|
||||
{
|
||||
unsigned int loop;
|
||||
@ -230,6 +242,7 @@ int main(int argc, char *argv[])
|
||||
const char *cipher_list = def_cipher_list;
|
||||
int out_state = def_out_state;
|
||||
unsigned int out_verify = def_out_verify;
|
||||
int out_totals = def_out_totals;
|
||||
int verify_mode = def_verify_mode;
|
||||
unsigned int verify_depth = def_verify_depth;
|
||||
|
||||
@ -330,6 +343,9 @@ next_arg:
|
||||
if(!parse_verify_level(*argv, &out_verify))
|
||||
return 1;
|
||||
goto next_arg;
|
||||
} else if(strcmp(*argv, "-out_totals") == 0) {
|
||||
out_totals = 1;
|
||||
goto next_arg;
|
||||
} else if(strcmp(*argv, "-v_peer") == 0) {
|
||||
verify_mode |= SSL_VERIFY_PEER;
|
||||
goto next_arg;
|
||||
@ -427,6 +443,27 @@ main_loop:
|
||||
/* We're closing whether for reasons of an error or a
|
||||
* natural close. Don't increment loop or t_item because
|
||||
* 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);
|
||||
fprintf(stderr, "Info, tunnel closed, down to %d\n",
|
||||
world.tunnels_used);
|
||||
|
@ -41,6 +41,9 @@
|
||||
typedef struct _buffer_t {
|
||||
unsigned char data[MAX_DATA_SIZE];
|
||||
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;
|
||||
|
||||
/* 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_empty(buffer_t *buf); /* Boolean, is it 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
|
||||
* added (so, you need to check if return value is less than size) */
|
||||
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
|
||||
* 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);
|
||||
#endif
|
||||
|
||||
#ifndef NO_IP
|
||||
/* Read or write between a file-descriptor and a buffer */
|
||||
|
Loading…
Reference in New Issue
Block a user