Debian에서 실행되고 SELinux를 적용하는 일부 OpenVPN 인스턴스(서버 1개, 클라이언트 여러 개)가 있는 서버가 있습니다. 내 컴퓨터에 연결된 VPN 서버 중 일부는 연결이 다소 불안정하고 내 컴퓨터의 OpenVPN 인스턴스가 때때로 충돌하므로 충돌 시 다시 시작하도록 cronjob을 설정했습니다.
이제 문제는 SELinux 문제로 인해 이 cronjob이 실패한다는 것인데, 저는 잘 이해가 되지 않습니다. 동일한 명령을 사용하여 명령줄에서 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
루트의 crontab에서 이를 사용하여 작업을 수행할 수 있습니다. run_init
스크립트가 시작될 때와 동일한 컨텍스트에서 실행되는지 확인하십시오.
편집: 충돌에 민감하고 데몬에 pid 파일이 있는 경우 inotify
/proc/pid에서 몇 가지 마법을 사용하여 파일이 사라지는 것을 확인한 다음 다시 시작 스크립트를 호출할 수 있습니다. waitpid
더 좋을 것이지만 하위 프로세스에만 해당됩니다.
답변2
SELinux가 없어서 도움을 드릴 수 없습니다. 그러나 OpenVPN을 계속 실행하는 데 문제가 있는 경우 다음과 같은 코드를 고려할 수 있습니다.
while sleep 5; do
/command/to/start/OpenVPN
done
이는 OpenVPN이 포그라운드에서 실행되고 있다고 가정합니다. OpenVPN 명령줄 옵션을 변경하여 포그라운드에 유지해야 할 수도 있습니다. 스크립트는 5초 동안 대기한 후 OpenVPN을 시작합니다. OpenVPN이 종료되면 5초 동안 절전 모드로 전환된 후 OpenVPN을 시작합니다. 거품을 내고 헹구고 반복하세요.
보기 흉한 해킹이지만 스크린 세션에서 실행하면 작업이 완료됩니다. 원한다면 화면에서 실행되는 스크립트로 모두 작성할 수 있습니다. 이 해킹이 얼마나 추악한지는 아무리 강조해도 지나치지 않습니다... 하지만 cron에서 정기적으로 서비스를 다시 시작하는 것도 마찬가지입니다.