Skip to contentSkip to conversation

Add 1:1 network mapping option (--netmap)

PATCH In review Andrea Bonomi 2 participants 4 messages Sep 10, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add 1:1 network mapping option (--netmap)

Dear Developers,
I developed a patch for implementing 1:1 NAT (something similar to the iptables NETMAP target). This is useful in situations when you have the same (private) network address behind clients. For example, consider the following scenario:

-lan1--192.168.0.0/24-- -lan2--192.168.0.0/24--

          |                             |
    gw1 192.168.0.1              gw2 192.168.0.1
          |                             | 
       [tunnel]-----OpenVPN server---[tunnel]
                        |
                     [tunnel]
                        |
                    clients…

The clients have to access to both the machines in lan1 and lan2, This patch allow to map all the address of a network, e.g.
[to g1] push "netmap 172.16.1.0/24 192.168.0.0/24"
[to g2] push "netmap 172.16.2.0/24 192.168.0.0/24"
The clients can access to, e.g. 192.168.0.79 on lan1 using the IP 172.16.1.79.

Regards,
Andrea

:: e n d i a n
:: security with passion

:: andrea bonomi
:: http://www.endian.com :: [email protected]...

---
 src/openvpn/Makefile.am             |    1 +
 src/openvpn/forward.c               |   10 +-
 src/openvpn/netmap.c                |  238 +++++++++++++++++++++++++++++++++++
 src/openvpn/netmap.h                |   53 ++++++++
 src/openvpn/openvpn.vcxproj         |    1 +
 src/openvpn/openvpn.vcxproj.filters |    3 +
 src/openvpn/options.c               |   19 +++
 src/openvpn/options.h               |   10 ++
 8 files changed, 333 insertions(+), 2 deletions(-)
 create mode 100644 src/openvpn/netmap.c
 create mode 100644 src/openvpn/netmap.h
src/openvpn/Makefile.am +1 -0
index 5d38628..eee5117 100644
@@ -73,6 +73,7 @@ openvpn_SOURCES = \
 	mtu.c mtu.h \
 	mudp.c mudp.h \
 	multi.c multi.h \
+	netmap.c netmap.h \
 	ntlm.c ntlm.h \
 	occ.c occ.h occ-inline.h \
 	pkcs11.c pkcs11.h pkcs11_backend.h \
src/openvpn/forward.c +8 -2
index 57c7846..fc52cae 100644
@@ -1026,15 +1026,21 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
        * The --passtos and --mssfix options require
        * us to examine the IPv4 header.
        */
+
 #if PASSTOS_CAPABILITY
-      if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
+      if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX) || c->options.netmap_enabled)
 #else
-      if (flags & PIPV4_MSSFIX)
+      if (flags & PIPV4_MSSFIX || c->options.netmap_enabled)
 #endif
 	{
 	  struct buffer ipbuf = *buf;
 	  if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
 	    {
+              if (c->options.netmap_enabled)
+                {
+	          do_netmap(&c->options.netmaps, flags, &ipbuf);
+	        }
+
 #if PASSTOS_CAPABILITY
 	      /* extract TOS from IP header */
 	      if (flags & PIPV4_PASSTOS)
src/openvpn/netmap.c new file +238 -0

238 lines not on this page · raw message

src/openvpn/netmap.h new file +53 -0

53 lines not on this page · raw message

src/openvpn/openvpn.vcxproj +1 -0
index 3b2340e..633b881 100755
@@ -128,6 +128,7 @@
     <ClCompile Include="mtu.c" />
     <ClCompile Include="mudp.c" />
     <ClCompile Include="multi.c" />
+    <ClCompile Include="netmap.c" />
     <ClCompile Include="ntlm.c" />
     <ClCompile Include="occ.c" />
     <ClCompile Include="openvpn.c" />
src/openvpn/openvpn.vcxproj.filters +3 -0
index 40336ba..4b26efb 100644
@@ -108,6 +108,9 @@
     <ClCompile Include="multi.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="netmap.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="ntlm.c">
       <Filter>Source Files</Filter>
     </ClCompile>
src/openvpn/options.c +19 -0
index d25bbea..7e5684e 100644
@@ -239,6 +239,9 @@ static const char usage_message[] =
   "                  Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
   "--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
   "                  the default gateway.  Useful when pushing private subnets.\n"
+  "--netmap source dest [netmask]: Add a 1:1 mapping of network address\n"
+  "                  'source' is the local network to be remapped into 'dest'\n"
+  "                  on the other side of the tunnel\n"
 #ifdef ENABLE_CLIENT_NAT
   "--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT rule.\n"
 #endif
@@ -870,6 +873,7 @@ init_options (struct options *o, const bool init_gc)
   }
 #endif /* WIN32 */
 #endif /* P2MP_SERVER */
+  o->netmaps.size = 0;
 }
 
 void
@@ -2759,6 +2763,9 @@ pre_pull_save (struct options *o)
       o->pre_pull->tuntap_options = o->tuntap_options;
       o->pre_pull->tuntap_options_defined = true;
       o->pre_pull->foreign_option_index = o->foreign_option_index;
+      o->pre_pull->netmaps = o->netmaps;
+      o->pre_pull->netmaps_defined = true;
+
       if (o->routes)
 	{
 	  o->pre_pull->routes = clone_route_option_list(o->routes, &o->gc);
@@ -2789,6 +2796,10 @@ pre_pull_restore (struct options *o)
       if (pp->tuntap_options_defined)
 	  o->tuntap_options = pp->tuntap_options;
 
+      CLEAR (o->netmaps);
+      if (pp->netmaps_defined)
+	  o->netmaps = pp->netmaps;
+
       if (pp->routes_defined)
 	{
 	  rol_check_alloc (o);
@@ -5115,6 +5126,14 @@ add_option (struct options *options,
 	}
       options->max_routes = max_routes;
     }
+  else if (streq (p[0], "netmap") && p[1])
+    {
+      VERIFY_PERMISSION (OPT_P_ROUTE);
+      if (!add_netmap_to_option_list(&options->netmaps, p[1], p[2], p[3], msglevel)) {
+	  goto err;
+      }
+      options->netmap_enabled = true;
+    }
   else if (streq (p[0], "route-gateway") && p[1])
     {
       VERIFY_PERMISSION (OPT_P_ROUTE_EXTRAS);
src/openvpn/options.h +10 -0
index 306520b..7b697d5 100644
@@ -34,6 +34,7 @@
 #include "common.h"
 #include "mtu.h"
 #include "route.h"
+#include "netmap.h"
 #include "tun.h"
 #include "socket.h"
 #include "plugin.h"
@@ -76,6 +77,9 @@ struct options_pre_pull
   struct client_nat_option_list *client_nat;
 #endif
 
+  bool netmaps_defined;
+  struct netmap_option_list netmaps;
+
   int foreign_option_index;
 };
 
@@ -347,6 +351,11 @@ struct options
   struct client_nat_option_list *client_nat;
 #endif
 
+  /** Network map */
+  int max_netmaps;
+  struct netmap_option_list netmaps;
+  bool netmap_enabled;
+
 #ifdef ENABLE_OCC
   /* Enable options consistency check between peers */
   bool occ;
@@ -624,6 +633,7 @@ struct options
 #define OPT_P_SOCKBUF         (1<<25)
 #define OPT_P_SOCKFLAGS       (1<<26)
 #define OPT_P_CONNECTION      (1<<27)
+#define OPT_P_NETMAP          (1<<28)
 
 #define OPT_P_DEFAULT   (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
 
Signature · 1 line
1.7.9.5
#1 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 6 lines · Andrea Bonomi

Dear Developers, I developed a patch for implementing 1:1 NAT (something similar to the iptables NETMAP target). This is useful in situations when you have the same (private) network address behind clients. For example, consider the following scenario:

-lan1--192.168.0.0/24-- -lan2--192.168.0.0/24-- |

Quoted 8 lines
| gw1 192.168.0.1              gw2 192.168.0.1 |
| [tunnel]-----OpenVPN server---[tunnel] | [tunnel] | clients…

The clients have to access to both the machines in lan1 and lan2, This patch allow to map all the address of a network, e.g. [to g1] push "netmap 172.16.1.0/24 192.168.0.0/24" [to g2] push "netmap 172.16.2.0/24 192.168.0.0/24" The clients can access to, e.g. 192.168.0.79 on lan1 using the IP 172.16.1.79.

Hi Andrea,

First of all, thanks a lot for your efforts here! I just have one question ... how does this differ from the --client-nat feature in the code base for OpenVPN v2.3? (git master or alpha releases)

- From the man page:

--client-nat snat|dnat network netmask alias
This pushable client option sets up a stateless one-to-one NAT rule on packet addresses (not ports), and is useful in cases where routes or ifconfig settings pushed to the client would cre? ate an IP numbering conflict.

network/netmask (for example
192.168.0.0/255.255.0.0) defines the local view of a resource from the client perspective, while alias/netmask (for example 10.64.0.0/255.255.0.0) defines the remote view from the server perspec? tive.

Use snat (source NAT) for resources owned by the client and dnat (destination NAT) for remote resources.

Set --verb 6 for debugging info showing the transformation of src/dest addresses in packets.

kind regards,

David Sommerseth
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlBN/eUACgkQDC186MBRfrqGzACfWvH91GXH6+Jc0EQ42conCEhZ IqQAoKojc8X/H0kn4wyFQtIKzhyzND9f
=BrY7
-----END PGP SIGNATURE-----

#2 lore raw

There no difference, it's exactly the same feature.
The next time I promise to check better before implementing something that already exist. Sorry,
Andrea Bonomi
:: e n d i a n
:: security with passion

:: andrea bonomi
:: http://www.endian.com :: [email protected]...

Quoted 60 lines · David Sommerseth

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 6 lines · Andrea Bonomi

Dear Developers, I developed a patch for implementing 1:1 NAT (something similar to the iptables NETMAP target). This is useful in situations when you have the same (private) network address behind clients. For example, consider the following scenario:

-lan1--192.168.0.0/24-- -lan2--192.168.0.0/24-- |

Quoted 8 lines
| gw1 192.168.0.1              gw2 192.168.0.1 |
| [tunnel]-----OpenVPN server---[tunnel] | [tunnel] | clients…

The clients have to access to both the machines in lan1 and lan2, This patch allow to map all the address of a network, e.g. [to g1] push "netmap 172.16.1.0/24 192.168.0.0/24" [to g2] push "netmap 172.16.2.0/24 192.168.0.0/24" The clients can access to, e.g. 192.168.0.79 on lan1 using the IP 172.16.1.79.

Hi Andrea,

First of all, thanks a lot for your efforts here! I just have one question ... how does this differ from the --client-nat feature in the code base for OpenVPN v2.3? (git master or alpha releases)

- From the man page:

--client-nat snat|dnat network netmask alias
This pushable client option sets up a stateless one-to-one NAT rule on packet addresses (not ports), and is useful in cases where routes or ifconfig settings pushed to the client would cre? ate an IP numbering conflict.

network/netmask (for example
192.168.0.0/255.255.0.0) defines the local view of a resource from the client perspective, while alias/netmask (for example 10.64.0.0/255.255.0.0) defines the remote view from the server perspec? tive.

Use snat (source NAT) for resources owned by the client and dnat (destination NAT) for remote resources.

Set --verb 6 for debugging info showing the transformation of src/dest addresses in packets.

kind regards,

David Sommerseth
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlBN/eUACgkQDC186MBRfrqGzACfWvH91GXH6+Jc0EQ42conCEhZ IqQAoKojc8X/H0kn4wyFQtIKzhyzND9f
=BrY7
-----END PGP SIGNATURE-----

#3 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 3 lines · Andrea Bonomi

There no difference, it's exactly the same feature. The next time I promise to check better before implementing something that already exist. Sorry,

No worries, I'm just sorry for you spending time on implementing this feature too. But good to know we know have the feature you need :)

Feel free to come back with other improvements whenever you have something up your sleeve. But to avoid such issues in the future, you may also try to get in touch with us on #openvpn-devel on FreeNode (IRC). There are often people there having enough overview to give a good recommendation to further progress.

kind regards,

David Sommerseth

Quoted 43 lines · David Sommerseth
Quoted 10 lines · Andrea Bonomi
Quoted 10 lines
Quoted 10 lines

Dear Developers, I developed a patch for implementing 1:1 NAT (something similar to the iptables NETMAP target). This is useful in situations when you have the same (private) network address behind clients. For example, consider the following scenario:

-lan1--192.168.0.0/24-- -lan2--192.168.0.0/24-- | | gw1
192.168.0.1 gw2 192.168.0.1 | |
[tunnel]-----OpenVPN server---[tunnel] | [tunnel] | clients…

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

The clients have to access to both the machines in lan1 and lan2, This patch allow to map all the address of a network, e.g. [to g1] push "netmap 172.16.1.0/24 192.168.0.0/24" [to g2] push "netmap 172.16.2.0/24 192.168.0.0/24" The clients can access to, e.g. 192.168.0.79 on lan1 using the IP 172.16.1.79.

Hi Andrea,

First of all, thanks a lot for your efforts here! I just have one question ... how does this differ from the --client-nat feature in the code base for OpenVPN v2.3? (git master or alpha releases)

- From the man page:

--client-nat snat|dnat network netmask alias This pushable client option sets up a stateless one-to-one NAT rule on packet addresses (not ports), and is useful in cases where routes or ifconfig settings pushed to the client would cre? ate an IP numbering conflict.

network/netmask (for example
192.168.0.0/255.255.0.0) defines the local view of a resource from the client perspective, while alias/netmask (for example 10.64.0.0/255.255.0.0) defines the remote view from the server perspec? tive.

Use snat (source NAT) for resources owned by the client and dnat (destination NAT) for remote resources.

Quoted 9 lines

Set --verb 6 for debugging info showing the transformation of src/dest addresses in packets.

kind regards,

David Sommerseth

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlBOCQAACgkQDC186MBRfrrlkACfQVEFhJLJk4w6LSLGfDSjk+Pn OSAAnAq1VVMM5Fj6mm1C40clBFEvRRIT
=8Gqh
-----END PGP SIGNATURE-----