net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* OpenVPN data channel offload
|
|
|
|
*
|
|
|
|
* Copyright (C) 2020-2025 OpenVPN, Inc.
|
|
|
|
*
|
|
|
|
* Author: Antonio Quartulli <antonio@openvpn.net>
|
|
|
|
* James Yonan <james@openvpn.net>
|
|
|
|
*/
|
|
|
|
|
2025-04-15 13:17:39 +02:00
|
|
|
#include <linux/ethtool.h>
|
2025-04-15 13:17:19 +02:00
|
|
|
#include <linux/genetlink.h>
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/netdevice.h>
|
2025-04-15 13:17:20 +02:00
|
|
|
#include <linux/inetdevice.h>
|
2025-04-15 13:17:25 +02:00
|
|
|
#include <net/gro_cells.h>
|
2025-04-15 13:17:20 +02:00
|
|
|
#include <net/ip.h>
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
#include <net/rtnetlink.h>
|
2025-04-15 13:17:20 +02:00
|
|
|
#include <uapi/linux/if_arp.h>
|
2025-04-15 13:17:19 +02:00
|
|
|
|
|
|
|
#include "ovpnpriv.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "netlink.h"
|
2025-04-15 13:17:20 +02:00
|
|
|
#include "io.h"
|
2025-04-15 13:17:22 +02:00
|
|
|
#include "peer.h"
|
2025-04-15 13:17:20 +02:00
|
|
|
#include "proto.h"
|
2025-04-15 13:17:28 +02:00
|
|
|
#include "tcp.h"
|
2025-04-15 13:17:25 +02:00
|
|
|
#include "udp.h"
|
|
|
|
|
2025-04-15 13:17:31 +02:00
|
|
|
static void ovpn_priv_free(struct net_device *net)
|
|
|
|
{
|
|
|
|
struct ovpn_priv *ovpn = netdev_priv(net);
|
|
|
|
|
|
|
|
kfree(ovpn->peers);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ovpn_mp_alloc(struct ovpn_priv *ovpn)
|
|
|
|
{
|
|
|
|
struct in_device *dev_v4;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ovpn->mode != OVPN_MODE_MP)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
dev_v4 = __in_dev_get_rtnl(ovpn->dev);
|
|
|
|
if (dev_v4) {
|
|
|
|
/* disable redirects as Linux gets confused by ovpn
|
|
|
|
* handling same-LAN routing.
|
|
|
|
* This happens because a multipeer interface is used as
|
|
|
|
* relay point between hosts in the same subnet, while
|
|
|
|
* in a classic LAN this would not be needed because the
|
|
|
|
* two hosts would be able to talk directly.
|
|
|
|
*/
|
|
|
|
IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false);
|
|
|
|
IPV4_DEVCONF_ALL(dev_net(ovpn->dev), SEND_REDIRECTS) = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the peer container is fairly large, therefore we allocate it only in
|
|
|
|
* MP mode
|
|
|
|
*/
|
|
|
|
ovpn->peers = kzalloc(sizeof(*ovpn->peers), GFP_KERNEL);
|
|
|
|
if (!ovpn->peers)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(ovpn->peers->by_id); i++) {
|
|
|
|
INIT_HLIST_HEAD(&ovpn->peers->by_id[i]);
|
|
|
|
INIT_HLIST_NULLS_HEAD(&ovpn->peers->by_vpn_addr4[i], i);
|
|
|
|
INIT_HLIST_NULLS_HEAD(&ovpn->peers->by_vpn_addr6[i], i);
|
|
|
|
INIT_HLIST_NULLS_HEAD(&ovpn->peers->by_transp_addr[i], i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2025-04-15 13:17:25 +02:00
|
|
|
static int ovpn_net_init(struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ovpn_priv *ovpn = netdev_priv(dev);
|
2025-04-15 13:17:31 +02:00
|
|
|
int err = gro_cells_init(&ovpn->gro_cells, dev);
|
|
|
|
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2025-04-15 13:17:25 +02:00
|
|
|
|
2025-04-15 13:17:31 +02:00
|
|
|
err = ovpn_mp_alloc(ovpn);
|
|
|
|
if (err < 0) {
|
|
|
|
gro_cells_destroy(&ovpn->gro_cells);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2025-04-15 13:17:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ovpn_net_uninit(struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ovpn_priv *ovpn = netdev_priv(dev);
|
|
|
|
|
|
|
|
gro_cells_destroy(&ovpn->gro_cells);
|
|
|
|
}
|
2025-04-15 13:17:19 +02:00
|
|
|
|
|
|
|
static const struct net_device_ops ovpn_netdev_ops = {
|
2025-04-15 13:17:25 +02:00
|
|
|
.ndo_init = ovpn_net_init,
|
|
|
|
.ndo_uninit = ovpn_net_uninit,
|
2025-04-15 13:17:20 +02:00
|
|
|
.ndo_start_xmit = ovpn_net_xmit,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct device_type ovpn_type = {
|
|
|
|
.name = OVPN_FAMILY_NAME,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct nla_policy ovpn_policy[IFLA_OVPN_MAX + 1] = {
|
|
|
|
[IFLA_OVPN_MODE] = NLA_POLICY_RANGE(NLA_U8, OVPN_MODE_P2P,
|
|
|
|
OVPN_MODE_MP),
|
2025-04-15 13:17:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ovpn_dev_is_valid - check if the netdevice is of type 'ovpn'
|
|
|
|
* @dev: the interface to check
|
|
|
|
*
|
|
|
|
* Return: whether the netdevice is of type 'ovpn'
|
|
|
|
*/
|
|
|
|
bool ovpn_dev_is_valid(const struct net_device *dev)
|
|
|
|
{
|
|
|
|
return dev->netdev_ops == &ovpn_netdev_ops;
|
|
|
|
}
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
|
2025-04-15 13:17:39 +02:00
|
|
|
static void ovpn_get_drvinfo(struct net_device *dev,
|
|
|
|
struct ethtool_drvinfo *info)
|
|
|
|
{
|
|
|
|
strscpy(info->driver, "ovpn", sizeof(info->driver));
|
|
|
|
strscpy(info->bus_info, "ovpn", sizeof(info->bus_info));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct ethtool_ops ovpn_ethtool_ops = {
|
|
|
|
.get_drvinfo = ovpn_get_drvinfo,
|
|
|
|
.get_link = ethtool_op_get_link,
|
|
|
|
.get_ts_info = ethtool_op_get_ts_info,
|
|
|
|
};
|
|
|
|
|
2025-04-15 13:17:20 +02:00
|
|
|
static void ovpn_setup(struct net_device *dev)
|
|
|
|
{
|
|
|
|
netdev_features_t feat = NETIF_F_SG | NETIF_F_GSO |
|
|
|
|
NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA;
|
|
|
|
|
|
|
|
dev->needs_free_netdev = true;
|
|
|
|
|
|
|
|
dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
|
|
|
|
|
2025-04-15 13:17:39 +02:00
|
|
|
dev->ethtool_ops = &ovpn_ethtool_ops;
|
2025-04-15 13:17:20 +02:00
|
|
|
dev->netdev_ops = &ovpn_netdev_ops;
|
|
|
|
|
2025-04-15 13:17:31 +02:00
|
|
|
dev->priv_destructor = ovpn_priv_free;
|
|
|
|
|
2025-04-15 13:17:20 +02:00
|
|
|
dev->hard_header_len = 0;
|
|
|
|
dev->addr_len = 0;
|
|
|
|
dev->mtu = ETH_DATA_LEN - OVPN_HEAD_ROOM;
|
|
|
|
dev->min_mtu = IPV4_MIN_MTU;
|
|
|
|
dev->max_mtu = IP_MAX_MTU - OVPN_HEAD_ROOM;
|
|
|
|
|
|
|
|
dev->type = ARPHRD_NONE;
|
|
|
|
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
|
|
|
dev->priv_flags |= IFF_NO_QUEUE;
|
2025-05-07 09:58:31 +02:00
|
|
|
/* when routing packets to a LAN behind a client, we rely on the
|
|
|
|
* route entry that originally brought the packet into ovpn, so
|
|
|
|
* don't release it
|
|
|
|
*/
|
|
|
|
netif_keep_dst(dev);
|
2025-04-15 13:17:20 +02:00
|
|
|
|
|
|
|
dev->lltx = true;
|
|
|
|
dev->features |= feat;
|
|
|
|
dev->hw_features |= feat;
|
|
|
|
dev->hw_enc_features |= feat;
|
|
|
|
|
|
|
|
dev->needed_headroom = ALIGN(OVPN_HEAD_ROOM, 4);
|
|
|
|
dev->needed_tailroom = OVPN_MAX_PADDING;
|
|
|
|
|
|
|
|
SET_NETDEV_DEVTYPE(dev, &ovpn_type);
|
|
|
|
}
|
|
|
|
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
static int ovpn_newlink(struct net_device *dev,
|
|
|
|
struct rtnl_newlink_params *params,
|
|
|
|
struct netlink_ext_ack *extack)
|
|
|
|
{
|
2025-04-15 13:17:20 +02:00
|
|
|
struct ovpn_priv *ovpn = netdev_priv(dev);
|
|
|
|
struct nlattr **data = params->data;
|
|
|
|
enum ovpn_mode mode = OVPN_MODE_P2P;
|
|
|
|
|
|
|
|
if (data && data[IFLA_OVPN_MODE]) {
|
|
|
|
mode = nla_get_u8(data[IFLA_OVPN_MODE]);
|
|
|
|
netdev_dbg(dev, "setting device mode: %u\n", mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
ovpn->dev = dev;
|
|
|
|
ovpn->mode = mode;
|
2025-04-15 13:17:22 +02:00
|
|
|
spin_lock_init(&ovpn->lock);
|
2025-04-15 13:17:33 +02:00
|
|
|
INIT_DELAYED_WORK(&ovpn->keepalive_work, ovpn_peer_keepalive_work);
|
2025-04-15 13:17:20 +02:00
|
|
|
|
2025-04-15 13:17:21 +02:00
|
|
|
/* Set carrier explicitly after registration, this way state is
|
|
|
|
* clearly defined.
|
|
|
|
*
|
|
|
|
* In case of MP interfaces we keep the carrier always on.
|
|
|
|
*
|
|
|
|
* Carrier for P2P interfaces is initially off and it is then
|
|
|
|
* switched on and off when the remote peer is added or deleted.
|
2025-04-15 13:17:20 +02:00
|
|
|
*/
|
2025-04-15 13:17:21 +02:00
|
|
|
if (ovpn->mode == OVPN_MODE_MP)
|
|
|
|
netif_carrier_on(dev);
|
|
|
|
else
|
|
|
|
netif_carrier_off(dev);
|
2025-04-15 13:17:20 +02:00
|
|
|
|
|
|
|
return register_netdevice(dev);
|
|
|
|
}
|
|
|
|
|
2025-04-15 13:17:22 +02:00
|
|
|
static void ovpn_dellink(struct net_device *dev, struct list_head *head)
|
|
|
|
{
|
|
|
|
struct ovpn_priv *ovpn = netdev_priv(dev);
|
|
|
|
|
2025-04-15 13:17:33 +02:00
|
|
|
cancel_delayed_work_sync(&ovpn->keepalive_work);
|
2025-04-15 13:17:31 +02:00
|
|
|
ovpn_peers_free(ovpn, NULL, OVPN_DEL_PEER_REASON_TEARDOWN);
|
2025-04-15 13:17:22 +02:00
|
|
|
unregister_netdevice_queue(dev, head);
|
|
|
|
}
|
|
|
|
|
2025-04-15 13:17:20 +02:00
|
|
|
static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ovpn_priv *ovpn = netdev_priv(dev);
|
|
|
|
|
|
|
|
if (nla_put_u8(skb, IFLA_OVPN_MODE, ovpn->mode))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
return 0;
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct rtnl_link_ops ovpn_link_ops = {
|
|
|
|
.kind = "ovpn",
|
|
|
|
.netns_refund = false,
|
2025-04-15 13:17:20 +02:00
|
|
|
.priv_size = sizeof(struct ovpn_priv),
|
|
|
|
.setup = ovpn_setup,
|
|
|
|
.policy = ovpn_policy,
|
|
|
|
.maxtype = IFLA_OVPN_MAX,
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
.newlink = ovpn_newlink,
|
2025-04-15 13:17:22 +02:00
|
|
|
.dellink = ovpn_dellink,
|
2025-04-15 13:17:20 +02:00
|
|
|
.fill_info = ovpn_fill_info,
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static int __init ovpn_init(void)
|
|
|
|
{
|
|
|
|
int err = rtnl_link_register(&ovpn_link_ops);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
pr_err("ovpn: can't register rtnl link ops: %d\n", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2025-04-15 13:17:19 +02:00
|
|
|
err = ovpn_nl_register();
|
|
|
|
if (err) {
|
|
|
|
pr_err("ovpn: can't register netlink family: %d\n", err);
|
|
|
|
goto unreg_rtnl;
|
|
|
|
}
|
|
|
|
|
2025-04-15 13:17:28 +02:00
|
|
|
ovpn_tcp_init();
|
|
|
|
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
return 0;
|
2025-04-15 13:17:19 +02:00
|
|
|
|
|
|
|
unreg_rtnl:
|
|
|
|
rtnl_link_unregister(&ovpn_link_ops);
|
|
|
|
return err;
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static __exit void ovpn_cleanup(void)
|
|
|
|
{
|
2025-04-15 13:17:19 +02:00
|
|
|
ovpn_nl_unregister();
|
net: introduce OpenVPN Data Channel Offload (ovpn)
OpenVPN is a userspace software existing since around 2005 that allows
users to create secure tunnels.
So far OpenVPN has implemented all operations in userspace, which
implies several back and forth between kernel and user land in order to
process packets (encapsulate/decapsulate, encrypt/decrypt, rerouting..).
With `ovpn` we intend to move the fast path (data channel) entirely
in kernel space and thus improve user measured throughput over the
tunnel.
`ovpn` is implemented as a simple virtual network device driver, that
can be manipulated by means of the standard RTNL APIs. A device of kind
`ovpn` allows only IPv4/6 traffic and can be of type:
* P2P (peer-to-peer): any packet sent over the interface will be
encapsulated and transmitted to the other side (typical OpenVPN
client or peer-to-peer behaviour);
* P2MP (point-to-multipoint): packets sent over the interface are
transmitted to peers based on existing routes (typical OpenVPN
server behaviour).
After the interface has been created, OpenVPN in userspace can
configure it using a new Netlink API. Specifically it is possible
to manage peers and their keys.
The OpenVPN control channel is multiplexed over the same transport
socket by means of OP codes. Anything that is not DATA_V2 (OpenVPN
OP code for data traffic) is sent to userspace and handled there.
This way the `ovpn` codebase is kept as compact as possible while
focusing on handling data traffic only (fast path).
Any OpenVPN control feature (like cipher negotiation, TLS handshake,
rekeying, etc.) is still fully handled by the userspace process.
When userspace establishes a new connection with a peer, it first
performs the handshake and then passes the socket to the `ovpn` kernel
module, which takes ownership. From this moment on `ovpn` will handle
data traffic for the new peer.
When control packets are received on the link, they are forwarded to
userspace through the same transport socket they were received on, as
userspace is still listening to them.
Some events (like peer deletion) are sent to a Netlink multicast group.
Although it wasn't easy to convince the community, `ovpn` implements
only a limited number of the data-channel features supported by the
userspace program.
Each feature that made it to `ovpn` was attentively vetted to
avoid carrying too much legacy along with us (and to give a clear cut to
old and probalby-not-so-useful features).
Notably, only encryption using AEAD ciphers (specifically
ChaCha20Poly1305 and AES-GCM) was implemented. Supporting any other
cipher out there was not deemed useful.
Both UDP and TCP sockets are supported.
As explained above, in case of P2MP mode, OpenVPN will use the main system
routing table to decide which packet goes to which peer. This implies
that no routing table was re-implemented in the `ovpn` kernel module.
This kernel module can be enabled by selecting the CONFIG_OVPN entry
in the networking drivers section.
NOTE: this first patch introduces the very basic framework only.
Features are then added patch by patch, however, although each patch
will compile and possibly not break at runtime, only after having
applied the full set it is expected to see the ovpn module fully working.
Cc: steffen.klassert@secunet.com
Cc: antony.antony@secunet.com
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Link: https://patch.msgid.link/20250415-b4-ovpn-v26-1-577f6097b964@openvpn.net
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-04-15 13:17:18 +02:00
|
|
|
rtnl_link_unregister(&ovpn_link_ops);
|
|
|
|
|
|
|
|
rcu_barrier();
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(ovpn_init);
|
|
|
|
module_exit(ovpn_cleanup);
|
|
|
|
|
|
|
|
MODULE_DESCRIPTION("OpenVPN data channel offload (ovpn)");
|
|
|
|
MODULE_AUTHOR("Antonio Quartulli <antonio@openvpn.net>");
|
|
|
|
MODULE_LICENSE("GPL");
|