I have a server with some OpenVPN instances (one server, several clients) running on Debian with enforcing SELinux. The connections to some of the VPN servers my machine is connecting to are somewhat unstable, and the OpenVPN instances on my machine crash now and then, so I had set up a cronjob to restart them in case of a crash.

Now the problem is, that this cronjob fails due to issues with SELinux, which I don't really understand. Restarting any OpenVPN instance by hand from commandline, using the same command, works fine. This ist what audit says:

type=AVC msg=audit(1422960005.730:3567927): avc:  denied  { sys_module } for  pid=14309 comm="ifconfig" capability=16  scontext=system_u:system_r:openvpn_t:s0 tcontext=system_u:system_r:openvpn_t:s0 tclass=capability
        Was caused by:
                Missing type enforcement (TE) allow rule.
                You can use audit2allow to generate a loadable module to allow this access.

type=AVC msg=audit(1422960005.722:3567921): avc:  denied  { relabelfrom } for  pid=14295 comm="openvpn" scontext=system_u:system_r:openvpn_t:s0 tcontext=unconfined_u:system_r:openvpn_t:s0-s0:c0.c1023 tclass=tun_socket
        Was caused by:

#Constraint rule:

        constrain tun_socket { create relabelfrom relabelto } ((u1 == u2 -Fail-)  or (t1 == { logrotate_t ldconfig_t initrc_t sysadm_t dpkg_t lvm_t mdadm_t unconfined_mount_t dpkg_script_t newrole_t local_login_t sysadm_passwd_t system_cronjob_t tmpreaper_t unconfined_execmem_t httpd_unconfined_script_t groupadd_t depmod_t insmod_t kernel_t passwd_t updpwd_t apmd_t apt_t chfn_t init_t sshd_t udev_t remote_login_t inetd_child_t restorecond_t setfiles_t unconfined_t systemd_tmpfiles_t sulogin_t useradd_t } -Fail-) ); Constraint DENIED

#       Possible cause is the source user (system_u) and target user (unconfined_u) are different.
#       Possible cause is the source level (s0) and target level (s0-s0:c0.c1023) are different.

I had already set up a local openvpn configuration for SELinux, in order to get it running at all. It looks like this:

module openvpn_local 1.0;

require {
        type openvpn_t;
        type kernel_t;
        type udev_t;
        type var_run_t;
        class system module_request;
        class file { read append };
        class capability sys_module;
        class tun_socket { relabelfrom relabelto };

#============= openvpn_t ==============
allow openvpn_t kernel_t:system module_request;
# allow openvpn_t self:capability sys_module;
allow openvpn_t self:tun_socket { relabelfrom relabelto };
allow udev_t var_run_t:file { read append };

This setup had worked, before I had to make some changes on my setup, to run the OpenVPN instances on static devices nodes. Since then, the granted rights don't seem to be sufficient anymore.

Any help, to set up a fine grained solution for this, or how to improve the local SELinux module for OpenVPN would be greatly appreciated!


The first error is clear; the line you've commented out gives the permission that audit says is missing.

The second part is more interesting, but what I suspect is the problem is the target context of the socket you're modifying (owned by unconfined_u). Because you've moved to static device nodes, your interfaces are no longer created by the openvpn process that's going to modify them, so I don't think self:tun_socket is going to be enough anymore. You may also be able to fix this by modifying the contexts of your nodes to be owned by system_u instead.

If all your network setup is handled in an initscript and everything works at boot, you can definitely use run_init /etc/init.d/openvpn start in root's crontab to make this work. run_init makes sure the script runs in the same context it would have been at boot.

EDIT: If you want it to be sensitve to crashes and your daemons have pidfiles, you could use some inotify magic on /proc/pid to notice when they disappear and then call the restart script. waitpid would be nicer, but only works on child processes.

  • Ahh, that actually did the trick. For some reason I thought, openvpn would persist its nodes by itself, so I had just created them once manually and never restarted the server since then. Now I put some lines in the init script to set them up, and everything is allright. Thanks for the hints! – Michael Feb 14 '15 at 1:11
  • Ah, now the damn bounty expired 30 minutes ago. Sorry for not being able to give you your well deserved points anymore :( – Michael Feb 14 '15 at 1:13
  • No problem, I do this to learn things I might not otherwise encounter, not for the magic internet points. :) – Mike Burns Feb 15 '15 at 18:00

I don't SELinux, so can't assist with that. However, if your issue is keeping OpenVPN running, you may consider code like this:

while sleep 5; do

This assumes OpenVPN is running in the foreground. You may need to change your OpenVPN command line options to get it to stick in the foreground. This script sleeps five seconds, then starts OpenVPN. When OpenVPN exits, it sleeps for five seconds and starts OpenVPN. Lather, rinse, repeat.

This is an ugly hack, but if you run it in a screen session, it can get the job done. You can script it all to run in screen if you want to. I can't stress enough that it's an ugly hack.... but so is restarting the service periodically from cron.

  • What I do right now is only regular checking, if it's alive, more like a watchdog, using service openvpn status client_name. I agree it isn't nice, but it is not half as hacky as keeping an screen root session open for indefinite time. I won't consider this as a permanent solution, sorry. – Michael Feb 12 '15 at 9:48
  • I would agree, it's ugly. It does have the advantage of triggering based on failures rather than time, though. But still... ugly ugly. – Rob Feb 12 '15 at 17:58

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.