Discussion:
[Openvpn-devel] [PATCH 0/3] Support non-root operation using ocproxy
Kevin Cernekee
2014-04-13 05:16:53 UTC
Permalink
Sometimes it is desirable to establish VPN connections without setting
up a kernel tun/tap device. Possible use cases include:

- Routing traffic from different applications through different VPNs.

- Connecting to multiple VPNs (clients, sites, ...) that have
overlapping IP ranges.

- Connecting to multiple VPNs that each advertise their own default
route and/or DNS settings.

- Situations in which direct access to the VPN from all processes/UIDs
is not necessarily wanted, impairs performance, or presents an
unacceptable risk of intrusion or data leakage.

- Multiuser systems or container-based VPSes.

- Other situations in which the openvpn user or program is not trusted
to reconfigure a tun/tap device.

For a long time, OpenConnect has had the ability to run as non-root[1],
redirecting VPN traffic to/from a helper program over a socketpair.
ocproxy[2] was written to take advantage of this interface. Now I am
submitting changes to allow openvpn to be used in a similar manner.
Sample usage:

openvpn --config foo.ovpn \
--script-security 2 \
--dev "|/usr/bin/ocproxy -L 2222:unix-host:22 -D 11080"

The -D and -L flags work just like their equivalents on ssh, enabling port
forwarding and a SOCKS5 proxy on the specified local sockets.
"--dev-type tun" is assumed if unspecified. The IP configuration is
passed into ocproxy through "vpnc-script"-compatible environment variables.

This was tested on Linux with IPv4.

[1] http://www.infradead.org/openconnect/nonroot.html
[2] http://repo.or.cz/w/ocproxy.git


Kevin Cernekee (3):
Add S_NOWAIT and S_SETPGRP flags to openvpn_execve
Move MTU field into struct tuntap
Add "pipe to external program" device

doc/openvpn.8 | 29 +++++++++++++--
src/openvpn/init.c | 17 ++++++---
src/openvpn/misc.c | 9 ++++-
src/openvpn/misc.h | 6 ++--
src/openvpn/tun.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++----
src/openvpn/tun.h | 4 ++-
6 files changed, 149 insertions(+), 18 deletions(-)
--
1.7.9.5
Kevin Cernekee
2014-04-13 05:16:56 UTC
Permalink
Allow the tunneled traffic to be handled by an external program rather
than by a real tun/tap kernel device. This allows non-root users to
connect to a VPN through a userland TCP/IP stack.

Signed-off-by: Kevin Cernekee <***@gmail.com>
---
doc/openvpn.8 | 29 +++++++++++++--
src/openvpn/init.c | 12 +++++--
src/openvpn/tun.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++----
src/openvpn/tun.h | 2 ++
4 files changed, 132 insertions(+), 11 deletions(-)

diff --git a/doc/openvpn.8 b/doc/openvpn.8
index 3a58317..00efeb8 100644
--- a/doc/openvpn.8
+++ b/doc/openvpn.8
@@ -709,17 +709,42 @@ peers which will be initiating connections by using the
option.
.\"*********************************************************
.TP
-.B \-\-dev tunX | tapX | null
+.B \-\-dev tunX | tapX | null | <program>
TUN/TAP virtual network device (
.B X
can be omitted for a dynamic device.)

+.B tunX
+or
+.B tapX
+is the name of a network interface that openvpn will create.
+
+.B null
+is a special value used for testing only. It will not pass traffic.
+
+.B <program>
+is the full path to an executable, such as
+.B |/usr/bin/ocproxy,
+which will pass traffic to and from openvpn over a socketpair. This is an
+alternative to using a tun/tap interface to pass traffic to and from the
+OS kernel; unlike tun/tap it does not require any special privileges. The
+path must start with a `|' (pipe) character. This works with either
+.B \-\-dev-type tun
+or
+.B \-\-dev-type tap.
+If left unspecified, it will default to tun.
+
See examples section below
for an example on setting up a TUN device.

You must use either tun devices on both ends of the connection
or tap devices on both ends. You cannot mix them, as they
-represent different underlying network layers.
+represent different underlying network layers. Similarly, endpoints using
+device type
+.B null
+will only interoperate with other
+.B null
+endpoints.

.B tun
devices encapsulate IPv4 or IPv6 (OSI Layer 3) while
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 139c625..1158ad0 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1326,7 +1326,9 @@ do_route (const struct options *options,
const struct plugin_list *plugins,
struct env_set *es)
{
- if (!options->route_noexec && ( route_list || route_ipv6_list ) )
+ if (!options->route_noexec &&
+ !tt->is_pipe &&
+ ( route_list || route_ipv6_list ) )
{
add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
setenv_int (es, "redirect_gateway", route_did_redirect_default_gateway(route_list));
@@ -1450,6 +1452,7 @@ do_open_tun (struct context *c)
/* do ifconfig */
c->c1.tuntap->mtu = TUN_MTU_SIZE (&c->c2.frame);
if (!c->options.ifconfig_noexec
+ && !c->c1.tuntap->is_pipe
&& ifconfig_order () == IFCONFIG_BEFORE_TUN_OPEN)
{
/* guess actual tun/tap unit number that will be returned
@@ -1462,7 +1465,8 @@ do_open_tun (struct context *c)
}

/* possibly add routes */
- if (route_order() == ROUTE_BEFORE_TUN) {
+ if (route_order() == ROUTE_BEFORE_TUN
+ && !c->c1.tuntap->is_pipe) {
/* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */
do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
c->c1.tuntap, c->plugins, c->c2.es);
@@ -1476,11 +1480,13 @@ do_open_tun (struct context *c)
c->c1.tuntap);

/* set the hardware address */
- if (c->options.lladdr)
+ if (c->options.lladdr
+ && !c->c1.tuntap->is_pipe)
set_lladdr(c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es);

/* do ifconfig */
if (!c->options.ifconfig_noexec
+ && !c->c1.tuntap->is_pipe
&& ifconfig_order () == IFCONFIG_AFTER_TUN_OPEN)
{
do_ifconfig (c->c1.tuntap, c->c1.tuntap->actual_name, c->c2.es);
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 31bb583..c832528 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -103,6 +103,8 @@ dev_type_enum (const char *dev, const char *dev_type)
return DEV_TYPE_TAP;
else if (is_dev_type (dev, dev_type, "null"))
return DEV_TYPE_NULL;
+ else if (dev && *dev == '|')
+ return DEV_TYPE_TUN;
else
return DEV_TYPE_UNDEF;
}
@@ -425,6 +427,9 @@ init_tun (const char *dev, /* --dev option */
tt->type = dev_type_enum (dev, dev_type);
tt->topology = topology;

+ if (dev && *dev == '|')
+ tt->is_pipe = true;
+
if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
{
bool tun = false;
@@ -1290,6 +1295,67 @@ open_null (struct tuntap *tt)
tt->actual_name = string_alloc ("null", NULL);
}

+static void
+set_vpnc_vars (struct env_set *es, struct tuntap *tt)
+{
+ struct gc_arena gc = gc_new ();
+
+ setenv_str (es, "INTERNAL_IP4_ADDRESS", print_in_addr_t (tt->local, 0, &gc));
+ setenv_int (es, "INTERNAL_IP4_MTU", tt->mtu);
+
+ if (tt->ipv6 && tt->did_ifconfig_ipv6_setup)
+ {
+ const char *ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
+ struct buffer out6 = alloc_buf_gc (64, &gc);
+
+ buf_printf (&out6, "%s/%d", ifconfig_ipv6_local, tt->netbits_ipv6);
+ setenv_str (es, "INTERNAL_IP6_NETMASK", buf_bptr (&out6));
+ }
+
+ gc_free (&gc);
+}
+
+static void
+open_pipe (const char *dev, struct tuntap *tt)
+{
+ struct argv argv;
+ struct env_set *es;
+ int fds[2], pid;
+
+ if (socketpair (AF_UNIX, SOCK_DGRAM, 0, fds) == -1)
+ {
+ msg (M_FATAL | M_ERRNO, "ERROR: socketpair call failed");
+ }
+
+ tt->fd = fds[0];
+ tt->actual_name = string_alloc ("pipe", NULL);
+
+ set_nonblock (tt->fd);
+ set_cloexec (tt->fd);
+
+ es = env_set_create (NULL);
+ setenv_int (es, "VPNFD", fds[1]);
+ set_vpnc_vars (es, tt);
+
+ argv_init (&argv);
+ /* dev looks like: "|/path/to/program <args...>" */
+ argv_printf (&argv, "/bin/sh -c %s", &dev[1]);
+ pid = openvpn_execve (&argv, es, S_SCRIPT | S_NOWAIT | S_SETPGRP);
+ argv_reset (&argv);
+ env_set_destroy (es);
+ close (fds[1]);
+
+ /*
+ * This doesn't detect errors in the subprocess, but hopefully we'll notice
+ * if the other side of the socketpair gets closed.
+ */
+ if (pid <= 0)
+ {
+ msg (M_FATAL, "ERROR: unable to start subprocess");
+ }
+ tt->pipe_pid = (pid_t)pid;
+}
+

#if defined (TARGET_OPENBSD) || (defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H)

@@ -1385,7 +1451,11 @@ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
if ( tt->ipv6 && ! ipv6_explicitly_supported )
msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");

- if (tt->type == DEV_TYPE_NULL)
+ if (tt->is_pipe)
+ {
+ open_pipe (dev, tt);
+ }
+ else if (tt->type == DEV_TYPE_NULL)
{
open_null (tt);
}
@@ -1486,6 +1556,8 @@ close_tun_generic (struct tuntap *tt)
close (tt->fd);
if (tt->actual_name)
free (tt->actual_name);
+ if (tt->pipe_pid)
+ kill (-tt->pipe_pid, SIGHUP);
clear_tuntap (tt);
}

@@ -1579,11 +1651,15 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
{
struct ifreq ifr;

- /*
- * We handle --dev null specially, we do not open /dev/null for this.
- */
- if (tt->type == DEV_TYPE_NULL)
+ if (tt->is_pipe)
{
+ open_pipe (dev, tt);
+ }
+ else if (tt->type == DEV_TYPE_NULL)
+ {
+ /*
+ * We handle --dev null specially, we do not open /dev/null for this.
+ */
open_null (tt);
}
else
@@ -1880,6 +1956,12 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
*/
CLEAR(ifr);

+ if (tt->is_pipe)
+ {
+ open_pipe (dev, tt);
+ return;
+ }
+
if (tt->type == DEV_TYPE_NULL)
{
open_null (tt);
@@ -4849,7 +4931,13 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu

msg( M_INFO, "open_tun, tt->ipv6=%d", tt->ipv6 );

- if (tt->type == DEV_TYPE_NULL)
+ if (tt->is_pipe)
+ {
+ open_pipe (dev, tt);
+ gc_free (&gc);
+ return;
+ }
+ else if (tt->type == DEV_TYPE_NULL)
{
open_null (tt);
gc_free (&gc);
diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
index 1b510d0..0c93a1d 100644
--- a/src/openvpn/tun.h
+++ b/src/openvpn/tun.h
@@ -131,6 +131,8 @@ struct tuntap
# define TUNNEL_TOPOLOGY(tt) ((tt) ? ((tt)->topology) : TOP_UNDEF)
int topology; /* one of the TOP_x values */

+ bool is_pipe;
+ pid_t pipe_pid;
bool did_ifconfig_setup;
bool did_ifconfig_ipv6_setup;
bool did_ifconfig;
--
1.7.9.5
Kevin Cernekee
2014-04-13 05:16:54 UTC
Permalink
This is to let openvpn_execve be used to create a process that runs in
the background, and return its PID so that its process group can be nuked
on exit.

Signed-off-by: Kevin Cernekee <***@gmail.com>
---
src/openvpn/misc.c | 9 ++++++++-
src/openvpn/misc.h | 6 ++++--
2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 7483184..a8018ff 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -308,6 +308,11 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
pid = fork ();
if (pid == (pid_t)0) /* child side */
{
+ if (flags & S_SETPGRP)
+ {
+ if (setpgid (0, getpid ()) == -1)
+ msg (M_WARN | M_ERRNO, "openvpn_execve: setpgid failed");
+ }
execve (cmd, argv, envp);
exit (127);
}
@@ -315,7 +320,9 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
msg (M_ERR, "openvpn_execve: unable to fork");
else /* parent side */
{
- if (waitpid (pid, &ret, 0) != pid)
+ if (flags & S_NOWAIT)
+ ret = (int)pid;
+ else if (waitpid (pid, &ret, 0) != pid)
ret = -1;
}
}
diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h
index 41748bd..5b7aeee 100644
--- a/src/openvpn/misc.h
+++ b/src/openvpn/misc.h
@@ -86,8 +86,10 @@ void write_pid (const struct pid_state *state);
void warn_if_group_others_accessible(const char* filename);

/* system flags */
-#define S_SCRIPT (1<<0)
-#define S_FATAL (1<<1)
+#define S_SCRIPT (1<<0)
+#define S_FATAL (1<<1)
+#define S_NOWAIT (1<<2)
+#define S_SETPGRP (1<<3)

const char *system_error_message (int, struct gc_arena *gc);
--
1.7.9.5
Kevin Cernekee
2014-04-13 05:16:55 UTC
Permalink
open_tun() will need to access this value, so we'll store it alongside
the IP/netmask addresses.

Signed-off-by: Kevin Cernekee <***@gmail.com>
---
src/openvpn/init.c | 5 +++--
src/openvpn/tun.c | 2 +-
src/openvpn/tun.h | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index c2907cd..139c625 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1448,6 +1448,7 @@ do_open_tun (struct context *c)
do_init_route_ipv6_list (&c->options, c->c1.route_ipv6_list, false, c->c2.es);

/* do ifconfig */
+ c->c1.tuntap->mtu = TUN_MTU_SIZE (&c->c2.frame);
if (!c->options.ifconfig_noexec
&& ifconfig_order () == IFCONFIG_BEFORE_TUN_OPEN)
{
@@ -1457,7 +1458,7 @@ do_open_tun (struct context *c)
c->options.dev_type,
c->options.dev_node,
&gc);
- do_ifconfig (c->c1.tuntap, guess, TUN_MTU_SIZE (&c->c2.frame), c->c2.es);
+ do_ifconfig (c->c1.tuntap, guess, c->c2.es);
}

/* possibly add routes */
@@ -1482,7 +1483,7 @@ do_open_tun (struct context *c)
if (!c->options.ifconfig_noexec
&& ifconfig_order () == IFCONFIG_AFTER_TUN_OPEN)
{
- do_ifconfig (c->c1.tuntap, c->c1.tuntap->actual_name, TUN_MTU_SIZE (&c->c2.frame), c->c2.es);
+ do_ifconfig (c->c1.tuntap, c->c1.tuntap->actual_name, c->c2.es);
}

/* run the up script */
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 4df271d..31bb583 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -631,10 +631,10 @@ void delete_route_connected_v6_net(struct tuntap * tt,
void
do_ifconfig (struct tuntap *tt,
const char *actual, /* actual device name */
- int tun_mtu,
const struct env_set *es)
{
struct gc_arena gc = gc_new ();
+ int tun_mtu = tt->mtu;

if (tt->did_ifconfig_setup)
{
diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h
index 631b53c..1b510d0 100644
--- a/src/openvpn/tun.h
+++ b/src/openvpn/tun.h
@@ -150,6 +150,7 @@ struct tuntap
in_addr_t local;
in_addr_t remote_netmask;
in_addr_t broadcast;
+ int mtu;

struct in6_addr local_ipv6;
struct in6_addr remote_ipv6;
@@ -243,7 +244,6 @@ void init_tun_post (struct tuntap *tt,

void do_ifconfig (struct tuntap *tt,
const char *actual, /* actual device name */
- int tun_mtu,
const struct env_set *es);

bool is_dev_type (const char *dev, const char *dev_type, const char *match_type);
--
1.7.9.5
Gert Doering
2014-04-13 10:47:05 UTC
Permalink
Hi,
Post by Kevin Cernekee
Sometimes it is desirable to establish VPN connections without setting
- Routing traffic from different applications through different VPNs.
- Connecting to multiple VPNs (clients, sites, ...) that have
overlapping IP ranges.
- Connecting to multiple VPNs that each advertise their own default
route and/or DNS settings.
- Situations in which direct access to the VPN from all processes/UIDs
is not necessarily wanted, impairs performance, or presents an
unacceptable risk of intrusion or data leakage.
- Multiuser systems or container-based VPSes.
- Other situations in which the openvpn user or program is not trusted
to reconfigure a tun/tap device.
I can see that you might want that, but I do not think we want this in
OpenVPN.

It brings in a fair bit of extra code complexity, more arcane options, and
code that needs to maintained and tested across all supported platforms.

I think the goal can in most cases be achieved using SSH port forwarding -
or OpenConnect, or a myriad of other "tunnel this file descriptor for me"
tools. OpenVPN will do tun/tap, and do that well.

gert
--
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany ***@greenie.muc.de
fax: +49-89-35655025 ***@net.informatik.tu-muenchen.de
Kevin Cernekee
2014-04-13 14:39:18 UTC
Permalink
Post by Gert Doering
I think the goal can in most cases be achieved using SSH port forwarding -
or OpenConnect, or a myriad of other "tunnel this file descriptor for me"
tools. OpenVPN will do tun/tap, and do that well.
The problem with all of these alternatives (at least in my case) is
that the other end is already running OpenVPN, not one of the other
tools. Right now, there aren't a lot of good ways to connect to
somebody's OpenVPN service without running as root. Prior to this
work I had been using separate VMs.

Are there any changes you could suggest that would make this feature
more palatable?
Arne Schwabe
2014-04-13 15:19:08 UTC
Permalink
Post by Kevin Cernekee
Post by Gert Doering
I think the goal can in most cases be achieved using SSH port forwarding -
or OpenConnect, or a myriad of other "tunnel this file descriptor for me"
tools. OpenVPN will do tun/tap, and do that well.
The problem with all of these alternatives (at least in my case) is
that the other end is already running OpenVPN, not one of the other
tools. Right now, there aren't a lot of good ways to connect to
somebody's OpenVPN service without running as root. Prior to this
work I had been using separate VMs.
Are there any changes you could suggest that would make this feature
more palatable?
You could look at the TARGET_ANDROID. That uses the management interface
and fds over unix socket to achieve something similar.

Arne
Kevin Cernekee
2014-04-13 16:31:11 UTC
Permalink
You could look at the TARGET_ANDROID. That uses the management interface and
fds over unix socket to achieve something similar.
Do you think it would be feasible to enable TARGET_ANDROID by default
in the Linux OpenVPN builds, and change the logic so that if the user
passes e.g. "--android" it will accept commands over the management
socket instead of using the standard CLI?

This would not work with ocproxy as-is, but I could write a wrapper program.

Let me know if you think it's worth putting together a patch set.


BTW, here is an example of how my current patch works with an existing
OpenVPN service:

$ ./src/openvpn/openvpn --config /tmp/vpnbook/vpnbook-us1-udp25000.ovpn \
--verb 0 --script-security 2 \
--dev "|/usr/bin/ocproxy -D 12345" &
Sun Apr 13 08:46:44 2014 WARNING: file '/tmp/vpnbook/user.txt' is
group or others accessible
Sun Apr 13 08:46:44 2014 WARNING: No server certificate verification
method has been enabled. See http://openvpn.net/howto.html#mitm for
more info.
Sun Apr 13 08:46:44 2014 WARNING: this configuration may cache
passwords in memory -- use the auth-nocache option to prevent this

$ SOCKS5_SERVER=127.0.0.1:12345 socksify links -source ipchicken.com |
grep -A1 Address
Address:
198.7.62.204 </font></td>


Using port forwarding with "ocproxy -L", socksify, or FoxyProxy,
individual connections / applications / URLs can be seamlessly
forwarded over different VPN links. Or, if I omit the --dev option,
OpenVPN will fall back to standard "create tunX" behavior.
Arne Schwabe
2014-04-13 16:59:08 UTC
Permalink
Post by Kevin Cernekee
You could look at the TARGET_ANDROID. That uses the management interface and
fds over unix socket to achieve something similar.
Do you think it would be feasible to enable TARGET_ANDROID by default
in the Linux OpenVPN builds, and change the logic so that if the user
passes e.g. "--android" it will accept commands over the management
socket instead of using the standard CLI?
I am sure how invasive a patch that allows --android would be.

Arne
Jan Just Keijser
2014-04-14 07:19:21 UTC
Permalink
Hi
Post by Kevin Cernekee
You could look at the TARGET_ANDROID. That uses the management interface and
fds over unix socket to achieve something similar.
Do you think it would be feasible to enable TARGET_ANDROID by default
in the Linux OpenVPN builds, and change the logic so that if the user
passes e.g. "--android" it will accept commands over the management
socket instead of using the standard CLI?
I'd vote against enabling TARGET_ANDROID by default - there's a reason
the code is split into
TARGET_LINUX
TARGET_FREEBSD
TARGET_SOLARIS
etc and I'd say you're asking for trouble if you enable two TARGETs on
one platform.
Post by Kevin Cernekee
This would not work with ocproxy as-is, but I could write a wrapper program.
I do like the idea of not needing root access to run openvpn - esp
windows users could benefit from this, as they're not always allowed to
install the tap-win adapter. Then again, it goes against the UNIX/Linux
philosophy that each tool (e.g. openvpn) should do one thing and it
should do it well. By adding patches like this left and right we're
steering away from that philosophy.


cheers,

JJK
Kevin Cernekee
2014-04-14 16:15:51 UTC
Permalink
This post might be inappropriate. Click to display it.
David Woodhouse
2014-04-24 13:27:57 UTC
Permalink
Post by Jan Just Keijser
I do like the idea of not needing root access to run openvpn - esp
windows users could benefit from this, as they're not always allowed to
install the tap-win adapter. Then again, it goes against the UNIX/Linux
philosophy that each tool (e.g. openvpn) should do one thing and it
should do it well. By adding patches like this left and right we're
steering away from that philosophy.
I'm inclined to agree about the philosophy, but I think it's a design
decision made long ago in OpenVPN, and I wouldn't necessarily advocate
changing it.

One way of applying the UNIX philosophy in this context is to suggest
that the "one thing" that a VPN tool should do well is the transfer of
packets between an encrypted network link and a local one.

If you take a look at vpnc and openconnect, you'll see that the nasty
details of how you *configure* a network connection for every platform
under the sun was considered to be outside the scope. It was farmed out
to a separate tool, vpnc-script. Which allows us to *share* that
vpnc-script between the two clients rather than reproducing the effort.

If you look at the situation from that point of view, then yes — adding
"patches like this left and right" is definitely steering away from the
UNIX philosophy. But the "patches like this" could be seen to include
all the existing support for configuring specific platforms such as
Linux, *BSD, Solaris, Windows, OSX, Android, etc. :)

But there are good reasons why openvpn does this stuff for itself, and I
don't think it's very practical to change it. Kevin's patches are in
line with the existing design.

We have a lot of configuration cruft in openvpn, and fundamentally what
it does is give the core code a file descriptor that it can shove
packets in and out of. If Kevin offers a relatively clean way for that
file descriptor to be a UNIX dgram socket which we handed to a spawned
child process, instead of a handle to the kernel's /dev/net/tun device,
I don't see why we'd consider that a violation of the philosophy.
--
David Woodhouse Open Source Technology Centre
***@intel.com Intel Corporation
Loading...