While using GeNLImpl::available() for ovpn-dco works, it requires more
privileges than currently granted by SElinux for openvpn3-linux to work.
Instead of extending the privileges, add method tun_builder_dco_available()
to the TUN builder API, so that the check can be done context sensitive
by the client.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
Take option value if pushed for the next round of remote address
caching.
Since the push replies are processed in Session, we need to extend the
transport slightly to process pushed options. There was no need so far,
since transport options are used before the session starts. The remote
cache timeout is currently the only exception to this rule.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
DCO only supports a limited set of ciphers, currently it is
discovered quite late if a unsupported algorithm is configured
(or pushed).
This introduces CryptoAlgs::allow_dc_algs() with which the
supported set of data channel algorithms can be specified.
The DCO code makes use of this, at the time a new_controller()
is created.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
The DCO component now implements the SessionStats::DCOTransportSource interface.
This interface is already used by ovpncli.cpp to retrieve the peer stats
from DCO.
With this patch, also the OvpnDcoCli object can be used to retrieve the
peer stats from kernel space.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
After invoking the get_peer() API, let the DCOClient component
extract the statistics and store them locally.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
If DCO support is compiled in, detect if it is available (i.e. Windows driver
or Linux kernel module is loaded) and then use it, if it is.
This changes the default configuration for DCO from off to on, so users of
the library need to set ClientAPI::Config::dco to false in case they do not
want to use dco for a connection.
The change is also reflected in the reference client "ovpncli". If DCO is
enabled in a build, it will detect and use it. The previously available
"ovpncliovpndco" and "ovpncliovpndcowin" clients have thus been removed.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
The TunBuilder implementation needs to know which peer to send the
control packet to and for this reason the ovpndcocli component is now
prepending the data with 4 bytes representing the peer-id of the
destination.
Since this approach is incompatible with sending a const Buffer (as it
cannot be modified), send() has to allocate a temporary buffer for the
purpose.
While at it, make transport_send(Buffer) obsolete, as ovpndcocli
is not expected to handle data packets (sent as non-const).
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
We are trying to adhere to the LLVM style as dictated by clang-format.
For this reason reformat all files in the dco/ subfolder with:
clang-fromat --style=LLVM -i $filename
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
With the recent changes in ovpn-dco, aimed at accommodating the new
multi-peer logic, userspace has to adapt as well in order to follow the
expected flow. In particular we require userspace to act as following:
1) create TCP/UDP transport socket towards peer/server;
2) perform initial handshare over TCP/UDP socket
3) when handshake is complete, add peer/server to ovpn-dco kernel module
via CMD_NEW_PEER by passing peer address, port and socket fd;
4) handle further control channel communication over netlink.
To implement the logic above, the OvpnDcoClient has lost its
"Protowrapper" template and now it basically implemente the
TransportClient and TransportParent at the same time.
This way, it can instantiate a TCP/UDP TransportClient internally and
use it for point 1 and 2. This change greatly simplify the OvpnDcoClient
itself as several operations are directly handled by the TCP/UDP
TransportClient.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
This adds support for various transport protocols to tunbuilder
code branch of ovpn-dco support code, which is used by openvpn3-linux
client.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
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>
- add tunbuilder support to OvpnDcoClient
Linux client uses core library in non-privileged
process which cannot do modify routing, add/remove interfaces etc.
Those operartions are executed in separate privileged
process via tunbuilder API.
- pass data between userspace/kernel via pipe
In Linux client, control channel packets are handled by
unprivileged process, which doesn't have direct access to netlink
socket to talk directly to kernel module. In order to enable
communication with kernel by unprivileged process, receiving side
of tunbuilder API, which itself is ran in privileged process,
creates socketpair and connects netlink socket with another socket,
which is passed back to unprivileged process. Unpriviled process
uses that socket to communicate with kernel module instead of GeNL
object.
- remove remnants of kovpn support from tunbuilder and tunbuilder
support from kovpn tun/transport client.
Kovpn doesn't need tunbuilder support, so relevant code is removed.
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>
In preparation for ovpn-dco support, move kovpn-specific code
out of KoRekey::Key into own Korekey::KovpnKey class.
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>
Add tun/transport client skeleton for ovpn-dco,
which doesn't do any work except creating/removing
ovpn-dco device.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
As other transport clients, call socket_protect()
before establishing connection.
This gives ability to create bypass route.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
In preparation of ovpn-dco support, split dco transport
client into two parts:
- generic dco support in dcocli.hpp
- kovpn-specific code in kovpncli.hpp
Add build directory (used by VS Code) to .gitignore
Use #pragma once instead of #ifndef/#define/#endif
Signed-off-by: Lev Stipakov <lev@openvpn.net>
- use explicit for non copy single argument constructor
- add override where applicable
Signed-off-by: Arne Schwabe <arne@openvpn.net>
Signed-off-by: David Sommerseth <davids@openvpn.net>
Commit 089aec00b pulled in a dependency for a very server specific
feature not normally needed in more basic implementations. This
resulted in the code not being able to compile unless the advanced
implementation would be available. This only happens when ENABLE_DCO is
enabled.
Signed-off-by: David Sommerseth <davids@openvpn.net>
That API was introduced in commit 5c00943
to implement persistence for macOS. That functionality
was refactored in 0609c76, but framework was left intact.
Since socket_protect() is called almost at the
same time as ip_hole_punch() and also receives
remote address, there is no need in this unused
API anymore.
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>
When ASIO performs an async DNS resolution, it relies on the
getaddrinfo() syscall in order to obtain a result.
This syscall is non-interruptible by design, which means that, in case
of sudden stop command received by the user, the core will not be able
to terminate all its threads until the getaddrinfo() has returned
(either by timeout or with a result).
If the the external core user is synchronously waiting for it to
terminate (i.e. like a UI), this behaviour will lead to the entire
client hanging.
To avoid this issue, this commit converts each asynchronous DNS
resolution to a synchrnous one performed in a detached thread.
This way, if the core wants to stop, it can do so without waiting for
the DNS thread to join. Otherwise, this change should not lead to any
functional difference.
Signed-off-by: Yuriy Barnovych <yuriy@openvpn.net>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>