Change the way Tunnelblick starts OpenVPN?

79 views
Skip to first unread message

Nicolas

unread,
Dec 11, 2017, 10:01:56 AM12/11/17
to tunnelblick-discuss
Hi,

I spent some time investigating an issue with TunnelBlick + OpenVPN + PKCS#11 + PC/SC + Smartcard (this problem is discussed here)…

Currently, TunnelBlick starts OpenVPN with the --daemon option, and with this option, OpenVPN forks after the first initializations to daemonize.. That fork seems to be the reason why OpenVPN then fails to use the PC/SC library…

According to the daemon(3) manpage, the daemon function is deprecated in Mac OS X; Apple recommends to use launchd instead.

In order to work around the issue with PC/SC, I tried a very ugly hack: I replaced the real openvpn binary with a script that generates a launchd plist and loads it with launchctl to start the real openvpn binary (without the --daemon option), and it works.

Given that launchd appears to be the “Apple-blessed” way to start daemons, do you think a patch that uses launchd and launchct to start and stop OpenVPN might be accepted? I know very little about objective-C and MacOS X programming, so I’d rather not loose too much time if there’s something inherently wrong with the idea, or if there’s no chance my patch gets accepted.


Cheers,

--
Nicolas

Tunnelblick developer

unread,
Dec 11, 2017, 11:08:42 AM12/11/17
to tunnelblick-discuss
Thanks for your work looking into this.

I would consider a patch. I have two concerns, though:
  • I'm not sure how to detect that OpenVPN failed before actually trying to connect a VPN -- for example, if there are bad options in the configuration file. I don't think that launchd provides such feedback. Currently, Tunnelblick just waits until OpenVPN returns, which always happens quickly: either when an error occurs and it can't proceed, or no error occurs and it has forked a new process to connect the VPN.

    It might work to wait for some period of time for OpenVPN to process its arguments and if it hasn't exited by that time, assume that it is running and trying to connect the VPN. Setting such a time limit so it works properly on both quiet and busy systems (and with fast and slow processors) might be tricky.

    An alternative might be to assume it failed and rely on feedback (or the lack thereof) via OpenVPN's management interface to indicate a problem (or lack of a problem).

  • I don't know what (if any) other side effects there might be if we don't use the OpenVPN --daemon option. I don't trust that the OpenVPN documentation fully lists what --deamon does I probably wouldn't want to make such a change without providing a way to run OpenVPN either way (that is, as it is done now with --deamon, and the new way using launchd).
I think such a patch would involve replacing line 2665 of tunnelblick-helper.m:

    status = runAsRoot(openvpnPath, arguments, 0755);

with a call to a new "runAsRootUsingLaunchd" function. That function would need to do all the checking that runAsRoot does, of course. (Which probably means that the checking should be put into a routine that both runAsRoot() and runAsRootUsingLaunchd() would use.)

Before you spend a lot of time on this, let me think about it some more and maybe do some experiments.

And, again, thanks for your work looking into this.

Tunnelblick developer

unread,
Dec 11, 2017, 12:18:52 PM12/11/17
to tunnelblick-discuss
OK, I've thought about it : )

I have another idea: perhaps the problem (issue with TunnelBlick + OpenVPN + PKCS#11 + PC/SC + Smartcard) is really that Tunnelblick is ignoring some message from OpenVPN's management interface. To check that, use the following Terminal command to have Tunnelblick do some extra logging:

defaults write net.tunnelblick.tunnelblick DB-AU -bool yes

and then try to connect. The Console log should contain a lot more info, including all the commands that OpenVPN sends Tunnelblick. You can filter in Console using "tunnelblick", and then post the entries for the time that you tried to connect.

When done, you can disable the extra logging with
defaults delete net.tunnelblick.tunnelblick DB-AU

Nicolas

unread,
Dec 11, 2017, 12:49:51 PM12/11/17
to tunnelbli...@googlegroups.com
Hi,

On Mon, Dec 11, 2017 at 08:08:41AM -0800, Tunnelblick developer wrote:
> Thanks for your work looking into this.

No problem.
That’s the reason why I love free software: if I have a problem, I can
(try to) fix it myself.


> I would consider a patch. I have two concerns, though:
>
> - I'm not sure how to detect that OpenVPN failed before actually trying
> to connect a VPN -- for example, if there are bad options in the
> configuration file. I don't think that launchd provides such
> feedback. Currently, Tunnelblick just waits until OpenVPN returns, which
> always happens quickly: either when an error occurs and it can't proceed,
> or no error occurs and it has forked a new process to connect the VPN.

To be honnest, I share your concern. I think the traditional UNIX way to
launch daemons is simple and efficient. I don’t really understand why
Apple decided to make simple things complex with launchd. (And most
linux distros follow the same route with systemd…)


> It might work to wait for some period of time for OpenVPN to process its
> arguments and if it hasn't exited by that time, assume that it is running
> and trying to connect the VPN. Setting such a time limit so it works
> properly on both quiet and busy systems (and with fast and slow processors)
> might be tricky.
>
> An alternative might be to assume it failed and rely on feedback (or the
> lack thereof) via OpenVPN's management interface to indicate a problem (or
> lack of a problem).

I think that might be the best option.


> - I don't know what (if any) other side effects there might be if we
> don't use the OpenVPN --daemon option. I don't trust that the OpenVPN
> documentation fully lists what --deamon does I probably wouldn't want to
> make such a change without providing a way to run OpenVPN either way (that
> is, as it is done now with --deamon, and the new way using launchd).

I had a look at the OpenVPN code, and I did not see anything besides the
code in the daemon function, that does fork(), setsid(), chdir("/") and
replace STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO with /dev/null.


> I think such a patch would involve replacing line 2665 of
> tunnelblick-helper.m:
>
> * status = runAsRoot(openvpnPath, arguments, 0755);*
>
> with a call to a new "runAsRootUsingLaunchd" function. That function would
> need to do all the checking that runAsRoot does, of course. (Which probably
> means that the checking should be put into a routine that both runAsRoot()
> and runAsRootUsingLaunchd() would use.)
>
> Before you spend a lot of time on this, let me think about it some more and
> maybe do some experiments.

No problem. If you wish to experiment with it, I may send you the
quick&dirty script I wrote to replace the openvpn binary.


On Mon, Dec 11, 2017 at 09:18:51AM -0800, Tunnelblick developer wrote:
> OK, I've thought about it : )

That was fast! :-)


> I have another idea: perhaps the problem (issue with
> TunnelBlick + OpenVPN + PKCS#11 + PC/SC + Smartcard) is really that
> Tunnelblick is ignoring some message from OpenVPN's management interface.

I don’t think so: I tried to capture the traffic on the management
interface with tcpdump, and I did not see any unexpected message from
OpenVPN to TunnelBlick.


> To check that, use the following Terminal command to have Tunnelblick do
> some extra logging:
>
> *defaults write net.tunnelblick.tunnelblick DB-AU -bool yes*
>
>
> and then try to connect. The Console log should contain a lot more info,
> including all the commands that OpenVPN sends Tunnelblick. You can filter
> in Console using "tunnelblick", and then post the entries for the time that
> you tried to connect.
>
> When done, you can disable the extra logging with
>
> *defaults delete net.tunnelblick.tunnelblick DB-AU*

Anyway, I’ll give it a try tomorrow.


Cheers,

--
Nicolas

Nicolas Boullis

unread,
Dec 12, 2017, 9:20:27 AM12/12/17
to tunnelbli...@googlegroups.com
On Mon, Dec 11, 2017 at 09:18:51AM -0800, Tunnelblick developer wrote:
> OK, I've thought about it : )
>
> I have another idea: perhaps the problem (issue with
> TunnelBlick + OpenVPN + PKCS#11 + PC/SC + Smartcard) is really that Tunnelblick
> is ignoring some message from OpenVPN's management interface. To check that,
> use the following Terminal command to have Tunnelblick do some extra logging:
>
>
> defaults write net.tunnelblick.tunnelblick DB-AU -bool yes
>
>
> and then try to connect. The Console log should contain a lot more info,
> including all the commands that OpenVPN sends Tunnelblick. You can filter in
> Console using "tunnelblick", and then post the entries for the time that you
> tried to connect.
>
> When done, you can disable the extra logging with
>
> defaults delete net.tunnelblick.tunnelblick DB-AU

I gave it a try, as promised, but with no success.
I ran the command you gave to enable extra logging. I checked with
“defaults read net.tunnelblick.tunnelblick” that it worked (it did).
I lauched the Console application and searched for “tunnelblick”. Then I
tried to connect the VPN in the Tunnelblick menu.
Then nothing appears in the concole besides messages from the openvpn
process, PCSC library: “communication with ctkpcscd failed”…
I don’t see the messages from OpenVPN’s management interface.

Sorry if I’m missing something obvious, I’m quite a Mac OS newbie (much
more a linux guy).


Cheers,

--
Nicolas

Tunnelblick developer

unread,
Dec 12, 2017, 10:04:04 AM12/12/17
to tunnelblick-discuss
OK, thanks for trying.

From a quick look at the way OpenVPN does things, I think this is a problem in OpenVPN (well, maybe "it's a feature, not a bug" : ) But I don't think OpenVPN will be fixing it any time soon, and it may have something with the way that Tunnelblick handles PKCS#11, so I guess Tunnelblick will have to deal with it.

I'll post back here when I have more about starting OpenVPN without the --daemon option, but I have no idea when that will be.

Nicolas

unread,
Dec 12, 2017, 11:18:42 AM12/12/17
to tunnelblick-discuss
I agree with you that it is a problem in OpenVPN that fails to interact with a smartcard when run as a daemon on Mac OS El Capitan and newer. I created a ticket for this but have not received any response so far.

Anyway, given that Apple has deprecated the use of the daemon function, and recommends to use launchd, they might reply that the --daemon option is deprecated on Mac OS…

So I think it might be more efficient to try to solve that issue in TunnelBlick.

Please tell me if/when you think I should try to patch TunnelBlick to use lauchd/launchctl to start OpenVPN.


Cheers,

--
Nicolas
Reply all
Reply to author
Forward
0 new messages