up and down user scripts
OpenVPN supports custom user scripts to be run as the service is started or stopped — known as the --up
and --down
parameters in the man page. On CentOS or other Red Hat-based distributions, these scripts may not work correctly because SELinux is preventing them from executing, which results in the OpenVPN service failing to start.
[root@localhost ~]# service openvpn start Starting openvpn: [FAILED] [root@localhost ~]# tail -15 /var/log/openvpn.log Tue Jul 1 10:48:44 2014 TUN/TAP TX queue length set to 100 Tue Jul 1 10:48:44 2014 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0 Tue Jul 1 10:48:44 2014 /sbin/ip link set dev tun0 up mtu 1500 Tue Jul 1 10:48:44 2014 /sbin/ip addr add dev tun0 local 172.16.1.1 peer 172.16.1.2 Tue Jul 1 10:48:44 2014 PLUGIN_CALL: POST /usr/lib64/openvpn/plugins/openvpn-plugin-down-root.so/PLUGIN_UP status=0 Tue Jul 1 10:48:44 2014 /etc/openvpn/scripts/up.sh tun0 1500 1542 172.16.1.1 172.16.1.2 init /etc/openvpn/scripts/up.sh: line 14: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 15: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 16: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 17: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 18: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 19: /sbin/iptables: Permission denied /etc/openvpn/scripts/up.sh: line 20: /proc/sys/net/ipv4/ip_forward: Permission denied Tue Jul 1 10:48:44 2014 WARNING: Failed running command (--up/--down): external program exited with error status: 1 Tue Jul 1 10:48:44 2014 Exiting due to fatal error
- OpenVPN fails to start with the
service
command. - Error messages in
/var/log/openvpn.log
show failed execution of commands regarding theup.sh
script.
Also to further verify SELinux is causing this problem, error messages can be found in /var/log/audit/audit.log
:
type=AVC msg=audit(1404247863.966:166): avc: denied { getattr } for pid=2946 comm="up.sh" path="/sbin/iptables-multi-1.4.7" dev=sda1 ino=705 scontext=unconfined_u:system_r:openvpn_t:s0 tcontext=system_u:object_r:iptables_exec_t:s0 tclass=file type=SYSCALL msg=audit(1404247863.966:166): arch=c000003e syscall=4 success=no exit=-13 a0=26c6890 a1=7fff1691d490 a2=7fff1691d490 a3=50 items=0 ppid=2939 pid=2946 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="up.sh" exe="/bin/bash" subj=unconfined_u:system_r:openvpn_t:s0 key=(null)
- Notice
up.sh
was trying to run shell commands and/bin/bash
.
To allow custom scripts to be executed two things must be done:
- The up or down script must have the correct file contexts set.
- The correct SELinux boolean must be set to allow for unconfined scripts to be run by OpenVPN.
1. OpenVPN SELinux file contexts
Anytime the restorecon
command is run, it reads the /etc/selinux/targeted/contexts/files/file_contexts
file to know what file context to set on a regular file or directory. Therefore we can search through this file to find all the default file contexts for OpenVPN using grep -i openvpn /etc/selinux/targeted/contexts/files/file_contexts
, see below.
[root@localhost ~]# grep -i openvpn /etc/selinux/targeted/contexts/files/file_contexts /etc/openvpn(/.*)? system_u:object_r:openvpn_etc_t:s0 /var/log/openvpn.* system_u:object_r:openvpn_var_log_t:s0 /etc/openvpn/ipp.txt -- system_u:object_r:openvpn_etc_rw_t:s0 /var/lib/openvpn(/.*)? system_u:object_r:openvpn_var_lib_t:s0 /var/run/openvpn(/.*)? system_u:object_r:openvpn_var_run_t:s0 /etc/openvpn/scripts(/.*)? system_u:object_r:openvpn_unconfined_script_exec_t:s0 /usr/sbin/openvpn -- system_u:object_r:openvpn_exec_t:s0 /etc/rc\.d/init\.d/openvpn -- system_u:object_r:openvpn_initrc_exec_t:s0 /usr/share/munin/plugins/openvpn -- system_u:object_r:munin_services_plugin_exec_t:s0
Note all the different context types, though, the type we are most interested in is system_u:object_r:openvpn_unconfined_script_exec_t:s0
which applies to all files and directories under /etc/openvpn/scripts/
, and the directory itself.
Create the /etc/openvpn/scripts
directory, move your custom script to it, and run a recursive restorecon
:
[root@localhost ~]# mkdir /etc/openvpn/scripts [root@localhost ~]# ls -Zd /etc/openvpn/scripts/ drwx------. root root unconfined_u:object_r:openvpn_etc_t:s0 /etc/openvpn/scripts/ [root@localhost ~]# mv -v up.sh /etc/openvpn/scripts/ `up.sh' -> `/etc/openvpn/scripts/up.sh' [root@localhost ~]# restorecon -Rv /etc/openvpn/scripts/ restorecon reset /etc/openvpn/scripts context unconfined_u:object_r:openvpn_etc_t:s0->unconfined_u:object_r:openvpn_unconfined_script_exec_t:s0 restorecon reset /etc/openvpn/scripts/roadwarrior context unconfined_u:object_r:openvpn_etc_t:s0->unconfined_u:object_r:openvpn_unconfined_script_exec_t:s0 restorecon reset /etc/openvpn/scripts/up.sh context unconfined_u:object_r:admin_home_t:s0->unconfined_u:object_r:openvpn_unconfined_script_exec_t:s0
- Notice the file context type for the
scripts/
directory and thescripts/up.sh
switch fromopenvpn_etc_t
toopenvpn_unconfined_script_exec_t
.
Verify the directory and files have the correct file contexts with ls -Z
:
[root@localhost ~]# ls -Zd /etc/openvpn/scripts/ drwx------. root root unconfined_u:object_r:openvpn_unconfined_script_exec_t:s0 /etc/openvpn/scripts/ [root@localhost ~]# ls -Zl /etc/openvpn/scripts/ total 3 -rwxr-xr-x. 1 unconfined_u:object_r:openvpn_unconfined_script_exec_t:s0 root root 0 Jul 1 12:21 up.sh
2. OpenVPN SELinux booleans
Find the relevant SELinux booleans by listening them using getsebool -a
:
[root@localhost ~]# getsebool -a | grep -i openvpn openvpn_enable_homedirs --> on openvpn_run_unconfined --> off
Change the openvpn_run_unconfined
boolean to on with the setsebool
command and verify:
[root@localhost ~]# setsebool openvpn_run_unconfined on [root@localhost ~]# getsebool -a | grep -i openvpn openvpn_enable_homedirs --> on openvpn_run_unconfined --> on
Now the OpenVPN service should be able to start without any errors relating to the execution of --up
or --down
scripts:
[root@localhost ~]# service openvpn start Starting openvpn: [ OK ] [root@localhost ~]# tail -15 /var/log/openvpn.log Tue Jul 1 12:33:45 2014 TUN/TAP TX queue length set to 100 Tue Jul 1 12:33:45 2014 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0 Tue Jul 1 12:33:45 2014 /sbin/ip link set dev tun0 up mtu 1500 Tue Jul 1 12:33:45 2014 /sbin/ip addr add dev tun0 local 172.16.1.1 peer 172.16.1.2 Tue Jul 1 12:33:45 2014 PLUGIN_CALL: POST /usr/lib64/openvpn/plugins/openvpn-plugin-down-root.so/PLUGIN_UP status=0 Tue Jul 1 12:33:45 2014 /etc/openvpn/scripts/up.sh tun0 1500 1542 172.16.1.1 172.16.1.2 init Tue Jul 1 12:33:46 2014 /sbin/ip route add 172.16.1.0/24 via 172.16.1.2 Tue Jul 1 12:33:46 2014 GID set to nobody Tue Jul 1 12:33:46 2014 UID set to nobody Tue Jul 1 12:33:46 2014 UDPv4 link local (bound): [undef] Tue Jul 1 12:33:46 2014 UDPv4 link remote: [undef] Tue Jul 1 12:33:46 2014 MULTI: multi_init called, r=256 v=256 Tue Jul 1 12:33:46 2014 IFCONFIG POOL: base=172.16.1.4 size=62, ipv6=0 Tue Jul 1 12:33:46 2014 IFCONFIG POOL LIST Tue Jul 1 12:33:46 2014 Initialization Sequence Completed
Custom OpenVPN listening port
The default listening port for OpenVPN is UDP port 1194. If you decide to use another port, SELinux settings must be updated using semanage
to reflect the newly assigned port.
List SELinux port information and find port contexts matching OpenVPN with semanage port -l | grep -i openvpn
:
[root@localhost ~]# semanage port -l | grep -i openvpn openvpn_port_t tcp 1194 openvpn_port_t udp 1194
If we decide to use UDP port 2194 instead, use the following semanage
command:
[root@localhost ~]# semanage port -a -t openvpn_port_t -p udp 2194
Optionally you can swap udp with tcp if you are using OpenVPN in TCP mode.
Verify SELinux port contexts are updated:
[root@localhost ~]# semanage port -l | grep -i openvpn openvpn_port_t tcp 1194 openvpn_port_t udp 2194, 1194
References
http://sysadmin-notepad.blogspot.com/2013/05/custom-openvpn-port-with-selinux-enabled.html
http://www.mankier.com/8/openvpn_unconfined_script_selinux
No comments:
Post a Comment