/
보안 정책 관리

보안 정책 관리

semanage는 SELinux 의 보안 정책을 조회하고 추가/변경/삭제할 수 있는 명령행 기반의 유틸리티입니다.


SELinux 는 파일, 네트워크 포트, 네트워크 인터페이스등을 별도의 보안 컨텍스트로 분리하여 다루고 있으므로 서비스 데몬을 SELinux 에서 문제없이 사용하려면 네트워크 포트와 파일 컨텍스트를 이해하고 semanage 로 컨텍스트를 다룰수 있어야 합니다.


semanage 는 일반적으로 추가로 설치해야 하는 패키지로 Red Hat의 다른 시스템 유틸리티처럼 python 으로 작성되어서 python 인터프리터를 필요로 하고 있으며 다음 yum 명령어를 사용하여 패키지를 설치할 수 있습니다.

$ sudo yum install -y policycoreutils-python  
semanage 설치


포트 컨텍스트

SELinux 는 네트워크 데몬마다 명시적으로 접근할 수 있는 포트 번호를 관리하고 있으며 설령 root 로 구동한 데몬 프로세스라도 허용된 포트 이외에는 차단해 버립니다.

이는 공격자가 웹 서버나 메일 서버등 인프라 프로세스의 취약점이나 잘못된 설정을 해킹하여 쉘을 얻은 후에 ssh 등을 사용하여 내부 망으로 다시 침투하는 2차 피해를 방지해 주는 강력한 기능이지만 well known 이 아닌 포트 번호를 사용하거나 새로운 포트 번호를 할당하는 등의 변경이 있을 경우 제대로 동작하지 않게 됩니다.


이런 내용을 모른다면 SELinux 가 서버의 포트 접근을 차단하여 SELinux 를 사용하면 서비스 운영이 힘들다는 생각을 갖게 될 수 있으므로 포트 컨텍스트에 대해 반드시 이해해야 합니다.


포트를 다루려면 semange 명령어 뒤에 port 명령을 사용하고 뒤에 옵션을 주면 되며 조회를 할 경우 -l 옵션을 사용하면 됩니다.

아래 명령은 SELinux 에 등록된 전체 포트 컨텍스트를 출력하며 첫 번째 행은 포트 유형, 두 번째는 프로토콜, 세 번째는 포트 번호이며 첫번째 포트 유형은 프로토콜:포트번호에 접근을 허용한다는 의미입니다.

$ sudo semanage port  -l

SELinux Port Type              Proto    Port Number
afs_bos_port_t                 udp      7007
afs_client_port_t              udp      7001
afs_fs_port_t                  tcp      2040
...


zebra_port_t                   udp      2600-2604, 2606
zented_port_t                  tcp      1229
zented_port_t                  udp      1229
zope_port_t                    tcp      8021
포트 컨텍스트 확인

즉 마지막 줄의 zope_port_t tcp 8021zope_port_t 라는 포트 유형은 tcp:8021 포트를 사용할 수 있습니다.


우리의 관심사는 웹 서버이므로 http 에 관한 포트 번호를 검색해야 하며 semanage 명령에서 타입별로 분류할 수 있는 기능은 제공하지 않으므로 특정 타입만 확인할 경우 grep 으로 분류를 해주면 됩니다.

아래는 http 가 들어간 전체 포트 컨텍스트 목록을 출력합니다.

$ sudo semanage port  -l | grep http


http_cache_port_t              tcp      3128, 8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 443, 8009, 8080


TODO http_port_t 진하게

포트 컨텍스트 확인


http_cache_port_t 는 squid 같은 웹 캐시 서버가 접근할 수 있는 포트를 의미하며 웹 서버가 접근할 수 있는 포트 컨텍스트의 이름은 http_port_t  타입으로 지정되어 있습니다. 


결과를 보면 웹 서버는 http_port_t 에 할당된 4개의 포트에 접근할 수 있다는 의미입니다. 보통 웹 서버는 80, 443을 리슨하는데 8009 나 8080 이 있는 것이 의아한 독자들이 있을 수 있습니다.


http_port_t 에 지정하는 포트는 웹 서버가 리슨하는 포트만이 아니라 커넥트하는 포트까지 지정해 주어야 하며 8009, 8080 는 아파치 톰캣이 리슨하는 포트이므로 웹 서버가 톰캣에 연결할 때 필요하므로 설정해 주어야 합니다.

예로 웹 서버를 PHP 의 WAS 라고 볼 수 있는 php-fpm 과 네트워크 소켓 방식으로 연동한다면 php-fpm 이 사용하는 포트(기본: 9000) 를 http_port_t 에 등록해 주지 않으면 SELinux 는 웹 서버의 9000 번 포트 연결을 차단해 버립니다.

또 하나의 사례로 아파치 웹 서버를 900 포트를 통해 서비스를 해야 할 일이 생겼다고 가정해 봅시다. 새로운 포트 추가는 아파치의 설정 파일(CentOS의 경우 /etc/httpd/conf/httpd.conf)에서 사용하는 포트를 지정하는 Listen 항목에서 900 을 추가하고 아파치 웹서버를 재시작해 주면 됩니다.


Listen 80
Listen 900
httpd 포트 추가

nginx 사용자는 가상 호스트 설정의 server 블록에 listen 900; 를 추가해 주면 됩니다.

server {
	listen 80;
	listen 900;



에러 로그를 보면 다음과 같이 900 번 포트에 바인드할 수 없다는 에러가 발생하고 웹 서버가 정상적으로 구동되지 않는 것을 볼 수 있습니다.

$ sudo systemctl restart httpd


(13)Permission denied: make_sock: could not bind to address [::]:900
(13)Permission denied: make_sock: could not bind to address 0.0.0.0:900
httpd 구동 에러


이는 아파치 웹 서버가 루트로 구동되지만 부여된 컨텍스트인 http_port_t 는 위에서 본 8개 포트이외에는 연결할 수 없으므로 발생하는 현상이며 이 문제를 해결하려면 http_port_t 컨텍스트가 연결할 수 있는 포트를 추가해 주면 됩니다.

포트를 추가할 경우 추가 옵션인 -a 와 사용할 프로토콜, 보안 컨텍스트, 포트 번호를 지정해 주면 됩니다. 


HTTP 는 tcp 를 사용하므로 -p tcp 옵션과  보안 컨텍스트를 지정하는 -t http_port_t 그리고 허용할 포트 번호 900 을 지정하여 최종 실행할 semanage 명령어는 아래와 같습니다.

$ sudo semanage port -a -p tcp -t http_port_t 900 
포트 추가

만약 "Port tcp/900 already defined" 같이 이미 포트가 지정되어 있다는 에러가 발생한다면 추가 옵션인 -a 대신 변경 옵션인 -m 을 사용하면 됩니다.


$ sudo semanage port -m -p tcp -t http_port_t 900 


정상적으로 설정이 끝났다면 포트 목록을 다시 확인해 봅시다.

$ sudo semanage port -l | grep http_port_t


http_port_t                    tcp      80, 443, 8009, 8080, 900

TODO 900 진하게

포트 목록 확인


웹 서버는 DMZ 구간에 위치하고 WAS 와는 리버스 프락시로 연결하면 서비스가 커질 경우 WAS 를 수평/수직 적으로 확장할 수 있는 장점과 더불어 보안도 견고해 지는 장점이 있습니다.

만약 WAS 를 한 서버에 별도의 포트로 추가 구성하는 수직 확장의 경우 포트 번호가 추가된다면 꼭 semanage port 명령으로 새로 만들어진 WAS 의 포트를 등록해 주어야 합니다.


추가된 포트 컨텍스트는 -d 옵션으로 삭제할 수 있으며 해당 포트를 추가할 때와 마찬가지로 -p 로 tcp 인지 udp 인지 지정해 주고 삭제할 포트 번호를 지정해 주면 되며 아래 명령어는 http_port_t 에 추가한 900 번 포트를 삭제합니다.

$ sudo semanage port -d -p tcp 900
포트 삭제


명령어가 정상적으로 종료된 후에 포트 목록을 조회해 보면 900 번이 사라진 것을 확인할 수 있습니다.

$ sudo semanage port -l | grep http_port_t


http_port_t                    tcp      80, 443, 8009, 8080
포트 목록 확인



파일 컨텍스트 

/var/www/html 폴더 밑에 cp 로 파일을 복사하거나 또는 에디터등으로 파일을 새로 만들면 자동으로 httpd_sys_content_t  컨텍스트가 부여되는 것을 확인했습니다. 또 restorecon 을 사용하면 위치에 맞는 보안 컨텍스트를 복구해 준다는 것도 알게 되었는데 어떻게 이게 가능한 것일까요? 


SELinux 는 사용자들이 일일이 보안 컨텍스트를 지정하지 않아도 되도록 주요 디렉터리 경로마다 자동으로 특정 컨텍스트를 부여하도록 사전 탑재 정책에 설정되어 있습니다. semange 의  파일 컨텍스트 기능은 바로 이런 SELinux 의 설정을 확인하고 추가/변경할 수 있는 해주는 기능으로 semanage 명령어 뒤에 fcontext 옵션을 주고 실행하면 됩니다.


먼저 설정된 파일 컨텍스트의 목록을 표시하는 옵션인 -l 을 사용해 봅시다. 많은 결과가 나오므로 어떤 경로에 파일을 작성하면 자동으로 httpd_sys_content_t 컨텍스트가 부여되는지 grep 을 사용하여 필터링을 합니다.


$ sudo semanage fcontext -l|grep httpd_sys_content_t 


/srv/([^/]*/)?www(/.*)?                            all files          system_u:object_r:httpd_sys_content_t:s0 
/var/www(/.*)?                                     all files          system_u:object_r:httpd_sys_content_t:s0 
/etc/htdig(/.*)?                                   all files          system_u:object_r:httpd_sys_content_t:s0 
httpd_sys_content_t 부여 경로 확인


경로는 정규식을 사용할 수 있으며 /var/www(/.*)? 는 /var/www 하위의 모든 파일과 폴더를 의미하므로 /var/www/html 이나 /var/www/mywebapp 모두 httpd_sys_content_t가 붙게 됩니다.


서비스를 운영하다 보면 MySQL 데이타가 늘어나서 기본 경로인 /var/lib/mysql 에 있는 데이타 베이스 파일을 다른 파티션(예: /opt/mysql)으로 이동해야 하는 일이 생길 수 있습니다.


MySQL 도 중요한 데몬 프로세스이므로 SELinux 에 사전 탑재 정책이 있고 MySQL 의 데이타베이스 파일도 대상이므로 MySQL 설정 파일에 datadir=/opt/mysql 로 설정하고 재부팅하면 기본 설정에서 어긋나므로 SELinux 가 차단하여 정상적으로 구동되지 않습니다.


먼저 MySQL 이 데이타베이스 파일을 저장할 수 있도록 허용된 타입인 mysqld_db_t 를 파일 컨텍스트를 사용하여 확인해 봅시다.

$ sudo semanage fcontext -l|grep mysqld_db_t


/var/lib/mysql(/.*)?                               all files          system_u:object_r:mysqld_db_t:s0 
/var/lib/squeezeboxserver(/.*)?                    all files          system_u:object_r:mysqld_db_t:s0 
httpd_sys_content_t 부여 경로 확인

/var/lib/mysql/var/lib/squeezeboxserver 하위의 경로가 아니라면 자동으로 mysql_db_t 가 붙지 않아서 문제가 될수 있으며 이를 해결하기 위해서는 두 가지 방법이 있습니다.


1.chcon 으로 타입 부여

MySQL 데이타를 새로운 폴더로 이동한 후에 아래 명령으로 타입을 부여해 주면 됩니다. 

$ sudo chcon -R -t mysqld_db_t /opt/mysql

이 방법의 단점은 새로운 database 를 추가할 경우 mysqld_db_t 가 자동으로 부여되지 않아서 오작동 한다는 점입니다.


2. 새로운 경로에 컨텍스트 설정


port 를 추가했을때 처럼 경로에 자동으로 적절한 보안 컨텍스트가 부여될 수 있도록 설정할 수 있습니다. 기존에 없는 위치이므로 -a 옵션으로 추가를 하고 -t 옵션에 부여할 컨텍스트를 적고 정규식으로 설정할 경로를 적어 주면 됩니다.다.


다음은 /opt/mysql 하단에 생기는 모든 파일과 폴더에 mysqld_db_t 를 자동으로 부여하는 semanage 명령어입니다.

$ sudo semanage fcontext -a -t mysqld_db_t "/opt/mysql(/.*)?"
mysqld_db_t 컨텍스트 부여

성공적으로 완료되었다면 새로 추가한 경로에 정책이 반영되도록 restorecon 을 실행해 줍니다.

$ sudo restorecon -R -v /opt/mysql
mysqld_db_t 컨텍스트 부여

정책에 추가되었으므로 이제 새로운 MySQL 데이타베이스 파일이 생겨도 정상적으로 동작합니다.


설정이 변경되어 파일 컨텍스트를 삭제할 경우 포트의 경우와 마찬가지로 -d 옵션으로 추가한 경로를 삭제 할 수 있으며 등록할 때와 마찬가지로 삭제할 경로를 입력해야 합니다.

$ sudo semanage fcontext -d "/opt/mysql(/.*)?" 
mysqld_db_t 컨텍스트 부여


이제 SELinux 의 보안 컨텍스트에서 두 가지 중요한 요소인 파일과 보안 컨텍스트를 이해하면 큰 문제없이 SELinux 를 사용할 수 있을 것입니다.


Related content

아키텍처
More like this
SELinux Boolean
SELinux Boolean
More like this
SELinux
More like this
SELinux 소개
SELinux 소개
More like this
정책 유틸리티 사용
정책 유틸리티 사용
More like this
Web/WAS 서비스 구축시 보안 유의사항
Web/WAS 서비스 구축시 보안 유의사항
More like this