- Used static_cast instead of direct type conversions in places where
it's safe
- Used numeric_cast where failure is possible
- Changed types of arguments and locals when practical
Signed-off-by: Charlie Vigue <charlie.vigue@openvpn.com>
Instead if displaying resolved family address (v4/v6),
display the one which is configured - either in ovpn profile
or config override options.
This is already the case for TCP.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
When parsing config, check DCO compatibility. Following
options break DCO compatibility:
- http-proxy
- compress
- comp-lzo
Same for config settings:
- non-preferred-algorithms
- legacy-algorithms
- proxyHost
DCO compatibility could be checked with
- bool EvalConfig::dcoCompatible
- std::string dcoIncompatibilityReason
If client nevertheless tries to connect, an exception
will be thrown:
connect error: option_error: dco_compatibility: config/options are not
compatible with dco
Fixes OVPN3-960.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This was introduced in commit
613aa6bf ("Win: support for local DNS resolvers")
but got removed by mistake in commit
fd065596 ("Merge release of OpenVPN Core library 3.6.4 to master")
Besides, this never worked for DCO, so fix that too.
Fixes OVPN3-964.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This is the result after running 'clang-format -i' on all C++ files and
headers, with the defined formatting rules in .clang-format.
Only the openvpn/common/unicode-impl.hpp has been excluded, as that is
mostly a copy of an external project.
Signed-off-by: David Sommerseth <davids@openvpn.net>
Add DcoTunPersist object to DCO::TunConfig.
DcoTunPersist stores:
- device handle
- tun settings
- adapter index/name
- pointer to TunSetup object, which itself
stores commands to undo tun settings
When intializing client options, instantiate DcoTunPersist
object within the scope of ClientConfig, which serves as
transport and tun factory for dco. Indicate that "sock" object
(device handle) should be preserved - not replaced when persisting
tun settings.
When establishing dco-win connection in OvpnDcoWinClient,
either use tun_persist created above (if persistance is enabled)
or instantiate it in-place (no persistance).
If nothing is stored in tun_persist (means this is first
connection or reconnect without persistance), acquire device
handle from tun_setup, wrap it into ASIO's basic_stream_handle
and store it in OvpnDcoWinClient - no need to persist it yet.
When starting tun, check if persisted tun session matches
to-be-created session. If no - clear previous tun settings,
set up tun and persist tun state. If device handle is already
stored in tun_persist, it won't be replaced.
On tun stop, send DEL_PEER command, which deletes peer
from the driver but keeps adapter in connected state. Then
close locally stored ASIO handle and reset tun_persist.
In case of "short term persistance" this will undo tun settings
and close device handle. For long term persistence, tun_persist
is also stored in ClientConfig and handle won't be closed yet.
In case of disconnect, ClientConfig::finalize(disconnect=true)
is called, which resets tun_persist, which in turn
undoes tun settings and closes device handle.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
OpenVPN 3.x has the same approach/problem for buffer allocation for the
tunnel packets that OpenVPN 2.x uses. Buffers are allocated very early
in the setup, so resizing/reacting to different frame sizes is not
really possible without major refactoring.
Therefore we use the same approach as with OpenVPN 2.x and allow a
MTU of up to 1600 by default and require setting tun-mtu-max in the
configuration file to allow larger values and allocate larger buffers.
Signed-off-by: Arne Schwabe <arne@openvpn.net>
Probe cipher support in runtime (works in Windows Server 2022 and Windows 11)
and add it to the list of allowed ciphers.
White on it, add missing halt check in dco-win client code.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add support for default mssfix, which is calculated
based on upper bound value 1492 minus payload and
encapculation overhead.
Payload overhead includes:
- compression byte (except for V2, which doesn't add overhead)
- pktid (in CBC)
- IPv4 and TCP headers
Encapculation overhead:
- crypto overhead (for AEAD 16 bytes auth tag, 4 bytes pktid, 4 bytes opcode/peer-id = 24)
- 2 bytes packet size for TCP transport
Also for CBC we must take padding [1..blocksize] into account.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add missing halt etc checks.
Replace dco_error with fatal exception ErrorCode(TUN_SETUP_FAILED).
IOCTL commands are not expected to fail and of they do, threat it as fatal error.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
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>
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>
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>
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>
- 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>
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>
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>