Make client code protocol-agnostic by encapsulating UDP/TCP
differences into ProtoBase/ProtoImpl/TCP/UDP classes.
Slightly change GeNL API to accomodate abovementioned changes.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Extend the ovpn-dco module to allow the user to specify ChaCha20Poly1305
as data channel cipher.
Same as AES-GCM, it also belongs to the AEAD family and its nonce length
is 12 bytes.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Since modern OpenVPN deployments negotiate AES-GCM,
there is no need to support AES-CBC / HMAC.
ovpn-dco doesn't support it, so clean up core as well.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
AES-GCM nonce is 12 bytes. OpenVPN obtains it by concatenating 4 bytes
packet id and rest (nonce_tail) from key material generated during TLS
handshake.
By some reasons ovpn-dco required userspace to provide 12 bytes
nonce_tail and generated 16 bytes nonce, even though kernel crypto API
uses only 12 bytes. This has been fixed in ovpn-dco and therefore has to
be fixed in userspace.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Commit cd68ae2740 ("ovpn-dco: support cipher 'none' and auth 'none'")
added initial support. This adds missing parts:
- do not throw exception in kocryto.hpp when using ovpn-dco
and cipher/auth are 'none'
- set hmac alg to OVPN_HMAC_ALG_NONE if crypto alg is 'none'
- pass hmac alg to ovpn-dco also when crypto alg is 'none'
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Since userspace doesn't know anything about data
channel traffic, keepalive should be handled in kernel.
Disable keepalive in userspace and implement
OVPN_CMD_SET_PEER ovpn-dco command, which sets
keepalive settings in kernel.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Implement OvpnDcoRekey, which parses key info
into format consumed by ovpn-dco.
Use KoRekey abstractions to hook into protocol layer
and get notified about rekeying events.
Pass new key to kernel or swap keys when commanded by
protocol layer.
Implement ovpn-dco netlink commands:
- OVPN_CMD_NEW_KEY
- OVPN_CMD_DEL_KEY
- OVPN_CMD_SWAP_KEYS
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add dependency to libnl-genl, which is C library
for generic netlink communication.
Implement C++ wrapper for libnl-genl, inspired by
ovpn-cli - a test client for ovpn-dco kernel module.
Implement ovpn-dco netlink commands:
- OVPN_CMD_START_VPN - pass transport socket,
protocol (UDP) and mode (client).
- OVPN_CMD_NEW_PEER - pass local and remote
endpoint info.
- OVPN_CMD_PACKET - move (control channel) packets
between userspace and kernel.
- OVPN_CMD_DEL_PEER - sent by kernel when peer is deleted
due to keepalive timeout (causes reconnect) or any other
reason (considered as fatal).
This change allows to perform openvpn handshake and
establish connection which doesn't work, since data channel
keys are not passed to kernel yet.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
ovpn-dco doesn't have concept of "opening" nor
file descriptor, since communication is handled
via netlink (to be added later).
Signed-off-by: Lev Stipakov <lev@openvpn.net>
These two new methods can be used to create and delete a tun or an
ovpn-dco interface via RTNL API.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Signed-off-by: Lev Stipakov <lev@openvpn.net>
In some situations, the local6 variable is nullptr but a default IPv6
route has been configured. This causes a segfault later in the call
chain when add_del_route() is being called.
We already have avoid a similar situation with IPv4, so implement the
same kind of safe guard for IPv6: If no local IPv6 address has been
configured, don't attempt to add IPv6 routes.
Signed-off-by: David Sommerseth <davids@openvpn.net>
When building the clinetcfg test client in openvpn3-linux with DCO support,
the building fails with the following compiler error:
In file included from ./openvpn3-core/openvpn/common/base64.hpp:31:0,
from ./openvpn3-core/openvpn/init/initprocess.hpp:31,
from ./openvpn3-core/client/ovpncli.cpp:90,
from ./openvpn3-core/test/ovpncli/cli.cpp:58,
from src/tests/netcfg/cli.cpp:29:
./openvpn3-core/openvpn/tun/linux/client/tunsetup.hpp: In member function ‘int openvpn::TunLinuxSetup::Setup<TUNMETHODS>::establish(const openvpn::TunBuilderCapture&, openvpn::TunBuilderSetup::Config*, openvpn::Stop*, std::ostream&)’:
./openvpn3-core/openvpn/tun/linux/client/tunsetup.hpp:145:94: error: there are no arguments to ‘errinfo’ that depend on a template parameter, so a declaration of ‘errinfo’ must be available [-fpermissive]
OPENVPN_THROW(tun_open_error, "error opening tun device " << node <<": " << errinfo(errno));
^
./openvpn3-core/openvpn/common/exception.hpp:130:18: note: in definition of macro ‘OPENVPN_THROW’
_ovpn_exc << stuff; \
^
By including the asioerr.hpp header file in
openvpn/tun/linux/client/tunsetup.hpp, this failure is resolved.
Signed-off-by: David Sommerseth <davids@openvpn.net>
When building on RHEL 7 using the stock compiler (gcc-4.8.5), compiler
errors like this one began to appear after commit 8a502f3b61:
core/openvpn/tun/linux/client/tunsetup.hpp:61:11: error: conversion from ‘openvpn::ActionList*’ to non-scalar type ‘openvpn::ActionList::Ptr {aka openvpn::RCPtr<openvpn::ActionList>}’ requested
class Setup : public TunBuilderSetup::Base
^
On GCC 8.2 (via devtoolset-8), this error did not occur at all. This
looks like a compiler bug, as declaring an empty Setup() constructor
resolves this issue. But we currently want to have GCC 4.8.5 compilers
functional, as it provides native RHEL-7 support without any use of
software collections.
Signed-off-by: David Sommerseth <davids@openvpn.net>
Since we now handle multiple replies from Netlink,
we need to pick if the gateway with longest route prefix
and lowest metric.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
When profile contains several remotes or single remote which
is resolved into multiple IP addresses AND all traffic is redirected
to the VPN, client will reconnect to the next remote if connection
is broken. Since all traffic is redirected to VPN, except traffic to
current remote, reconnect fails.
Currently this problem is solved by creating bypass routes
to all remotes before establishing connection, so that reconnect
won't go via broken VPN. This solution is sub-optimal, since
it leaks traffic to other remotes.
This patch implements a better approach. Before connecting to
remote, we create a bypass route just for this remote. On reconnect
we replace an old route with a new one for the new remote.
We piggyback on socket_protect() method of OpenVPNClient
which is called before opening connection to remote.
Connection to a new remote usually means a new IP address etc,
so to prevent traffic leakage we first create a new tun interface,
set up routes and then remove old routes and tear down old tun interface.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
When creating bypass route for server, it is better
to use gateway for server address instead of 0.0.0.0 or ::0.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This will be needed to exclude gateway on tun interface when
creating bypass route.
Note that this is required only for sitnl, since iproute-based routines
already ignore tun gateway.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Gateways are returned in multipart netlink
message, so we must properly handle those
instead of bailing out after reading first message.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
There are two ways how Linux tun can be manipulated -
by using iproute2 or netlink. Both implementations have
defined identical Setup class implementation.
This commit factors out Setup class from tun implementations
and templatizes it, which removes need in duplicated code.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Implement component that uses netlink to setup the tunnel
interface.
This new component gets rid of the "ip" commands and replaces
them with direct netlink calls.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Preserve tun and routes across reconnects. Store tun descriptor in
TunPersist object, which is member of TunClientFactory. Handle
add/remove commands inside TunBuilderSetup::Base instance, which is
owned by TunPersist.
Tunnel is recreated if new tunnel options are different from previous
ones.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Using LinuxGW46 instead of the obsolete get_default_gateway_v4()
allows us to correctly implement the bypass route for
redirect-gateway ipv6.
Signed-off-by: James Yonan <james@openvpn.net>
Created a lightweight abstraction layer so that another i/o
reactor can be dropped in place of asio.
The basic approach is to rename all references to asio::xxx
types to openvpn_io::xxx and then make openvpn_io a
preprocessor variable that points to the top-level namespace
of the i/o reactor implementation.
All of the source files that currently include <asio.hpp> now
include <openvpn/io/io.hpp> instead:
This gives us a lightweight abstraction layer that allows us
to define openvpn_io to be something other than asio.
Other changes:
* Inclusion of asio by scripts/build is now optional, and is
enabled by passing ASIO=1 or ASIO_DIR=<dir>.
* Refactored openvpn/common/socktypes.hpp to no longer
require asio.
* Refactored openvpn/log/logthread.hpp to no longer require
asio.
* Added openvpn::get_hostname() method as alternative to
calling asio directly.
* openvpn/openssl/util/init.hpp will now #error
if USE_ASIO is undefined.
Signed-off-by: James Yonan <james@openvpn.net>