diff options
Diffstat (limited to '')
-rw-r--r-- | forward.c | 16 | ||||
-rw-r--r-- | manage.c | 27 | ||||
-rw-r--r-- | manage.h | 56 | ||||
-rw-r--r-- | management/management-notes.txt | 72 | ||||
-rw-r--r-- | multi.c | 11 |
5 files changed, 153 insertions, 29 deletions
@@ -707,12 +707,17 @@ process_incoming_link (struct context *c) c->c2.original_recv_size = c->c2.buf.len; #ifdef ENABLE_MANAGEMENT if (management) - management_bytes_in (management, c->c2.buf.len); + { + management_bytes_in (management, c->c2.buf.len); +#ifdef MANAGEMENT_DEF_AUTH + management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); +#endif + } #endif } else c->c2.original_recv_size = 0; - + #ifdef ENABLE_DEBUG /* take action to corrupt packet if we are in gremlin test mode */ if (c->options.gremlin) { @@ -1100,7 +1105,12 @@ process_outgoing_link (struct context *c) c->c2.link_write_bytes += size; #ifdef ENABLE_MANAGEMENT if (management) - management_bytes_out (management, size); + { + management_bytes_out (management, size); +#ifdef MANAGEMENT_DEF_AUTH + management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); +#endif + } #endif } } @@ -367,11 +367,15 @@ man_status (struct management *man, const int version, struct status_output *so) static void man_bytecount (struct management *man, const int update_seconds) { - man->connection.bytecount_update_seconds = update_seconds; + if (update_seconds >= 0) + man->connection.bytecount_update_seconds = update_seconds; + else + man->connection.bytecount_update_seconds = 0; + msg (M_CLIENT, "SUCCESS: bytecount interval changed"); } void -man_bytecount_output (struct management *man) +man_bytecount_output_client (struct management *man) { char in[32]; char out[32]; @@ -382,6 +386,25 @@ man_bytecount_output (struct management *man) man->connection.bytecount_last_update = now; } +#ifdef MANAGEMENT_DEF_AUTH + +void +man_bytecount_output_server (struct management *man, + const counter_type *bytes_in_total, + const counter_type *bytes_out_total, + struct man_def_auth_context *mdac) +{ + char in[32]; + char out[32]; + /* do in a roundabout way to work around possible mingw or mingw-glibc bug */ + openvpn_snprintf (in, sizeof (in), counter_format, *bytes_in_total); + openvpn_snprintf (out, sizeof (out), counter_format, *bytes_out_total); + msg (M_CLIENT, ">BYTECOUNT_CLI:%lu,%s,%s", mdac->cid, in, out); + mdac->bytecount_last_update = now; +} + +#endif + static void man_kill (struct management *man, const char *victim) { @@ -51,6 +51,8 @@ struct man_def_auth_context { unsigned int flags; unsigned int mda_key_id_counter; + + time_t bytecount_last_update; }; #endif @@ -143,6 +145,10 @@ log_history_capacity (const struct log_history *h) struct management_callback { void *arg; + +# define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */ + unsigned int flags; + void (*status) (void *arg, const int version, struct status_output *so); void (*show_net) (void *arg, const int msglevel); int (*kill_by_cn) (void *arg, const char *common_name); @@ -432,31 +438,65 @@ void management_auth_failure (struct management *man, const char *type); * These functions drive the bytecount in/out counters. */ -void man_bytecount_output (struct management *man); +void man_bytecount_output_client (struct management *man); static inline void -man_bytecount_possible_output (struct management *man) +man_bytecount_possible_output_client (struct management *man) { if (man->connection.bytecount_update_seconds > 0 && now >= man->connection.bytecount_last_update + man->connection.bytecount_update_seconds) - man_bytecount_output (man); + man_bytecount_output_client (man); } static inline void -management_bytes_out (struct management *man, const int size) +management_bytes_out_client (struct management *man, const int size) { man->persist.bytes_out += size; - man_bytecount_possible_output (man); + man_bytecount_possible_output_client (man); } static inline void -management_bytes_in (struct management *man, const int size) +management_bytes_in_client (struct management *man, const int size) { man->persist.bytes_in += size; - man_bytecount_possible_output (man); + man_bytecount_possible_output_client (man); } -#endif +static inline void +management_bytes_out (struct management *man, const int size) +{ + if (!(man->persist.callback.flags & MCF_SERVER)) + management_bytes_out_client (man, size); +} +static inline void +management_bytes_in (struct management *man, const int size) +{ + if (!(man->persist.callback.flags & MCF_SERVER)) + management_bytes_in_client (man, size); +} + +#ifdef MANAGEMENT_DEF_AUTH + +static inline void +management_bytes_server (struct management *man, + const counter_type *bytes_in_total, + const counter_type *bytes_out_total, + struct man_def_auth_context *mdac) +{ + void man_bytecount_output_server (struct management *man, + const counter_type *bytes_in_total, + const counter_type *bytes_out_total, + struct man_def_auth_context *mdac); + + if (man->connection.bytecount_update_seconds > 0 + && now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds + && (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED) + man_bytecount_output_server (man, bytes_in_total, bytes_out_total, mdac); +} + +#endif /* MANAGEMENT_DEF_AUTH */ + +#endif #endif diff --git a/management/management-notes.txt b/management/management-notes.txt index 4d86111..5327338 100644 --- a/management/management-notes.txt +++ b/management/management-notes.txt @@ -3,26 +3,24 @@ OpenVPN Management Interface Notes The OpenVPN Management interface allows OpenVPN to be administratively controlled from an external program via -a TCP socket. +a TCP or unix domain socket. -The interface has been specifically designed for GUI developers -and those who would like to programmatically or remotely control -an OpenVPN daemon. +The interface has been specifically designed for developers +who would like to programmatically or remotely control +an OpenVPN daemon, and can be used when OpenVPN is running +as a client or server. The management interface is implemented using a client/server TCP -connection, where OpenVPN will listen on a provided IP address -and port for incoming management client connections. +connection or unix domain socket where OpenVPN will listen on a +provided IP address and port for incoming management client connections. The management protocol is currently cleartext without an explicit security layer. For this reason, it is recommended that the -management interface either listen on localhost (127.0.0.1) -or on the local VPN address. It's possible to remotely connect -to the management interface over the VPN itself, though some -capabilities will be limited in this mode, such as the ability -to provide private key passwords. - -Future versions of the management interface may allow out-of-band -connections (i.e. not over the VPN) and secured with SSL/TLS. +management interface either listen on a unix domain socket, +localhost (127.0.0.1), or on the local VPN address. It's possible +to remotely connect to the management interface over the VPN itself, +though some capabilities will be limited in this mode, such as the +ability to provide private key passwords. The management interface is enabled in the OpenVPN configuration file using the following directive: @@ -39,6 +37,44 @@ a telnet client which understands "raw" mode). Once connected to the management port, you can use the "help" command to list all commands. +COMMAND -- bytecount +-------------------- + +The bytecount command is used to request real-time notification +of OpenVPN bandwidth usage. + +Command syntax: + + bytecount n (where n > 0) -- set up automatic notification of + bandwidth usage once every n seconds + bytecount 0 -- turn off bytecount notifications + +If OpenVPN is running as a client, the bytecount notification +will look like this: + + >BYTECOUNT:{BYTES_IN},{BYTES_OUT} + +BYTES_IN is the number of bytes that have been received from +the server and BYTES_OUT is the number of bytes that have been +sent to the server. + +If OpenVPN is running as a server, the bytecount notification +will look like this: + + >BYTECOUNT_CLI:{CID},{BYTES_IN},{BYTES_OUT} + +CID is the Client ID, BYTES_IN is the number of bytes that have +been received from the client and BYTES_OUT is the number of +bytes that have been sent to the client. + +Note that when the bytecount command is used on the server, every +connected client will report its bandwidth numbers once every n +seconds. + +When the client disconnects, the final bandwidth numbers will be +placed in the 'bytes_received' and 'bytes_sent' environmental variables +as included in the >CLIENT:DISCONNECT notification. + COMMAND -- echo --------------- @@ -661,6 +697,14 @@ column and are immediately followed by a type keyword indicating the type of real-time message. The following types are currently defined: +BYTECOUNT -- Real-time bandwidth usage notification, as enabled + by "bytecount" command when OpenVPN is running as + a client. + +BYTECOUNT_CLI -- Real-time bandwidth usage notification per-client, + as enabled by "bytecount" command when OpenVPN is + running as a server. + CLIENT -- Notification of client connections and disconnections on an OpenVPN server. Enabled when OpenVPN is started with the --management-client-auth option. CLIENT @@ -437,6 +437,13 @@ multi_del_iroutes (struct multi_context *m, } static void +setenv_stats (struct context *c) +{ + setenv_counter (c->c2.es, "bytes_received", c->c2.link_read_bytes); + setenv_counter (c->c2.es, "bytes_sent", c->c2.link_write_bytes); +} + +static void multi_client_disconnect_setenv (struct multi_context *m, struct multi_instance *mi) { @@ -444,8 +451,7 @@ multi_client_disconnect_setenv (struct multi_context *m, setenv_trusted (mi->context.c2.es, get_link_socket_info (&mi->context)); /* setenv stats */ - setenv_counter (mi->context.c2.es, "bytes_received", mi->context.c2.link_read_bytes); - setenv_counter (mi->context.c2.es, "bytes_sent", mi->context.c2.link_write_bytes); + setenv_stats (&mi->context); /* setenv connection duration */ { @@ -2583,6 +2589,7 @@ init_management_callback_multi (struct multi_context *m) struct management_callback cb; CLEAR (cb); cb.arg = m; + cb.flags = MCF_SERVER; cb.status = management_callback_status; cb.show_net = management_show_net_callback; cb.kill_by_cn = management_callback_kill_by_cn; |