]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Add --bind-dev option.
authorMaximilian Wilhelm <max@sdn.clinic>
Mon, 29 Jun 2020 10:49:07 +0000 (12:49 +0200)
committerGert Doering <gert@greenie.muc.de>
Mon, 29 Jun 2020 11:15:22 +0000 (13:15 +0200)
This options allows the user to specify a network interface or VRF
device the OpenVPN process should use when making a connection or
binding to an address.

This is done by setting the SO_BINDTODEVICE option to the corresponding
socket (on Linux).  SO_BINDTODEVICE forces all packets sent on that socket
to go out via the specified interface, and only packets coming in on
that interface are received by OpenVPN.

When used in a VRF context on Linux [0], you can also specify the name
of the VRF ("--bind-dev external_vrf"), which will put the OpenVPN
"network side" into this VRF.  This allows making connections using a
non-default VRF and having the tun/tap interface in the default VRF.

Thanks to David Ahern (Cumulus Networks) for insights on this.

[0] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/vrf.txt

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1593427748-29801-2-git-send-email-max@rfc2324.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg20156.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/init.c
src/openvpn/options.c
src/openvpn/options.h
src/openvpn/socket.c
src/openvpn/socket.h

index 2af25c1ac35a70415a15f01574ecb727755dd6cd..dd1747f337e65a3f485e6725b6f7283f2329caf8 100644 (file)
@@ -3445,6 +3445,7 @@ do_init_socket_1(struct context *c, const int mode)
                             c->options.rcvbuf,
                             c->options.sndbuf,
                             c->options.mark,
+                            c->options.bind_dev,
                             &c->c2.server_poll_interval,
                             sockflags);
 }
index 9580d1d276575d7b14a02279a7fe57c32b155c69..34e2bfd3dbdd67546d061b8b1293cfc35f746bdb 100644 (file)
@@ -294,6 +294,9 @@ static const char usage_message[] =
 #if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK
     "--mark value    : Mark encrypted packets being sent with value. The mark value\n"
     "                  can be matched in policy routing and packetfilter rules.\n"
+    "--bind-dev dev  : Bind to the given device when making connection to a peer or\n"
+    "                  listening for connections. This allows sending encrypted packets\n"
+    "                  via a VRF present on the system.\n"
 #endif
     "--txqueuelen n  : Set the tun/tap TX queue length to n (Linux only).\n"
 #ifdef ENABLE_MEMSTATS
@@ -6084,6 +6087,13 @@ add_option(struct options *options,
             }
         }
     }
+#ifdef TARGET_LINUX
+    else if (streq (p[0], "bind-dev") && p[1])
+    {
+        VERIFY_PERMISSION (OPT_P_SOCKFLAGS);
+        options->bind_dev = p[1];
+    }
+#endif
     else if (streq(p[0], "txqueuelen") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_GENERAL);
index 375a4fc971281f260da2231a3da8998b9f07e26f..c83a46aa6bc29b3b922e78bd106159ffa982ce8d 100644 (file)
@@ -352,6 +352,7 @@ struct options
 
     /* mark value */
     int mark;
+    char *bind_dev;
 
     /* socket flags */
     unsigned int sockflags;
index f2fb54da3ccaad76bf81123ccdb76fa1efbb0784..61463bcd23856b32d7362674df884ace0a37b55e 100644 (file)
@@ -1138,6 +1138,18 @@ create_socket(struct link_socket *sock, struct addrinfo *addr)
     /* set socket to --mark packets with given value */
     socket_set_mark(sock->sd, sock->mark);
 
+#if defined(TARGET_LINUX)
+    if (sock->bind_dev)
+    {
+        msg (M_INFO, "Using bind-dev %s", sock->bind_dev);
+        if (setsockopt (sock->sd, SOL_SOCKET, SO_BINDTODEVICE, sock->bind_dev, strlen (sock->bind_dev) + 1) != 0)
+        {
+            msg(M_WARN|M_ERRNO, "WARN: setsockopt SO_BINDTODEVICE=%s failed", sock->bind_dev);
+        }
+
+    }
+#endif
+
     bind_local(sock, addr->ai_family);
 }
 
@@ -1880,6 +1892,7 @@ link_socket_init_phase1(struct link_socket *sock,
                         int rcvbuf,
                         int sndbuf,
                         int mark,
+                        const char *bind_dev,
                         struct event_timeout *server_poll_timeout,
                         unsigned int sockflags)
 {
@@ -1906,6 +1919,7 @@ link_socket_init_phase1(struct link_socket *sock,
 
     sock->sockflags = sockflags;
     sock->mark = mark;
+    sock->bind_dev = bind_dev;
 
     sock->info.proto = proto;
     sock->info.af = af;
index 38e5138d257af70cd139091762f8e8e1121a140e..8db9e8bae73f6ffa62918a5cb9734fe2003dc9de 100644 (file)
@@ -212,6 +212,7 @@ struct link_socket
 #define SF_GETADDRINFO_DGRAM (1<<4)
     unsigned int sockflags;
     int mark;
+    const char *bind_dev;
 
     /* for stream sockets */
     struct stream_buf stream_buf;
@@ -326,6 +327,7 @@ link_socket_init_phase1(struct link_socket *sock,
                         int rcvbuf,
                         int sndbuf,
                         int mark,
+                        const char *bind_dev,
                         struct event_timeout *server_poll_timeout,
                         unsigned int sockflags);
 /* Reenable uncrustify *INDENT-ON* */