[CentOS] Using syslog-ng with SELinux in enforcing
제목을 무엇으로 지을까 고민하다가, 참고한 글의 제목을 그대로 따왔다.
# Issue
처음 이 문제가 나타난 것은 syslog-ng
의 플러그인 라이브러리를 사용해 MariaDB
로 Destination 설정을 해줬을 때 였다.
Default로 설치된 syslog-ng
를 # systemctl start syslog-ng
명령어를 사용해 시작하면 잘 동작하는데, syslog-ng.conf
파일에 MariaDB
로의 Destination 설정만 넣으면 서비스 Fail이 발생하는 것이였다.😢
관련해서 혼자 해결하기 힘들다고 판단해, syslog-ng
를 개발한 Balabit Github에 이슈 등록을 했다.
결론 먼저 말하자면,
리눅스 커널 보안 정책인 SELinux
때문에 발생한 문제였다.
SELinux
보안 정책을 Permissive mode
로 변경 후 syslog-ng
서비스를 재시작하니, MariaDB
로 Destination 설정이 되어 있더라도 잘 동작하는 것을 볼 수 있었다.👏👏👏
하지만 늘상 Permissive mode
로 하고 있을 순 없으니... 궁극적으로 해결할 수 있는 방법이 필요했다.
Github 이슈에 보면 Balabit 개발자가 참고하라고 알려준 링크가 있는데, 이 링크가 바로 이 문제를 해결할 수 있었던 열쇠이다.
syslog-ng
를 사용하면서 등록되는 이슈의 절반 이상이 SELinux
문제여서, 관련 가이드 글을 작성한듯 하다. (👉 링크)
부족한 영어실력 & 구글 네이버의 힘을 빌려 변역했으니 참고하실 분은 아래 더보기를 눌러서 참고하세요.😉
SELinux
는 리눅스에서 엄격한 보안 정책을 담당하는 서비스이면서 동시에 Syslog-ng
서비스가 동작하는데 이슈의 절반 이상에 해당하는 문제를 야기한다.
환경설정에 비정상적인 포트 번호 또는 디렉토리 이름이 지정되면 Syslog-ng
가 정상적이라도 작동하지 않는다.
Enforce mode
에서 SELinux
와 함께 Syslog-ng
를 사용하는 방법을 알아보자.
SELinux basics
먼저 SELinux
가 컴퓨터에서 Enforcing mode
인지 확인한다.
cat
명령어를 사용해서 확인하는 방법과 getenforce
명령어를 사용하는 방법이 있음
[root@selinux ~]# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
[root@selinux ~]# getenforce
Enforcing
만약 Enforcing mode
가 아닌 경우, 환경설정 파일을 변경하고 재부팅한다.
SELinux
를 완전히 비활성화하는 것은 권장되지 않는다.
SELinux
를 다시 활성화하려면 restorecon
을 사용하여 파일 시스템의 label 도 다시 지정해야 한다.
setenfoce
명령어를 사용하여 SELinuxM
를 일시적으로 비활성화하고 getenforce
명령어를 사용하여 결과를 확인할 수 있다.
[root@selinux ~]# setenforce 0
[root@selinux ~]# getenforce
Permissive
[root@selinux ~]# setenforce 1
[root@selinux ~]# getenforce
Enforcing
Permissive mode
에서는 SELinux
는 정책 위반을 감지하고 기록하지만, 규칙을 적용하지는 않는다. 이는 디버깅 목적으로 사용할 수 있다.
# setenforce 0
을 사용하면, SELinux
가 실수로 비활성화 상태로 유지되지 않게 할 수 있다.
Logging
SELinux
로그는 /var/log/audit/audit.log
파일에 수집된다.기본 배포 구성으로 Syslog-ng
를 시작할 때 로그에 표시되는 유일한 로그는 새 서비스가 시작되었다는 로그이다.
[root@selinux ~]# grep syslog-ng /var/log/audit/audit.log
type=SERVICE_START msg=audit(1494923144.043:303): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=syslog-ng comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
최근 Syslog-ng
릴리즈의 linux-audit-parser()
기능을 사용하여 이 파일의 내용을 구문 분석할 수 있다. 자세한 내용은 이 링크를 참조
SELinux
에서는 label을 기반으로 접근 권한이 부여된다.
일반적으로 명령의 옵션으로 대문자 Z 를 사용하여 파일 및 프로세스에 대해 이러한 label을 나열할 수도 있다.
Using a different storage directory
우리는 /var/log
디렉토리에 로컬 로그 메시지를 저장한다.
그러나 중앙 Syslog-ng
서버의 로그는 종종 별도의 파티션(ex: /data/logs
디렉토리)에 저장된다.
syslog-ng.conf
를 수정하고 syslog-ng
를 다시 시작하면 디렉토리에서 로그를 볼 수 없다. 어떻게 된걸까?
/var/log/audit/audit.log
에서 syslog-ng
가 logs
라는 디렉토리에 대한 접근이 거부되었음을 알 수 있다.
type=AVC msg=audit(1494927489.413:407): avc: denied { write } for pid=50082 comm="syslog-ng" name="logs" dev="dm-0" ino=35096600 scontext=system_u:system_r:syslogd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=dir
만약 /var/log/messages
를 살펴보면 다음과 비슷한 메시지를 찾을 수 있다.
May 16 11:40:44 selinux syslog-ng[50082]: Error opening file for writing; filename='/data/logs/file', error='No such file or directory (2)'
SELinux
문제라고 할 수도 있으며, audit2allow
명령을 사용하여 권한 문제를 해결해야 한다.
늘 그렇듯이 인생이 쉽지 않은 이유는, syslog-ng
가 너무 많은 접근 권한을 받도록 하기 떄문이다. 차라리 직접 변경해야 한다.
위 디렉토리 목록에서 볼 수 있듯이 /var/log
디렉토리는 var_log_t
label에 있다.
새로 생성된 디렉토리를 나열하면 다음과 같은 다른 내용이 있다.
[root@selinux conf.d]# ls -ldZ /data/logs/
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/logs/
chcon
명령을 사용하여 label을 var_log_t
로 변경하고 ls
명령의 Z
옵션을 사용하여 결과를 확인할 수 있다.
[root@selinux conf.d]# chcon -t var_log_t /data/logs/
[root@selinux conf.d]# ls -ldZ /data/logs/
drwxr-xr-x. root root unconfined_u:object_r:var_log_t:s0 /data/logs/
이 접근법의 문제점은 변경이 일시적이라는 것이다.
restorecon
명령어를 사용하여 시스템을 재부팅하거나, SELinux
label을 복원하면 손실된다.
[root@selinux conf.d]# restorecon -v /data/logs/
restorecon reset /data/logs context unconfined_u:object_r:var_log_t:s0->unconfined_u:object_r:default_t:s0
[root@selinux conf.d]# ls -ldZ /data/logs/
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/logs/
semanage
명령을 사용하면 영구적으로 변경할 수 있다.
[root@selinux conf.d]# semanage fcontext -a -t var_log_t '/data/logs(./*)?'
[root@selinux conf.d]# restorecon -v /data/logs/
restorecon reset /data/logs context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:var_log_t:s0
[root@selinux conf.d]# ls -ldZ /data/logs/
drwxr-xr-x. root root unconfined_u:object_r:var_log_t:s0 /data/logs/
이제 로그가 디렉토리에 나타날 것이다.
Using a different port
기본적으로 SELinux
는 기본 syslog
포트에 대한 연결만 허용한다. 다음은 SELinux
에 알려진 syslog
관련 포트이다.
[root@selinux conf.d]# semanage port --list | grep syslog
syslog_tls_port_t tcp 6514
syslog_tls_port_t udp 6514
syslogd_port_t tcp 601
syslogd_port_t udp 514, 601
어떤 이유로든 다른 포트를 사용해야하는 경우 문제가 될 수 있다.
일반적인 시나리오는 TCP 로그 메시지에 대해서도 포트 514를 활성화하는 것이다.
포트 42에서 일부 로그를 수집하여 삶과 우주 및 모든 것이 대해 배울 수도 있다. 더 심각한 문제는 로그 메시지 유형별로 다른 포트 번호를 사용하여 로그 구문 분석을 더 쉽게 만드는 것이다.
만약 포트42(또는 다른 포트도 마찬가지)를 추가하고 SELinux
를 구성하지 않고 syslog-ng
를 다시 시작하면 서비스 시작에 실패한다.
journalctl
을 사용하여 오류 메시지를 확인할 수 있다.
May 17 09:55:35 selinux.localdomain setroubleshoot[3640]: SELinux is preventing /usr/sbin/syslog-ng from name_bind access on the tcp_socket port 42. For complete SELinux messages. run sealert -l ff7a7f22-128e-4b
May 17 09:55:35 selinux.localdomain python[3640]: SELinux is preventing /usr/sbin/syslog-ng from name_bind access on the tcp_socket port 42.
다음 명령어를 사용하여 syslogd_port_t
에 TCP 포트 42를 추가하고 포트 목록으로 확인하여 실제 추가되었는지 확인할 수 있다.
[root@selinux ~]# semanage port -a -t syslogd_port_t -p tcp 42
[root@selinux ~]# semanage port --list | grep sysl
syslog_tls_port_t tcp 6514
syslog_tls_port_t udp 6514
syslogd_port_t tcp 42, 601
syslogd_port_t udp 514, 601
이후 이 Syslog-ng
가 정상적으로 시작되고 netstat
를 사용하면, 포트 42에서 Listening 상태를 볼 수 있다.
외부에서 포트 42로 로그를 보내는 것은 여전히 작동하지 않기 때문에 퀘스트는 아직 끝나지 않았다.
여전히 동작하지 않는 이유는 방화벽 때문일 수도 있다.
따라서 포트 42를 열고 방화벽 규칙을 다시 로드하여 구성을 활성화한 다음, 열린 포트들을 나열한다.
[root@selinux conf.d]# firewall-cmd --permanent --add-port=42/tcp
success
[root@selinux conf.d]# firewall-cmd --reload
success
[root@selinux conf.d]# firewall-cmd --list-ports
42/tcp
이제 Syslog-ng
는 포트 42에서 모든 것에 대한 로그 메시지를 수신할 수 있다.
Further reading
여기서는 Default가 아닌 디렉토리나 포트를 로깅에 사용하는 방법에 대해 몇 가지 정보를 제공했다.
SELinux
및 firewalld
에 대해 자세히 알아보기 위해서는 다음의 웹 사이트를 참고하길 바란다.
글이 꽤 길어서 접은글 방식으로 넣어놨는데, 원본 글 번역이 귀찮은 사람들은 천천히 읽어보면 좋을 듯하다.
# Solution
나의 경우에는 원본 글에서 'Using a different storage directory' 단락이, 해결에 도움이 되었다.
SELinux
의 로그를 볼 수 있는 /var/log/audit/audit.log
파일을 살펴보면, 다음을 확인할 수 있었다.
type=AVC msg=audit(1600235930.808:152): avc: denied { read } for pid=1574 comm="syslog-ng"
name="syslog-ng.conf" dev="dm-0" ino=4217396 scontext=system_u:system_r:syslogd_t:s0
tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
중요한 것은 avc: denied { read }
부분인데, 원본 글에서 로그 폴더 접근 권한이 denied 된 부분과 흡사했다.
name="syslog-ng.conf"
인 것을 보니, 정리하면 syslog-ng
환경설정 파일을 읽는데 접근 권한 문제가 발생한 것이다.
가이드대로 semanage
명령어를 사용해 /var/log
디렉토리와 같은 label 설정을 해주었다.
[root@localhost syslog-ng]# semanage fcontext -a -t var_log_t '/etc/syslog-ng/syslog-ng.conf(./*)?'
[root@localhost syslog-ng]# restorecon -v /etc/syslog-ng/syslog-ng.conf
restorecon reset /etc/syslog-ng/syslog-ng.conf context unconfined_u:object_r:admin_home_t:s0->unconfined_u:object_r:var_log_t:s0
[root@localhost syslog-ng]# ls -ldZ /etc/syslog-ng/syslog-ng.conf
-rw-r--r--. root root unconfined_u:object_r:var_log_t:s0 /etc/syslog-ng/syslog-ng.conf
☝ 참고로,
- 나는 파일도 label 설정이 되는지 테스트하기 위해, 파일에 label 설정을 했는데 가이드 글과 마찬가지로 폴더(
/etc/syslog-ng/
)에 label 설정하는 것이 더 좋을 듯 하다. - 만약
semanage
명령어가 없어서 'command not found' 메시지가 떨어진다면 다음 명령어를 사용해 관련 패키지 설치를 하면 된다 →# yum install policycoreutils-python
이후 시스템 재부팅을 해서 확인해보면,
[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]# systemctl status syslog-ng
● syslog-ng.service - System Logger Daemon
Loaded: loaded (/usr/lib/systemd/system/syslog-ng.service; enabled; vendor preset: enabled)
Active: active (running) since 수 2020-09-16 15:22:34 KST; 26s ago
...
SELinux
정책을 비활성화 하지 않았지만, syslog-ng
서비스가 정상 작동하는 것을 볼 수 있다.👏👏👏
이 글은 syslog-ng
이슈만 참고할 것이 아니라, 다른 서비스에서도 SELinux
에 의한 문제가 있을 때 참고할 수 있을 것 같다.