From patchwork Sat Dec 2 05:24:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 117 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director3.mail.ord1d.rsapps.net ([172.27.255.7]) by backend31.mail.ord1d.rsapps.net (Dovecot) with LMTP id 7fLnAG/UIlprLwAAgoeIoA for ; Sat, 02 Dec 2017 11:27:27 -0500 Received: from proxy2.mail.iad3a.rsapps.net ([172.27.255.7]) by director3.mail.ord1d.rsapps.net (Dovecot) with LMTP id w6WlIW/UIlpePAAAkXNnRw ; Sat, 02 Dec 2017 11:27:27 -0500 Received: from smtp14.gate.iad3a ([172.27.255.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.iad3a.rsapps.net (Dovecot) with LMTP id MghtHm/UIlobNAAABcWvHw ; Sat, 02 Dec 2017 11:27:27 -0500 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.34.181.88] Authentication-Results: smtp14.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.34.181.88"; 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-Classification-ID: af414aea-d77d-11e7-8068-b8ca3a5bbb60-1-1 Received: from [216.34.181.88] ([216.34.181.88:37516] helo=lists.sourceforge.net) by smtp14.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 8D/6E-04602-F64D22A5; Sat, 02 Dec 2017 11:27:27 -0500 Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.89) (envelope-from ) id 1eLAc2-0002po-IA; Sat, 02 Dec 2017 16:25:58 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.194] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) (envelope-from ) id 1eLAc0-0002ph-Qk for openvpn-devel@lists.sourceforge.net; Sat, 02 Dec 2017 16:25:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: 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=wxEZNJfIc5vf4FH2THTT8I4CPldgrsU/NUb2yeGuPk8=; b=GZHVhhrpuxALCPNuMfpDVxQrCb dCue9kzLpDtyNsDj3uwPqk/AS2hKbnGdyH/olsYUIOAGZYQuAZ3nnq1MnAwC0q9HXkTN87YknoaQU Dx0JeHgVI+NV1vDLEBMBlKJ/zyz3Y+hu32Ag1SD3fomdVBd7vmTQcpaQX5OTi3v0RvDU=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding: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=wxEZNJfIc5vf4FH2THTT8I4CPldgrsU/NUb2yeGuPk8=; b=F0fkFIEv1/zn6ZCMggv332z7tI LpUiKSST2CxgDgU8v1US5VUSC0LsZp++Jtb4tOTYYOlht/8Uy6T28b2Azxgp9lUxEaKQorYDECFU2 a165QOeV0ofOqWgP/I8w/biu3qT4FfDCSOKXXQo8R9K3S2mMO7tX+5aXUy+D8UKoKoA0=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) id 1eLAbz-0005FV-4u for openvpn-devel@lists.sourceforge.net; Sat, 02 Dec 2017 16:25:56 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Sun, 3 Dec 2017 00:24:53 +0800 Message-Id: <20171202162453.29838-2-a@unstable.cc> In-Reply-To: <20171202162453.29838-1-a@unstable.cc> References: <20171202162453.29838-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1eLAbz-0005FV-4u Subject: [Openvpn-devel] [PATCH 2/2] PF: never drop essential ICMPv6 packets 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 MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Some ICMPv6 packets can't be dropped otherwise the entire overlaying network layer (IPv6) would just stop working. Such packets are described in RFC4890, sec. 4.4.1. Improve the mroute packet parsing routine in order to detect these specific packets types and thus avoid PF to drop them. This way, when PF is enabled, the user won't need to whitelist any specific multicats IPv6 address. PF will just work as expected. Signed-off-by: Antonio Quartulli --- src/openvpn/mroute.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/openvpn/mroute.h | 4 ++- src/openvpn/multi.c | 19 +++++++++++--- src/openvpn/proto.h | 16 ++++++++++++ 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/src/openvpn/mroute.c b/src/openvpn/mroute.c index 8b364efd..68a440f6 100644 --- a/src/openvpn/mroute.c +++ b/src/openvpn/mroute.c @@ -126,6 +126,71 @@ mroute_is_mcast_ipv6(const struct in6_addr addr) } #ifdef ENABLE_PF +/** + * Return the ICMPv6 sub-packet type + * + * @param buf packet buffer pointing to the beginning of the IMCPv6 header + */ +static uint8_t +mroute_icmp6_get_type(const struct buffer *buf) +{ + const struct openvpn_icmp6hdr *icmp6; + + if (BLEN (buf) < (int) sizeof (struct openvpn_icmp6hdr)) + { + return 0; + } + + icmp6 = (const struct openvpn_icmp6hdr *) BPTR (buf); + + return icmp6->icmp6_type; +} + +/** + * Check if this IPv6 packet is essential to IPv6 basic communications and, + * therefore, should not be dropped (based on RFC4890, sec. 4.4.1) + * + * @param ipv6 pointer to the current IPv6 header + * @param buf packet buffer pointing to the beginning of the IPv6 header + */ +static bool +mroute_ipv6_should_not_drop(const struct openvpn_ipv6hdr *ipv6, + const struct buffer *buf) +{ + struct buffer b = *buf; + uint8_t type; + + /* packets to "save" are a subset of ICMPv6 */ + if (ipv6->nexthdr != IPPROTO_ICMPV6) + { + return false; + } + + if (!buf_advance (&b, sizeof (struct openvpn_ipv6hdr))) + { + return false; + } + + type = mroute_icmp6_get_type (&b); + + switch (type) + { + /* + * By following the guideline of RFC4890, sec. 4.4.1, the + * following are the ICMPv6 packet types that are strictly + * required to let a host join a IPv6 network. + * Therefore, such packets can't be dropped by PF. + */ + case OPENVPN_ND_ROUTER_SOLICIT: + case OPENVPN_ND_ROUTER_ADVERT: + case OPENVPN_ND_NEIGHBOR_SOLICIT: + case OPENVPN_ND_NEIGHBOR_ADVERT: + case OPENVPN_ND_INVERSE_SOLICIT: + case OPENVPN_ND_INVERSE_ADVERT: + return true; + } + return false; +} static unsigned int mroute_extract_addr_arp(struct mroute_addr *src, @@ -212,9 +277,15 @@ mroute_extract_addr_ip(struct mroute_addr *src, struct mroute_addr *dest, } ret |= MROUTE_EXTRACT_SUCCEEDED; + +#ifdef ENABLE_PF + if (mroute_ipv6_should_not_drop (ipv6, buf)) + { + ret |= MROUTE_EXTRACT_NO_DROP; + } +#endif } break; - default: msg(M_WARN, "IP packet with unknown IP version=%d seen", OPENVPN_IPH_GET_VER(*BPTR(buf))); diff --git a/src/openvpn/mroute.h b/src/openvpn/mroute.h index eacb1239..ab04c98a 100644 --- a/src/openvpn/mroute.h +++ b/src/openvpn/mroute.h @@ -41,13 +41,15 @@ #define MROUTE_EXTRACT_BCAST (1<<1) #define MROUTE_EXTRACT_MCAST (1<<2) #define MROUTE_EXTRACT_IGMP (1<<3) +#define MROUTE_EXTRACT_NO_DROP (1<<4) #define MROUTE_SEC_EXTRACT_SUCCEEDED (1<<(0+MROUTE_SEC_SHIFT)) #define MROUTE_SEC_EXTRACT_BCAST (1<<(1+MROUTE_SEC_SHIFT)) #define MROUTE_SEC_EXTRACT_MCAST (1<<(2+MROUTE_SEC_SHIFT)) #define MROUTE_SEC_EXTRACT_IGMP (1<<(3+MROUTE_SEC_SHIFT)) +#define MROUTE_SEC_EXTRACT_NO_DROP (1<<(4+MROUTE_SEC_SHIFT)) -#define MROUTE_SEC_SHIFT 4 +#define MROUTE_SEC_SHIFT 5 /* * Choose the largest address possible with diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 82a0b9d9..8b2afcd5 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -2627,7 +2627,8 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst { #ifdef ENABLE_PF struct mroute_addr edest; - mroute_addr_reset(&edest); + mroute_addr_reset (&edest); + unsigned int no_drop; #endif /* extract packet source and dest addresses */ mroute_flags = mroute_extract_addr_from_packet(&src, @@ -2676,10 +2677,20 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst } } #ifdef ENABLE_PF - if (c->c2.to_tun.len && !pf_addr_test(c, &edest, "tap_dest_addr")) + /* + * If a packet is marked as "do not drop", then no PF + * test has to be performed on it, but has to be allowed + * right away. + */ + no_drop = MROUTE_EXTRACT_NO_DROP | MROUTE_SEC_EXTRACT_NO_DROP; + if ((mroute_flags & MROUTE_SEC_EXTRACT_SUCCEEDED) && + !(mroute_flags & no_drop) && c->c2.to_tun.len && + !pf_addr_test(c, &edest, "tap_dest_addr")) { - msg(D_PF_DROPPED, "PF: client -> addr[%s] packet dropped by TAP packet filter", - mroute_addr_print_ex(&edest, MAPF_SHOW_ARP, &gc)); + msg(D_PF_DROPPED, + "PF: client -> addr[%s] packet dropped by TAP packet filter", + mroute_addr_print_ex(&edest, MAPF_SHOW_ARP, + &gc)); c->c2.to_tun.len = 0; } #endif diff --git a/src/openvpn/proto.h b/src/openvpn/proto.h index 57f25c90..48acc39e 100644 --- a/src/openvpn/proto.h +++ b/src/openvpn/proto.h @@ -120,6 +120,22 @@ struct openvpn_ipv6hdr { struct in6_addr daddr; }; +/* + * ICMPv6 header + */ +struct openvpn_icmp6hdr { +#define OPENVPN_ND_ROUTER_SOLICIT 133 +#define OPENVPN_ND_ROUTER_ADVERT 134 +#define OPENVPN_ND_NEIGHBOR_SOLICIT 135 +#define OPENVPN_ND_NEIGHBOR_ADVERT 136 +#define OPENVPN_ND_INVERSE_SOLICIT 141 +#define OPENVPN_ND_INVERSE_ADVERT 142 + uint8_t icmp6_type; + + uint8_t icmp6_code; + uint16_t icmp6_cksum; + uint8_t icmp6_dataun[4]; +}; /* * UDP header