From patchwork Wed Aug 3 21:14:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 2626 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director13.mail.ord1d.rsapps.net ([172.27.255.53]) by backend30.mail.ord1d.rsapps.net with LMTP id GJwHK9px62JzPQAAIUCqbw (envelope-from ) for ; Thu, 04 Aug 2022 03:14:34 -0400 Received: from proxy20.mail.iad3a.rsapps.net ([172.27.255.53]) by director13.mail.ord1d.rsapps.net with LMTP id OBvrKtpx62INcQAA91zNiA (envelope-from ) for ; Thu, 04 Aug 2022 03:14:34 -0400 Received: from smtp9.gate.iad3a ([172.27.255.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy20.mail.iad3a.rsapps.net with LMTPS id 0PS8I9px62LbeAAAtfLT2w (envelope-from ) for ; Thu, 04 Aug 2022 03:14:34 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp9.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 16f29404-13c5-11ed-9b53-52540097fc8c-1-1 Received: from [216.105.38.7] ([216.105.38.7:55926] helo=lists.sourceforge.net) by smtp9.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id DD/60-18962-9D17BE26; Thu, 04 Aug 2022 03:14:34 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.94.2) (envelope-from ) id 1oJV32-0007tH-1c; Thu, 04 Aug 2022 07:13:36 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1oJV31-0007tB-6t for openvpn-devel@lists.sourceforge.net; Thu, 04 Aug 2022 07:13:35 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=2CLEuQm0ErHDhaCFP0T9d43oLRLX1UweiZxWTgwFO6s=; b=ZuzLYELLdL8YswlB+3boWknB6x DhB8Dp00fzNtxTW0AY4Ngklx6vkCsJnXTKS2lCPiRqhVjWNKZBbOvqaTHH2hIYm/vAct6jYFWp2uy R309Da5cXYJZTaqH0GpVspzoXoWisynz+wpW/J5/yxq/Z1JjHD0xa0O/vnqztn9QHfmc=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=2CLEuQm0ErHDhaCFP0T9d43oLRLX1UweiZxWTgwFO6s=; b=FT9XTm4JRaDpZKQeNOZ1Ys+8RJ nIDCjVzJtvohEhhoFWv7fEELfr4QT2Aab+7fToPPGQqdaTbKBQOgnNONove9cKW612ENWCM1aVQtm Kc1syHZDqpbgQm1zLpdNj2JtH3MIEQ96Zfd0ZRk0XUXI9vz8aHpzxOyppoQ6K2iUUGq8=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.94.2) id 1oJV2y-002tI6-T1 for openvpn-devel@lists.sourceforge.net; Thu, 04 Aug 2022 07:13:34 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 4 Aug 2022 09:14:01 +0200 Message-Id: <20220804071401.12410-1-a@unstable.cc> In-Reply-To: <20220624083809.23487-14-a@unstable.cc> References: MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: With this change we introduce ovpn-dco support only along the p2p/client code path. Server codebase is still unchanged. Signed-off-by: Antonio Quartulli --- Changes from v1: * rebased --- src/openvpn/dco.c | 91 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/dco.h | 48 +++++++++++++++++++++++ src/openvpn/event.h | 3 ++ src/openvpn/forward.c | 63 + [...] Content analysis details: (0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1oJV2y-002tI6-T1 Subject: [Openvpn-devel] [PATCH v2 13/25] dco: implement dco support for p2p/client code path X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox With this change we introduce ovpn-dco support only along the p2p/client code path. Server codebase is still unchanged. Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- Changes from v1: * rebased --- src/openvpn/dco.c | 91 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/dco.h | 48 +++++++++++++++++++++++ src/openvpn/event.h | 3 ++ src/openvpn/forward.c | 63 ++++++++++++++++++++++++++++-- src/openvpn/init.c | 33 ++++++++++++++++ src/openvpn/init.h | 2 +- src/openvpn/socket.h | 1 + 7 files changed, 237 insertions(+), 4 deletions(-) diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index 8c22b7ea..b5cc8a70 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -36,6 +36,7 @@ #include "crypto.h" #include "dco.h" #include "errlevel.h" +#include "multi.h" #include "networking.h" #include "openvpn.h" #include "options.h" @@ -382,4 +383,94 @@ dco_check_pull_options(int msglevel, const struct options *o) return true; } +int +dco_p2p_add_new_peer(struct context *c) +{ + if (!dco_enabled(&c->options)) + { + return 0; + } + + + struct tls_multi *multi = c->c2.tls_multi; + struct link_socket *ls = c->c2.link_socket; + + struct in6_addr remote_ip6 = { 0 }; + struct in_addr remote_ip4 = { 0 }; + + struct in6_addr *remote_addr6 = NULL; + struct in_addr *remote_addr4 = NULL; + + const char *gw = NULL; + + ASSERT(ls->info.connection_established); + + /* In client mode if a P2P style topology is used we assume the + * remote-gateway is the IP of the peer */ + if (c->options.topology == TOP_NET30 || c->options.topology == TOP_P2P) + { + gw = c->options.ifconfig_remote_netmask; + } + if (c->options.route_default_gateway) + { + gw = c->options.route_default_gateway; + } + + /* These inet_pton conversion are fatal since options.c already implements + * checks to have only valid addresses when setting the options */ + if (c->options.ifconfig_ipv6_remote) + { + if (inet_pton(AF_INET6, c->options.ifconfig_ipv6_remote, &remote_ip6) != 1) + { + msg(M_FATAL, + "DCO peer init: problem converting IPv6 ifconfig remote address %s to binary", + c->options.ifconfig_ipv6_remote); + } + remote_addr6 = &remote_ip6; + } + + if (gw) + { + if (inet_pton(AF_INET, gw, &remote_ip4) != 1) + { + msg(M_FATAL, "DCO peer init: problem converting IPv4 ifconfig gateway address %s to binary", gw); + } + remote_addr4 = &remote_ip4; + } + else if (c->options.ifconfig_local) + { + msg(M_INFO, "DCO peer init: Need a peer VPN addresss to setup IPv4 (set --route-gateway)"); + } + + struct sockaddr *remoteaddr = &ls->info.lsa->actual.dest.addr.sa; + + int ret = dco_new_peer(&c->c1.tuntap->dco, multi->peer_id, + c->c2.link_socket->sd, NULL, remoteaddr, + remote_addr4, remote_addr6); + if (ret < 0) + { + return ret; + } + + c->c2.tls_multi->dco_peer_added = true; + c->c2.link_socket->info.dco_installed = true; + + return 0; +} + +void +dco_remove_peer(struct context *c) +{ + if (!dco_enabled(&c->options)) + { + return; + } + + if (c->c1.tuntap && c->c2.tls_multi && c->c2.tls_multi->dco_peer_added) + { + dco_del_peer(&c->c1.tuntap->dco, c->c2.tls_multi->peer_id); + c->c2.tls_multi->dco_peer_added = false; + } +} + #endif /* defined(ENABLE_DCO) */ diff --git a/src/openvpn/dco.h b/src/openvpn/dco.h index fbb35906..602dafb7 100644 --- a/src/openvpn/dco.h +++ b/src/openvpn/dco.h @@ -151,6 +151,36 @@ int init_key_dco_bi(struct tls_multi *multi, struct key_state *ks, */ void dco_update_keys(dco_context_t *dco, struct tls_multi *multi); +/** + * Install a new peer in DCO - to be called by a CLIENT (or P2P) instance + * + * @param c the main instance context + * @return 0 on success or a negative error code otherwise + */ +int dco_p2p_add_new_peer(struct context *c); + +/** + * Modify DCO peer options. Special values are 0 (disable) + * and -1 (do not touch). + * + * @param dco DCO device context + * @param peer_id the ID of the peer to be modified + * @param keepalive_interval keepalive interval in seconds + * @param keepalive_timeout keepalive timeout in seconds + * @param mss TCP MSS value + * + * @return 0 on success or a negative error code otherwise + */ +int dco_set_peer(dco_context_t *dco, unsigned int peerid, + int keepalive_interval, int keepalive_timeout, int mss); + +/** + * Remove a peer from DCO + * + * @param c the main instance context of the peer to remove + */ +void dco_remove_peer(struct context *c); + #else /* if defined(ENABLE_DCO) */ typedef void *dco_context_t; @@ -223,5 +253,23 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi) ASSERT(false); } +static inline bool +dco_p2p_add_new_peer(struct context *c) +{ + return true; +} + +static inline int +dco_set_peer(dco_context_t *dco, unsigned int peerid, + int keepalive_interval, int keepalive_timeout, int mss) +{ + return 0; +} + +static inline void +dco_remove_peer(struct context *c) +{ +} + #endif /* defined(ENABLE_DCO) */ #endif /* ifndef DCO_H */ diff --git a/src/openvpn/event.h b/src/openvpn/event.h index a472afbe..f2438f97 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -72,6 +72,9 @@ #define MANAGEMENT_WRITE (1 << (MANAGEMENT_SHIFT + WRITE_SHIFT)) #define FILE_SHIFT 8 #define FILE_CLOSED (1 << (FILE_SHIFT + READ_SHIFT)) +#define DCO_SHIFT 10 +#define DCO_READ (1 << (DCO_SHIFT + READ_SHIFT)) +#define DCO_WRITE (1 << (DCO_SHIFT + WRITE_SHIFT)) /* * Initialization flags passed to event_set_init diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 38d2683c..55c939c4 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1110,6 +1110,39 @@ process_incoming_link(struct context *c) perf_pop(); } +static void +process_incoming_dco(struct context *c) +{ +#if defined(ENABLE_DCO) && defined(TARGET_LINUX) + struct link_socket_info *lsi = get_link_socket_info(c); + dco_context_t *dco = &c->c1.tuntap->dco; + + dco_do_read(dco); + + if (dco->dco_message_type == OVPN_CMD_DEL_PEER) + { + trigger_ping_timeout_signal(c); + return; + } + + if (dco->dco_message_type != OVPN_CMD_PACKET) + { + msg(D_DCO_DEBUG, "%s: received message of type %u - ignoring", __func__, + dco->dco_message_type); + return; + } + + struct buffer orig_buff = c->c2.buf; + c->c2.buf = dco->dco_packet_in; + c->c2.from = lsi->lsa->actual; + + process_incoming_link(c); + + c->c2.buf = orig_buff; + buf_init(&dco->dco_packet_in, 0); +#endif /* if defined(ENABLE_DCO) && defined(TARGET_LINUX) */ +} + /* * Output: c->c2.buf */ @@ -1633,9 +1666,17 @@ process_outgoing_link(struct context *c) socks_preprocess_outgoing_link(c, &to_addr, &size_delta); /* Send packet */ - size = link_socket_write(c->c2.link_socket, - &c->c2.to_link, - to_addr); + if (c->c2.link_socket->info.dco_installed) + { + size = dco_do_write(&c->c1.tuntap->dco, + c->c2.tls_multi->peer_id, + &c->c2.to_link); + } + else + { + size = link_socket_write(c->c2.link_socket, &c->c2.to_link, + to_addr); + } /* Undo effect of prepend */ link_socket_write_post_size_adjust(&size, size_delta, &c->c2.to_link); @@ -1905,6 +1946,9 @@ io_wait_dowork(struct context *c, const unsigned int flags) #ifdef ENABLE_ASYNC_PUSH static int file_shift = FILE_SHIFT; #endif +#ifdef TARGET_LINUX + static int dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ +#endif /* * Decide what kind of events we want to wait for. @@ -2012,6 +2056,12 @@ io_wait_dowork(struct context *c, const unsigned int flags) */ socket_set(c->c2.link_socket, c->c2.event_set, socket, (void *)&socket_shift, NULL); tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)&tun_shift, NULL); +#if defined(TARGET_LINUX) + if (socket & EVENT_READ && c->c2.did_open_tun) + { + dco_event_set(&c->c1.tuntap->dco, c->c2.event_set, (void *)&dco_shift); + } +#endif #ifdef ENABLE_MANAGEMENT if (management) @@ -2134,4 +2184,11 @@ process_io(struct context *c) process_incoming_tun(c); } } + else if (status & DCO_READ) + { + if (!IS_SIG(c)) + { + process_incoming_dco(c); + } + } } diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 4423e162..340c75d9 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2106,6 +2106,22 @@ do_deferred_options_part2(struct context *c) return false; } + if (dco_enabled(&c->options) + && (c->options.ping_send_timeout || c->c2.frame.mss_fix)) + { + int ret = dco_set_peer(&c->c1.tuntap->dco, + c->c2.tls_multi->peer_id, + c->options.ping_send_timeout, + c->options.ping_rec_timeout, + c->c2.frame.mss_fix); + if (ret < 0) + { + msg(D_DCO, "Cannot set parameters for DCO peer (id=%u): %s", + c->c2.tls_multi->peer_id, strerror(-ret)); + return false; + } + } + return true; } @@ -2150,6 +2166,19 @@ do_up(struct context *c, bool pulled_options, unsigned int option_types_found) } } + if (c->mode == MODE_POINT_TO_POINT) + { + /* ovpn-dco requires adding the peer now, before any option can be set, + * but *after* having parsed the pushed peer-id in do_deferred_options() + */ + int ret = dco_p2p_add_new_peer(c); + if (ret < 0) + { + msg(D_DCO, "Cannot add peer to DCO: %s (%d)", strerror(-ret), ret); + return false; + } + } + /* do_deferred_options_part2() and do_deferred_p2p_ncp() *must* be * invoked after open_tun(). * This is required by DCO because we must have created the interface @@ -4363,6 +4392,10 @@ close_instance(struct context *c) /* free buffers */ do_close_free_buf(c); + /* close peer for DCO if enabled, needs peer-id so must be done before + * closing TLS contexts */ + dco_remove_peer(c); + /* close TLS */ do_close_tls(c); diff --git a/src/openvpn/init.h b/src/openvpn/init.h index 5f412a33..f53b65ee 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -30,7 +30,7 @@ * Baseline maximum number of events * to wait for. */ -#define BASE_N_EVENTS 4 +#define BASE_N_EVENTS 5 void context_clear(struct context *c); diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index a75adb00..0d521d22 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -120,6 +120,7 @@ struct link_socket_info sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/ bool bind_ipv6_only; int mtu_changed; /* Set to true when mtu value is changed */ + bool dco_installed; }; /*