0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00

DCOTransport: new routing code for trunk links

Also:

* removed IPCollisionDetectBase
* added ping-restart-override

Signed-off-by: James Yonan <james@openvpn.net>
This commit is contained in:
James Yonan 2019-07-03 08:18:35 -06:00
parent 5befbd430f
commit 089aec00b1

View File

@ -41,11 +41,9 @@
#include <openvpn/kovpn/korekey.hpp>
#include <openvpn/kovpn/kostats.hpp>
#include <openvpn/linux/procfs.hpp>
#include <openvpn/dco/ipcollbase.hpp>
#ifdef ENABLE_PG
#include <openvpn/kovpn/kodevtun.hpp>
#include <openvpn/kovpn/ipcoll.hpp>
#endif
// client-side DCO (Data Channel Offload) module for Linux/kovpn
@ -68,6 +66,7 @@ namespace openvpn {
DCO::TunConfig tun;
int trunk_unit = -1;
unsigned int ping_restart_override = 0;
virtual TunClientFactory::Ptr new_tun_factory(const DCO::TunConfig& conf, const OptionList& opt) override
{
@ -89,6 +88,9 @@ namespace openvpn {
// parse trunk-unit
trunk_unit = opt.get_num<decltype(trunk_unit)>("trunk-unit", 1, trunk_unit, 0, 511);
// parse ping-restart-override
ping_restart_override = opt.get_num<decltype(ping_restart_override)>("ping-restart-override", 1, ping_restart_override, 0, 3600);
return TunClientFactory::Ptr(this);
}
@ -195,7 +197,7 @@ namespace openvpn {
devconf.dc.peer_lookup = OVPN_PEER_LOOKUP_NONE;
devconf.dc.cpu_id = -1;
// create kovpn tun socket
// create kovpn tun socket (implementation in kodevtun.hpp)
impl.reset(new TunImpl(io_context,
devconf,
this,
@ -216,12 +218,6 @@ namespace openvpn {
transport_start_udp();
}
// VPN IP collision detection for multi-channel trunking
static void set_vpn_ip_collision(IPCollisionDetectBase* vpn_ip_collision_arg)
{
vpn_ip_collision = vpn_ip_collision_arg;
}
virtual bool transport_send_const(const Buffer& buf) override
{
return send(buf);
@ -323,47 +319,56 @@ namespace openvpn {
OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string());
// add/remove command lists
ActionList::Ptr add_cmds = new ActionList();
remove_cmds.reset(new ActionListReversed());
// configure tun properties
std::vector<IP::Route> rtvec;
if (config->trunk_unit >= 0)
{
// VPN IP collision detection, will throw on collision
if (vpn_ip_collision)
detect_vpn_ip_collision(*vpn_ip_collision, *po, config->trunk_unit, *remove_cmds);
// trunk setup
TunIPRoute::iface_config(state->iface_name,
config->trunk_unit,
*po,
nullptr,
*add_cmds,
*remove_cmds);
ovpn_peer_assign_route_id kri;
std::memset(&kri, 0, sizeof(kri));
kri.peer_id = peer_id;
kri.route_id = config->trunk_unit;
kri.allow_incoming = true;
kri.snat_flags = OVPN_SNAT_DEFAULT_ON | OVPN_SNAT_REQUIRED;
// Note that in trunking mode, kovpn must be
// configured for source routing.
add_vpn_ips_as_source_routes(*po, rtvec, IP::Addr::V4);
add_vpn_ips_as_source_routes(*po, rtvec, IP::Addr::V6);
// SNAT via VPN IPv4 addresses received from server
{
const TunBuilderCapture::RouteAddress *ra = po->vpn_ip(IP::Addr::V4);
if (ra)
kri.snat.a4 = IP::Addr(ra->address, "server-assigned-vpn4-addr", IP::Addr::V4).to_ipv4().to_in_addr();
}
// SNAT via VPN IPv6 addresses received from server
{
const TunBuilderCapture::RouteAddress *ra = po->vpn_ip(IP::Addr::V6);
if (ra)
kri.snat.a6 = IP::Addr(ra->address, "server-assigned-vpn6-addr", IP::Addr::V4).to_ipv6().to_in6_addr();
}
// kovpn route ID setup
KoTun::API::peer_assign_route_id(impl->native_handle(), &kri);
}
else
{
// add/remove command lists
ActionList::Ptr add_cmds = new ActionList();
remove_cmds.reset(new ActionListReversed());
// configure tun properties
std::vector<IP::Route> rtvec;
// non-trunk setup
TunIPRoute::TunMethods::tun_config(state->iface_name,
*po,
&rtvec,
*add_cmds,
*remove_cmds);
// Add routes to DCO implementation
impl->peer_add_routes(peer_id, rtvec);
// execute commands to bring up interface
add_cmds->execute_log();
}
// Add routes to DCO implementation
impl->peer_add_routes(peer_id, rtvec);
// execute commands to bring up interface
add_cmds->execute_log();
// Add a hook so ProtoContext will call back to
// rekey() on rekey ops.
dc_settings.set_factory(CryptoDCFactory::Ptr(new KoRekey::Factory(dc_settings.factory(), this, config->transport.frame)));
@ -371,12 +376,6 @@ namespace openvpn {
// signal that we are connected
tun_parent->tun_connected();
}
catch (const IPCollisionDetectBase::ip_collision& e)
{
// on VPN IP address collision, just reconnect to get a new address
stop_();
tun_parent->tun_error(Error::TUN_ERROR, e.what());
}
catch (const std::exception& e)
{
stop_();
@ -453,6 +452,10 @@ namespace openvpn {
transport_parent->disable_keepalive(ka.keepalive_ping,
ka.keepalive_timeout);
// Allow overide of keepalive timeout
if (config->ping_restart_override)
ka.keepalive_timeout = config->ping_restart_override;
// Modify the peer
impl->peer_set_keepalive(&ka);
}
@ -659,35 +662,6 @@ namespace openvpn {
return *static_cast<UDP*>(proto.get());
}
static void add_vpn_ips_as_source_routes(const TunBuilderCapture& pull,
std::vector<IP::Route>& rtvec,
const IP::Addr::Version ver)
{
const TunBuilderCapture::RouteAddress *ra = pull.vpn_ip(ver);
if (ra)
rtvec.push_back(IP::route_from_string_prefix(ra->address,
IP::Addr::version_size(ver),
"DCOTransport::Client::add_vpn_ips_as_source_routes",
ver));
}
// Throw an exception of type IPCollisionDetectBase::ip_collision
// if VPN IP is already in use by another client thread.
// This is intended to force a reconnect and obtain a
// new non-colliding address.
static void detect_vpn_ip_collision(IPCollisionDetectBase& ipcoll,
const TunBuilderCapture& pull,
unsigned int unit,
ActionList& remove)
{
const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4();
const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6();
if (local4)
ipcoll.add(local4->address, unit, remove);
if (local6)
ipcoll.add(local6->address, unit, remove);
}
// override for SessionStats::DCOTransportSource
virtual SessionStats::DCOTransportSource::Data dco_transport_stats_delta() override
{
@ -727,8 +701,6 @@ namespace openvpn {
SessionStats::DCOTransportSource::Data last_stats;
__u64 cc_rx_bytes = 0;
static IPCollisionDetectBase* vpn_ip_collision;
};
inline DCO::Ptr new_controller()
@ -750,8 +722,6 @@ namespace openvpn {
cli->tun_parent = &parent;
return TunClient::Ptr(cli);
}
IPCollisionDetectBase* Client::vpn_ip_collision; // GLOBAL
}
};