OS: Ubuntu 16.04.2 LTS

My VPN config has directives:

user ovpn
group ovpn
up "/path/to/my/script"
down "/path/to/my/script"

My visudo file has the directive:

%ovpn ALL=(ALL:ALL) NOPASSWD: /sbin/iptables

This allows openvpn to deescalate from root to the unprivileged user ovpn (for security reasons), but still use iptables to bring up and down routes loaded from a database. It works if I invoke the openvpn process directly from a shell, i.e.:

$ sudo openvpn /etc/openvpn/vpn0.conf

and then kill it with CTRL-C. By "it works" I mean that the iptables rules are added and removed as desired without any errors.

However, if I start and stop the openvpn process using the vanilla Ubuntu systemd openvpn service. i.e.

$ sudo systemctl start openvpn
$ sudo systemctl stop openvpn

then the "--down" script fails during execution of the "stop" command. When I examine the syslog I see that the --down script has failed at the shell command invoking sudo /sbin/iptables, specifically where it is attempting to fork the process. (regarding error message, my script is a python script using subprocess.call(['/usr/bin/sudo', '/sbin/iptables', ...]). Error message is:

File "/usr/lib/python2.7/subprocess.py", line 523, in call
  return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
  errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1235, in _execute_child
  self.pid = os.fork()
OSError: [Errno 11] Resource temporarily unavailable

If I remove the user and group directives from the openvpn configuration file so that the process remains root throughout execution, then I don't get the error, and the iptables invocations work as expected, even when using the systemd service to start and stop.

So it smells like systemd is preventing me from escalating privileges using sudo while shutting down the service.

Any ideas on how to overcome this difficulty while still deescalating to an unprivileged user?

  • sudo may need a tty. try Defaults:%ovpn !requiretty – meuh Oct 3 '19 at 20:02
  • I added the !requiretty line as requested, with no change in observed behaviour. I also tried a vanilla Defaults !requiretty line, also with no change in observed behaviour. – Isaac Sutherland Oct 4 '19 at 14:36
  • 1
    I dont use openvpn, but on my Fedora system the systemd openvpn Unit file openvpn-client@.service has an entry LimitNPROC=10. This would limit the number of processes that can run simultaneously in the service (when User= not root). Perhaps you can try increasing this a tad? – meuh Oct 4 '19 at 16:30
  • 1
    I changed it to LimitNPROC=1000 in the equivalent openvpn server Ubuntu 16.04 config file and everything started working! I wonder what the reasoning is behind that limit. I'm gonna try bringing it down to 100 to see if that will work with my application. – Isaac Sutherland Oct 5 '19 at 18:07

Apparently, in this case Resource temporarily unavailable was telling me that os.fork was failing because the unprivileged user had hit the maximum number of processes allowed by the openvpn service's systemd config.

To fix this, I edited /lib/systemd/system/openvpn@.service and made the following change:

- LimitNPROC=10
+ LimitNPROC=100

And subsequently my iptables chain tear down commands are succeeding even when using an unprivileged user and elevating privileges using sudo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.