我有一台服务器,其中有一些 OpenVPN 实例(一台服务器,多个客户端),在 Debian 上运行,并强制执行 SELinux。我的机器所连接的一些 VPN 服务器的连接有些不稳定,并且我机器上的 OpenVPN 实例时不时地崩溃,因此我设置了一个 cronjob 来在崩溃时重新启动它们。
现在的问题是,这个 cronjob 由于 SELinux 的问题而失败,我不太明白。使用相同的命令从命令行手动重新启动任何 OpenVPN 实例都可以正常工作。审计是这样说的:
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.
我已经为 SELinux 设置了本地 openvpn 配置,以便让它运行。它看起来像这样:
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 };
在我必须对我的设置进行一些更改以在静态设备节点上运行 OpenVPN 实例之前,此设置已经有效。从那时起,授予的权利似乎不再足够了。
任何帮助,为此建立一个细粒度的解决方案,或者如何改进 OpenVPN 的本地 SELinux 模块将不胜感激!
答案1
第一个错误很明显;您注释掉的行给出了审计认为缺少的权限。
第二部分更有趣,但我怀疑问题是您正在修改的套接字的目标上下文(由 unconfined_u 拥有)。因为您已经转移到静态设备节点,所以您的接口不再由要修改它们的 openvpn 进程创建,所以我认为 self:tun_socket 不再足够了。您还可以通过将节点的上下文修改为由 system_u 拥有来解决此问题。
如果您所有的网络设置都在 initscript 中处理,并且一切都在启动时正常工作,那么您绝对可以run_init /etc/init.d/openvpn start
在 root 的 crontab 中使用来完成此工作。run_init
确保脚本在启动时的相同上下文中运行。
编辑:如果你希望它对崩溃敏感并且你的守护进程有 pid 文件,你可以inotify
在 /proc/pid 上使用一些魔法来注意到它们何时消失,然后调用重新启动脚本。waitpid
会更好,但仅适用于子进程。
答案2
我没有 SELinux,所以无法提供帮助。但是,如果您的问题是保持 OpenVPN 运行,您可以考虑如下代码:
while sleep 5; do
/command/to/start/OpenVPN
done
这假设 OpenVPN 在前台运行。您可能需要更改 OpenVPN 命令行选项以使其停留在前台。该脚本休眠五秒钟,然后启动 OpenVPN。当 OpenVPN 退出时,它会休眠五秒钟并启动 OpenVPN。起泡沫,冲洗,重复。
这是一个丑陋的黑客,但如果你在屏幕会话中运行它,它可以完成工作。如果您愿意,您可以将其全部编写为在屏幕上运行的脚本。我无法强调这是一个丑陋的黑客......但从 cron 定期重新启动服务也是如此。