Skip to contentSkip to conversation

Implement --mssfix handling for IPv6 packets

Openvpn-devel Applied Gert Doering 3 participants 4 messages Dec 2, 2012 – Dec 13, 2012

lore
Share & tools
lore
#0 lore raw

Hi,

in the next mail you'll find a patch to extend the existing --mssfix code to handle IPv6 packets as well.

The actual mssfix implementation is only about half the change, but I took the liberty to rename process_ipv4_header() to process_ip_header(), and (after discussion on IRC) the PIPV4_MSSFIX flag to PIP_MSSFIX - to make it obvious that this is no longer "IPv4 only".

The code has been tested on our corporate VPN server for 3 days now, and did what advertised - adjusted MSS; not breaking anything else. It does fix the connectivity problems one of my users had - sitting behind a router with broken PMTU handling *and* broken IPv4 fragment handling, which killed IPv6 SSH-Sessions (all crypted, not compressible) quite reliably.

Testing this is a bit tricky - the t_client framework won't cover it (as it doesn't do TCP payload tests yet), so to actually *see* the change you either need to have a broken network wrt IPv4 PMTU/fragment handling before, or look at TCP SYN / SYN ACK packets with wireshark.

Anyway, I believe it's ready for inclusion in RC2, and should most definitely be in 2.3-RELEASE (as we'll see more users with broken networks then).

gert

#1 lore raw

PATCH 1/1 Implement --mssfix handling for IPv6 packets.

Rename process_ipv4_header() to process_ip_header() and PIPV4_MSSFIX flag to PIP_MSSFIX, to make visible that it's no longer IPv4-only.

Inside process_ip_header(), call out to mss_fixup_ipv6() if --mssfix is active and IPv6 packet seen.

Rename mss_fixup() to mss_fixup_ipv4(), implement mss_fixup_ipv6().

---
 src/openvpn/forward.c |   26 +++++++++++++--------
 src/openvpn/forward.h |    4 +-
 src/openvpn/mss.c     |   57 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/openvpn/mss.h     |    3 +-
 src/openvpn/multi.c   |    6 ++--
 src/openvpn/proto.c   |   19 +++++++++++++--
 src/openvpn/proto.h   |    3 +-
 7 files changed, 97 insertions(+), 21 deletions(-)
src/openvpn/forward.c +16 -10
index 57c7846..024cd58 100644
@@ -985,9 +985,9 @@ process_incoming_tun (struct context *c)
     {
       /*
        * The --passtos and --mssfix options require
-       * us to examine the IPv4 header.
+       * us to examine the IP header (IPv4 or IPv6).
        */
-      process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
+      process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
 
 #ifdef PACKET_TRUNCATION_CHECK
       /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
@@ -1009,10 +1009,10 @@ process_incoming_tun (struct context *c)
 }
 
 void
-process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
+process_ip_header (struct context *c, unsigned int flags, struct buffer *buf)
 {
   if (!c->options.ce.mssfix)
-    flags &= ~PIPV4_MSSFIX;
+    flags &= ~PIP_MSSFIX;
 #if PASSTOS_CAPABILITY
   if (!c->options.passtos)
     flags &= ~PIPV4_PASSTOS;
@@ -1027,9 +1027,9 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
        * us to examine the IPv4 header.
        */
 #if PASSTOS_CAPABILITY
-      if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
+      if (flags & (PIPV4_PASSTOS|PIP_MSSFIX))
 #else
-      if (flags & PIPV4_MSSFIX)
+      if (flags & PIP_MSSFIX)
 #endif
 	{
 	  struct buffer ipbuf = *buf;
@@ -1042,8 +1042,8 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
 #endif
 			  
 	      /* possibly alter the TCP MSS */
-	      if (flags & PIPV4_MSSFIX)
-		mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+	      if (flags & PIP_MSSFIX)
+		mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
 
 #ifdef ENABLE_CLIENT_NAT
 	      /* possibly do NAT on packet */
@@ -1061,6 +1061,12 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
 		    route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
 		}
 	    }
+	  else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
+	    {
+	      /* possibly alter the TCP MSS */
+	      if (flags & PIP_MSSFIX)
+		mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+	    }
 	}
     }
 }
@@ -1217,9 +1223,9 @@ process_outgoing_tun (struct context *c)
 
   /*
    * The --mssfix option requires
-   * us to examine the IPv4 header.
+   * us to examine the IP header (IPv4 or IPv6).
    */
-  process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
+  process_ip_header (c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
 
   if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
     {
src/openvpn/forward.h +2 -2
index 0f829bd..1830a00 100644
@@ -228,12 +228,12 @@ void process_outgoing_tun (struct context *c);
 bool send_control_channel_string (struct context *c, const char *str, int msglevel);
 
 #define PIPV4_PASSTOS         (1<<0)
-#define PIPV4_MSSFIX          (1<<1)
+#define PIP_MSSFIX            (1<<1)         /* v4 and v6 */
 #define PIPV4_OUTGOING        (1<<2)
 #define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
 #define PIPV4_CLIENT_NAT      (1<<4)
 
-void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf);
+void process_ip_header (struct context *c, unsigned int flags, struct buffer *buf);
 
 #if P2MP
 void schedule_exit (struct context *c, const int n_seconds, const int signal);
src/openvpn/mss.c +56 -1

70 lines not on this page · raw message

src/openvpn/mss.h +2 -1
index 0b290c3..0d32943 100644
@@ -28,7 +28,8 @@
 #include "proto.h"
 #include "error.h"
 
-void mss_fixup (struct buffer *buf, int maxmss);
+void mss_fixup_ipv4 (struct buffer *buf, int maxmss);
+void mss_fixup_ipv6 (struct buffer *buf, int maxmss);
 void mss_fixup_dowork (struct buffer *buf, uint16_t maxmss);
 
 #endif
src/openvpn/multi.c +3 -3
index 9876b80..ab3f10c 100644
@@ -2411,13 +2411,13 @@ multi_get_queue (struct mbuf_set *ms)
 
   if (mbuf_extract_item (ms, &item)) /* cleartext IP packet */
     {
-      unsigned int pipv4_flags = PIPV4_PASSTOS;
+      unsigned int pip_flags = PIPV4_PASSTOS;
 
       set_prefix (item.instance);
       item.instance->context.c2.buf = item.buffer->buf;
       if (item.buffer->flags & MF_UNICAST) /* --mssfix doesn't make sense for broadcast or multicast */
-	pipv4_flags |= PIPV4_MSSFIX;
-      process_ipv4_header (&item.instance->context, pipv4_flags, &item.instance->context.c2.buf);
+	pip_flags |= PIP_MSSFIX;
+      process_ip_header (&item.instance->context, pip_flags, &item.instance->context.c2.buf);
       encrypt_sign (&item.instance->context, true);
       mbuf_free_buf (item.buffer);
 
src/openvpn/proto.c +16 -3
index 2cf8314..b437f1a 100644
@@ -36,11 +36,12 @@
 #include "memdbg.h"
 
 /*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv<X>, return true and increment
  * buffer offset to start of IP header.
  */
+static
 bool
-is_ipv4 (int tunnel_type, struct buffer *buf)
+is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver )
 {
   int offset;
   const struct openvpn_iphdr *ih;
@@ -68,12 +69,24 @@ is_ipv4 (int tunnel_type, struct buffer *buf)
 
   ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset);
 
-  if (OPENVPN_IPH_GET_VER (ih->version_len) == 4)
+  /* IP version is stored in the same bits for IPv4 or IPv6 header */
+  if (OPENVPN_IPH_GET_VER (ih->version_len) == ip_ver)
     return buf_advance (buf, offset);
   else
     return false;
 }
 
+bool
+is_ipv4 (int tunnel_type, struct buffer *buf)
+{
+    return is_ipv_X( tunnel_type, buf, 4 );
+}
+bool
+is_ipv6 (int tunnel_type, struct buffer *buf)
+{
+    return is_ipv_X( tunnel_type, buf, 6 );
+}
+
 #ifdef PACKET_TRUNCATION_CHECK
 
 void
src/openvpn/proto.h +2 -1
index 8cd4ede..f91e787 100644
@@ -219,10 +219,11 @@ struct ip_tcp_udp_hdr {
                              - sizeof(struct openvpn_tcphdr))
 
 /*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv4 or IPv6, return true and increment
  * buffer offset to start of IP header.
  */
 bool is_ipv4 (int tunnel_type, struct buffer *buf);
+bool is_ipv6 (int tunnel_type, struct buffer *buf);
 
 #ifdef PACKET_TRUNCATION_CHECK
 void ipv4_packet_size_verify (const uint8_t *data,
Signature · 1 line
1.7.8.6
#2 lore raw

Re: [Openvpn-devel] [PATCH] Implement --mssfix handling for IPv6 packets.

Am 02.12.12 22:11, schrieb Gert Doering:

Quoted 9 lines

Rename process_ipv4_header() to process_ip_header() and PIPV4_MSSFIX flag to PIP_MSSFIX, to make visible that it's no longer IPv4-only.

Inside process_ip_header(), call out to mss_fixup_ipv6() if --mssfix is active and IPv6 packet seen.

Rename mss_fixup() to mss_fixup_ipv4(), implement mss_fixup_ipv6().

I have no setup with broken mss but I looked through the patch and I think is the right fix.

Arne

#3 lore raw

Re: [Openvpn-devel] [PATCH] Implement --mssfix handling for IPv6 packets.

In reply to Gert Doering
Quoted 9 lines · Gert Doering

Rename process_ipv4_header() to process_ip_header() and PIPV4_MSSFIX flag to PIP_MSSFIX, to make visible that it's no longer IPv4-only.

Inside process_ip_header(), call out to mss_fixup_ipv6() if --mssfix is active and IPv6 packet seen.

Rename mss_fixup() to mss_fixup_ipv4(), implement mss_fixup_ipv6().

Quoted 9 lines
---
 src/openvpn/forward.c |   26 +++++++++++++--------
 src/openvpn/forward.h |    4 +-
 src/openvpn/mss.c     |   57 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/openvpn/mss.h     |    3 +-
 src/openvpn/multi.c   |    6 ++--
 src/openvpn/proto.c   |   19 +++++++++++++--
 src/openvpn/proto.h   |    3 +-
 7 files changed, 97 insertions(+), 21 deletions(-)

Applied in master and beta/2.3

commit f0e8997a874a89b3fe1f82109c443232e8967b01 (master) commit 729c8464021ff7c41a7fbb03501465eca55909a3 (beta/2.3)

Author: Gert Doering <[email protected]...>
Date:   Sun Dec 2 22:11:12 2012 +0100
    Implement --mssfix handling for IPv6 packets.

    Signed-off-by: Gert Doering <[email protected]...>
    Acked-by: Arne Schwabe <[email protected]...>
    Message-Id: [email protected]...
    URL: http://article.gmane.org/gmane.network.openvpn.devel/7173
    Signed-off-by: David Sommerseth <[email protected]...>
Signature · 3 lines
kind regards,

David Sommerseth