SELinux 아키텍처

SELinux 는 리눅스 커널의 일부이며 다음과 같은 아키텍처를 갖고 있다. 시스템 콜은 SELinux 보안 모듈을 통해 보안 정책을 질의한 후에 처리되며 모든 시스템 콜에 대해 SELinux가 보안 정책을 확인해서 접근 허용 여부를 판단 해야 하므로 속도를 빠르게 하기 위해 캐슁하여 처리하고 있으며 이 부분을 AVC(Access Vector Cache) 라고 부른다.

시스템의 성능을 떨어뜨리지 않기 위해 AVC 는 질의에 최적화되었다. 그래서 AVC 에 정책을 추가/변경/삭제하는 작업은 매우 시간이 오래 걸리지만 AVC 에서 정책을 질의하는 것은 빠르게 처리된다.



Security Context 

SELinux 는 모든 프로세스와 객체마다 보안 컨텍스트 - Security Context (또는 보안 레이블 이라고도 한다.)이라고 부르는 정보를 부여하여 관리하고 있다. 이 정보는 접근 권한을 확인하는데 사용되고 있으며 SELinux 를 이해하기 위한 핵심 요소이다.

컨텍스트는 다음 4가지 구성 요소로 이루어져 있다.

요소설명
사용자시스템의 사용자와는 별도의 SELinux 사용자이다. 역할이나 레벨과 연계하여 접근 권한을 관리하는데 사용된다.
역할(Role)하나 혹은 그 이상의 타입과 연결되어 SELinux 의 사용자의 접근을 허용할 지 결정하는데 사용된다.
타입(Type)

Type Enforcement의 속성중 하나로 프로세스의 도메인이나 파일의 타입을 지정하고 이를 기반으로 접근 통제를 수행한다.

레벨(Label)

레벨은 MLS(Multi Level System)에 필요하며 강제 접근 통제보다 더 강력한 보안이 필요할 때 사용하는 기능이라고 한다.

이 기능이 필요한 곳은 군대등 최고의 기밀을 취급하는 곳 정도라고 하며 필자도 MLS 는 사용해 본적이 없으므로 생략하기로 하자.


여기서 가장 중요하고 꼭 알아야 할 부분은 타입이며 이는 보안 컨텍스트의 핵심 부분이다. SELinux 를 활성화하면 파일이나 디렉터리등의 객체마다 보안 컨텍스트를 부여하고 있으며 이는 ls 나 ps 등의 명령어에 -Z 옵션을 추가하면 확인할 수 있다.

ls 명령어에 -Z 옵션을 사용하여 직접 파일과 디렉터리의 보안 컨텍스트를 확인해 보도록 하자. 먼저 웹 컨텐츠를 제공하는 /var/www/html 를 확인해 보면 다음처럼 system_u 라는 사용자와 object_r 이라는 역할, httpd_sys_content_t라는 타입을 갖고 있다.


이제 아파치 httpd 가 구동되었을 때 어떤 보안 컨텍스트를 갖게 되는지 확인해 보자. "ps -ZC httpd" 명령으로 아파치 프로세스의 보안 컨텍스트를 확인할 수 있다. -C 옵션은 pid 대신 프로세스 이름으로 프로세스의 정보를 얻어오는 옵션이다.


위와 같이 httpd 프로세스는 httpd_t 라는 보안 컨텍스트를 갖고 구동된다. 여기까지 읽어도 강제 접근 통제 방식이 어떻게 동작하는지 잘 이해가 되지 않을 것이니 다음 절의 TE 부분을 읽고 실제 설정된 사례를 확인하여 강제 접근 통제를 이해해 보자.



Type Enforcement

TE(Type Enforcement)는 SELinux 를 사용하면 많이 보게 되는 단어일 것이다. TE는 기본적인 접근 통제를 처리하는 매커니즘으로 주체가 객체에 접근하려고 할 때 주체에 부여된 보안 컨텍스트가 객체에 접근할 권한이 있는지 판단하는 역할을 수행한다. 

예로 아파치 웹 서버가 /var/www/html/ 에 접근하려고 할 때 아파치 웹 서버는 주체가 되며 /var/www/html/ 는 객체가 되며 아파치 웹 서버에 부여된 보안 컨텍스트는 httpd_t 가 된다.

객체에 부여된 보안 컨텍스트는 위에서 ls -Z 로 보았듯이 httpd_sys_content_t 이며 httpd_t 는 httpd_sys_content_t 보안 컨텍스트가 부여된 객체에 접근이 허용되므로 아파치 웹 서버는 /var/www/html/ 디렉터리에 있는 컨텐츠를 읽고 클라이언트에 서비스 할 수 있다.

대다수의 SELinux 관련 실수는 보안 컨텍스트를 잘못 설정하는 것이며 이로 인해 SELinux 의 TE 가 위배되어 접근이 차단되게 된다. TE 관련 에러 메시지는 기본적으로 /var/log/audit/audit.log 에 남게 된다.


이제 강제 접근 통제가 어떻게 이루어 지는지 살펴 보자. 관리자는 새로운 웹 서비스를 제공하기 위해 아파치 httpd 를 설치하였고 웹 서비스용 컨텐츠를 /var/new-html 이라는 디렉터리를 통해서 제공하기로 하고 디렉터리 생성,컨텐츠 작성후 httpd 에 해당 디렉터리를 추가하고 소유자도 apache 계정과 그룹으로 변경하여 모든 설정을 마쳤다. 

그리고 service httpd restart 명령어로 httpd 를 재시작한후에 브라우저로 연결하면 권한이 없다는 403 에러를 만나게 되며 httpd 의 에러 로그 파일을 조회하면 다음과 같이  (13)Permission denied: access to /index.html denied 가 남아 있다. 더 자세한 SELinux 로그 메시지를 보기 위해 /var/log/audit/audit.log 을 열어 보면 다음과 같은 형식의 에러 메시지를 볼 수 있다.


SELinux에 익숙하지 않은 독자들은 위 로그를 어떻게 해석해야 난감할 것이지만 에러 형식만 알고 나면 그리 어렵지 않다. 볼드체로 표시한 부분을 특히 주의깊게 살펴 보고 로그 메시지를 해석해 보자. 


먼저 다음과 같이 avc: denied { getattr }, comm="httpd"와 path="/var/new-html/index.html" 부분을 보자.

이는 오류 메시지가 "avc 접근 거부 유형"이며 거부된 시스템 콜은 getattr 이며 해당 시스템 콜을 호출한 프로그램(comm)은 "httpd" 이며 거부된 객체의 경로는 /var/new-html/index.html 인 것을 의미한다.

아파치 httpd 가 컨텐츠를 서비스 하기 위해서는 해당 파일의 정보를 얻어 오는 getattr 시스템 콜을 호출했다는 것을 알 수 있다.

그 다음인 scontext=unconfined_u:system_r:httpd_t 부분을 보자. scontext는 소스 컨텍스트란 의미이며 이는 주체인 아파치 httpd 에 부여된 보안 컨텍스트를 의미하며 "httpd_t" 라는 컨텍스트를 갖고 수행 되었음을 알수 있다.

다음 tcontext=unconfined_u:object_r:var_t 보면 tcontext는 타켓 컨텍스트를 의미하며 타겟이 가진 보안 컨텍스트는 var_t 라는 것을 알 수 있다.


이제 /var/new-html 이라는 디렉터리를 아파치 http가 왜 읽지 못 했는지 생각해 보자. 에러 메시지를 봐서는 httpd_t 의 컨텍스트를 갖는 프로세스는 var_t 컨텍스트의 파일이나 디렉터리를 읽을 수 없다는 것을 유추할 수 있다. 

httpd_t 가 읽을 수 있는 컨텍스트는 httpd_sys_content_t 이며 이 컨텍스트가 설정되어 있지 않으면 아파치 웹 서버가 소유하고 있는 파일이라도 읽을 수가 없다.

실제로 이는 리눅스를 사용할 때 자주 하는 실수로 아파치 httpd 에서 해당 디렉터리를 읽지 못하는 원인을 모르므로 아예 SELinux 를 꺼 버리고 이 때문에 리눅스 시스템의 보안을 취약하게 만드는 경우가 많다.


이제 SELinux 가 켜져 있다면 공격자가 아파치의 알려지지 않은 보안 취약점이나 잘못된 설정을 이용하여 웹서버의 권한을 탈취했을 경우 SELinux 가 어떻게 시스템을 안전하게 지켜 주는지 살펴 보자.

  1. 공격자는 /home/lesstif 계정의 데이타를 읽으려고 할 경우 아파치 httpd 는 httpd_sys_content_t 컨텍스트인 객체만 읽을 수 있지만 /home 디렉터리는 user_home_dir_t 보안 컨텍스트가 부여되므로 접근이 차단된다.
  2. CGI 를 이용하여 외부 프로그램(Ex: ps, ls)을 실행하여 시스템의 정보를 추가로 수집하려고 했지만 아파치 웹 서버는 httpd_sys_script_exec_t 컨텍스트가 설정되지 않은 스크립트는 아파치 소유라도 실행할 수 없다.
  3. WAS (Web Application Server) 가 있는 서버로 2차 침입을 시도했으나 아파치 웹 서버는 기본 허용된 포트(80, 443, 8080, 8009 등)만 접근이 허용되므로 이외의 포트에는 연결할 수 없다.


이와 같이 SELinux 는 잘못된 설정이나 보안 버그를 사용하여 외부에서 침입했어도 시스템과 데이타를 지켜주며 2 차 피해를 최소화해 준다. 


Targeted Policy

RHEL 기반의 배포판은 버전 4 부터 SELinux 가 기본 포함되어 있고 프로세스, 파일등 모든 객체에 대해 상세한 보안 정책을 만들어서 같이 탑재하고 있다.

이 정책을 targeted policy 라고 하며 /etc/selinux/targeted/ 에 정의되어 있다.  아래는 httpd_t 에 대한 설정의 일부분으로 아파치 웹서버가 갖는 보안 컨텍스트인 httpd_t 는 httpd_sys_content_t 에만 연결이 가능하며 허용된 시스템 콜은 ioctl, read, getattr, lock, open 이라는 의미이다.

allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open };
CODE

서버 데몬을 개발하는 개발자가 아닌 이상 일반적인 사용자라면 위와 같이 SELinux 의 보안 정책을 작성하거나 정책을 수정할 일은 거의 발생하지 않을 것이다.

일반 사용자가 관리자는 SELinux 가 주체, 객체, 보안 컨텍스트에 대해서 기본적인 지식을 갖추면 되며 SELinux 는 httpd, ftpd, sambad 등의 서비스 데몬일 경우 특히 더 엄격하게 통제하므로 서비스 데몬이 SELinux 때문에 차단된 것 같으면 ps 나 ls 의 명령어에 -Z 옵션을 이용하여 보안 컨텍스트를 확인하고 적절한 보안 컨텍스트를 설정하는 것만 이해한다면 큰 무리없이 배포판에 있는 서비스 데몬들을 사용할 수 있다.


동작 모드

SELinux 는 enforce, permissive, disable 세 가지 동작 모드가 있으며 설치하면 기본적으로 enforce 모드로 동작하며 enforce 모드일 경우 정책과 룰에 어긋나는 동작은 모두 차단된다.

SELinux 의 동작 모드를 변경하는 명령어는 setenforce 명령어이며 0 또는 1을 옵션으로 줄 수 있으며 1일 경우 enforce 모드, 0 일 경우 permissive 모드이다.

setenforce 1

현재 SELinux 의 동작 모드는 getenforce 로 확인할 수 있다.


SElinux 동작 모드에 대해 더 자세한 정보를 얻으려면 sestatus 명령을 사용할 수 있다. 다음은 setenforce 0 명령어를 수행한 후에 sestatus 실행 결과로 현재 동작 모드는 permissive 모드이며 설정 파일에는 enforcing 으로 설정된 것을 알 수 있다.

Permissive mode 는 정책과 룰에 어긋나는 동작이 있을 경우 감사 로그(audit log)를 남기고 해당 작업은 허용한다. 내부 개발 서버일 경우 특정 데몬이나 서비스에 문제가 있을 경우 setenforce 0 으로 Permissive mode 로 전환하여 사용하면서 문제를 해결한 후에 enforce mode 로 전환하는 방식을 권장한다.


모드 영구 설정

setenforce 명령어로 설정한 모드는 영구적이지 않으며 재부팅하면 설정이 초기화 된다. 영구적인 설정은 /etc/sysconfig/selinux 을 열어서 SELINUX=enforcing 항목을 수정후 재부팅 해야 한다. SELinux 영구적인 해제는 설정 파일에 SELINUX=disabled 라 기술하면 되지만 결코 추천하지 않는다.

만약 SElinux 를 해제한 후에 다시 사용하려면 재부팅이 필요하며 이때 많은 시간이 걸릴 수 있다. 이유는 SELinux 를 해제하면 파일 시스템내에 SELinux 보안 컨텍스트를 기록하지 않으므로 다시 사용하기로 하고 재부팅할 때 모든 파일과 디렉터리에 대해 보안 컨텍스트를 다시 분류해야 하므로 시간이 많이 걸리기 때문이다.

SELinux Boolean

SElinux 는 보안 정책 설정의 편리를 위해 활성/비활성할 수 있는 사전에 정의된 개별 규칙들을 갖고 있으며 이 규칙들을 SELinux 불린(Boolean) 이라고 한다. 아파치 httpd 가 cgi 를 실행할 수 있게 하려면 여러 가지 설정을 해야 하지만 이런 번거로움을 없애기 위해 httpd_enable_cgi 라는 SELinux 불린이 있고 이 값을 true 로 설정하면 SElinux 는 아파치 웹 서버의 cgi 실행을 허용한다. 현재 불린 설정 값을 확인하려면 getsebool 명령어를 사용한다. 명령어 뒤에는 확인하려는 불린명을 주어야 하며 -a 옵션을 줄 경우 모든 불린의 설정 현황을 표시한다.

그러면 아파치 httpd 가 메일 서버에 연결할 수 있는지를 나타내는 불린인 httpd_can_sendmail 를 확인해 보자.

# getsebool httpd_can_sendmail httpd_can_sendmail --> off

기본 설정은 off 이므로 PHP(mod_php) 나 python(mod_wsgi) 같은 언어를 사용하여 아파치 웹 서버에서 모듈로 구동하는 경우 apache httpd 권한과 도메인을 상속받게 되므로 메일 서버에 연결할 수 없다.

이 문제를 재연해 보기 위해 PHP 에서 mail 함수를 사용하는 mailtest.php 코드를 아파치 웹 서버에서 실행해 보자.

<?php
 
mail('user@example.com', 'Subject', 'Message Body');
?>
CODE

위 php 스크립트를 /var/www/html/mailtest.php 에 저장한 후에 브라우저를 통해서 호출하면 아파치 웹 서버가 실행하므로 httpd_can_sendmail  불린 설정에 의해 다음과 같은 오류가 발생하게 된다.

sendmail: fatal: chdir /var/spool/postfix: Permission denied

불린 설정을 변경하려면 setsebool 명령어를 사용하며 뒤에 불린명을 적어주고 그 뒤에 1이나 true 또는 0 이나 false 를 지정하여 해당 불린을 활성화/비활성화할 수 있다. 그러면 httpd_can_sendmail 를 true 로 설정하여 PHP 에서 메일 전송이 가능하게 해 보자.

setsebool httpd_can_sendmail true

이제 다시 브라우저에서 mailtest.php 에 연결하면 정상 동작하여 메일이 가는 것을 확인할 수 있을 것이다.

setsebool 명령으로 설정한 불린 값은 서버를 재부팅하면 기본 설정으로 되돌아 오며 영구적으로 불린을 적용하려면 -P 옵션을 붙여서 실행해야 한다. 다음 명령어는 재부팅해도 아파치 httpd 가 메일 서버에 연결할 수 있게 한다.

setsebool -P httpd_can_sendmail true


SELinux 유틸리티

여기까지 읽었어도 아직도 독자들은 SELinux 가 어렵고 낯설고 복잡하게 느껴질 것이다. 레드햇과 리눅스 커뮤니티의 노력으로 SELinux 를 쉽게 사용하기 위해 많은 유틸리티가 개발되어 있으며 SELinux 가 남기는 에러 메시지를 더 사용자 친화적으로 표시하기 위해  에러 로그를 분석해 주는 유틸리티등이 있으므로 이런 도구들의 사용법을 익히면 SELinux 를 큰 무리없이 사용할 수 있을 것이다. 이 절에서는 SELinux 를 좀 더 편하게 사용할 수 있는 주요 유틸리티와 사용법에 대해서 알아 보자.

restorecon 과 chcon

아파치 웹 서버가 읽을 수 있도록 웹 컨텐츠는 httpd_sys_content_t 보안 컨텍스트가 설정되어야 하며 컨텐츠가 위치하는 기본 경로는 /var/www/html 디렉터리이다. 이 디렉터리 아래에 에디터로 test.html 파일을 작성후 저장하면 test.html 의 보안 컨텍스트는 어떻게 될까? 자동으로 httpd_sys_content_t 컨텍스트가 부여되어 웹 서비스를 제공할 수 있으며 만약 그렇지 않고 파일이나 디렉터리를 생성할 때마다 일일이 SELinux 를 부여해야 한다면 시스템 관리자는 보안 컨텍스트 설정 작업으로 인해 다른 작업을 거의 할 여력이 없을 것이다.

이렇게 관리의 편의를 위해 SELinux 는 주요 경로마다 생성되는 파일에 대해 자동으로 보안 컨텍스트를 부여하게 설정(/etc 에 파일을 생성하면 etc_t, /var/www/html 에 생성하면 httpd_sys_content_t )되어 있으므로 위치에 파일을 생성한다면 별도로 보안 컨텍스트를 부여할 필요가 없다.

그러나 만약 /root 디렉터리에 test.html 을 생성한 후에 이 파일을 /var/www/html 에 mv 명령어를 이용하여 이동시키면 어떤 결과가 발생할까. 먼저 관리자의 홈 디렉터리에 파일을 생성한 후 부여되는 보안 컨텍스트를 확인해 보자.

root 디렉터리에 생성한 파일은 admin_home_t 라는 컨텍스트를 갖게 되는 것을 알 수 있으며 이제 이 파일을 mv 명령어로 /var/www/html 디렉터리로 이동해 보자.

위와 같이 mv 로 이동 시킬 경우 admin_home_t 를 계속 유지하는 것을 알 수 있다. admin_home_t 컨텍스트는 아파치 프로세스의 컨텍스트인 httpd_t 가 접근할 수 없으므로 브라우저가 웹 서버에 test.html 파일을 요청했을 경우 웹 서버가 접근하지 못 하므로 서비스 하지 못하게 된다.

이 문제를 해결하려면 크게 세 가지 방법이 있다.


방법 #1 - cp 사용

cp 와 mv 는 SELinux 하에서 서로 다르게 동작한다. 위의 예에서 보듯이 mv 는 이동하는 대상의 보안 컨텍스트를 유지하지만 cp 는 대상의 보안 컨텍스트를 이동하려는 경로에 맞게 변경한다. 위의 명령어를 mv 대신 cp 로 복사할 경우 test.html은 /var/www/html 에 복사되므로 admin_home_t 대신 httpd_sys_content_t 컨텍스트가 설정되어 아파치가 접근이 가능해 진다.


방법 #2 - restorecon

cp 로 복사할 경우 보안 컨텍스트가 복사되는 목적지에 맞게 자동으로 설정되지만  파일이나 디렉터리가 여러 개라면 cp 로 복사하여 보안 컨텍스트가 자동으로 설정되게  하는 건 번거롭다. cp 보다 더 SELinux 에 적합한 방법은 restorecon 명령어를 사용하는 것이다. 명령어 이름에서 짐작했듯이 잘못 설정된 보안 컨텍스트를 복구해 주는 유용한 명령어이다. 부여되는 보안 컨텍스트는 사전에 설정된 정책에 의해 자동으로 설정된다. 다음 두 가지 경우를 보자

  • admin_home_t  를 갖는 test.html 이 /var/www/html 경로에 있을 경우
    restorecon 을 실행하면 httpd_sys_content_t  컨텍스트로 복구
  • httpd_sys_content_t  를 갖는 test.html이 /root 에 있을 경우
    restorecon 을 실행하면 admin_home_t  컨텍스트로 복구

이제 test.html 에 대해 다음과 같이 "restorecon /var/www/html/test.html" 명령어를 적용하여 문제를 해결해 보자. 대상이 디렉터리일 경우 -R 옵션을 붙여서 실행하면 하위 디렉터리까지 재귀적으로 처리해 주므로 "restorecon -R /var/www/html" 명령어를 실행해도 된다.

restorecon 을 수행한 후에 결과를 확인해 보면 위와 같이 보안 컨텍스트가 복구된 것을 알 수 있다.


방법 #3 - chcon

chcon 은 change context 의 약자로 객체의 보안 컨텍스트를 직접 지정할 수 있는 명령어이다. 지정할 적절한 보안 컨텍스트를 알아야 하므로 SELinux 에 경험많은 사용자에게 유리하다. 여러 가지 옵션이 있지만 가장 많이 사용되는 것은 재귀적으로 처리하는 -R 옵션과 컨텍스트를 지정하는 -t  옵션이다. "chcon -R -t httpd_sys_content_t /var/www/html/test.html"  명령어로  /var/www/html/test.html 에 적절한 보안 컨텍스트를 지정해 보자.

ls 로 결과를 보면 원하는 대로 보안 컨텍스트가 설정 되었음을 확인할 수 있다.


matchpathcon

SELinux에 익숙하지 않은 이상 특정 디렉터리에 어떤 보안 컨텍스트를 부여해야 하는지 모를 경우가 많다. 대부분의 SELinux 에러는 잘못된 보안 컨텍스트를 설정해서 발생하므로 경로에 따른 보안 컨텍스트를 알아 내는 것은 문제 해결을 위해 중요한 단계이다. matchpathcon 유틸리티를 사용하면 디렉터리별로 필요한 보안 컨텍스트를 알아 낼 수 있다. 사용은 matchpathcon 뒤에 보안 컨텍스트를 알아낼 디렉터리의 경로를 적어주면 된다. 여러 개의 경로를 알고 싶을 경우 공백을 구분자로 하여 적어 주면 된다.

# matchpathcon /var/log/ /var/www/ /etc/


/var/log system_u:object_r:var_log_t:s0

/var/www system_u:object_r:httpd_sys_content_t:s0

/etc system_u:object_r:etc_t:s0

/var/log, /var/www, /etc 세 개의 디렉터리가 각각 별도의 보안 컨텍스트를 필요로 함을 알수 있다. 잘못 설정된 보안 컨텍스트는 서비스의 오작동의 주요 원인이며 위에서 설명한 restorecon 이나 chcon 명령어를 사용하여 수정할 수 있다.


semange 패키지

이제부터 소개할 유틸리티는 추가로 설치해야 하는 패키지이다. 대부분의 SELinux 유틸리티는 python 으로 작성되어 제공되고 있다. 전 장에서 익힌 yum 명령어를 사용하여 패키지를 설치해 보자. 패키지명은 policycoreutils-python-2.0.83-19.39.el6.x86_64 이므로 다음과 같이 설치하면 된다.

yum install -y policycoreutils-python  


semanage

semanage는 SELinux 의 보안 정책을 조회하고 추가/변경/삭제할 수 있는 명령행 기반의 유틸리티이다. 보안 컨텍스트는 파일이나 네트워크 포트, 네트워크 인터페이스등으로 분리 되어 있으며 이중에서 향후 다룰 서비스 데몬이 SELinux 와 조화롭게 동작하려면 꼭 알아 두어야 할 것이 네트워크 포트 컨텍스트이다. 이제 semanage 로 이 컨텍스트를 사용하는 방법을 알아 보자.


포트 컨텍스트

포트 컨텍스트는 port 명령어를 통해서 확인할 수 있으며 많이 사용하는 옵션은 설정된 포트 목록을 출력하는 -l 옵션이다. 아파치 http 가 접근할 수 있는 포트는 http_port_t 컨텍스트를 가진 포트이므로 httpd_port_t 컨텍스트는 어떤 포트에 연결할 수 있는지 확인해 보자.

# semanage port -l | grep http_port_t http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000

위 결과를 보면 80부터 9,000 까지 총 8개의 포트에 연결이 가능함을 알 수 있다. 만약 아파치 웹 서버를 800포트를 통해 서비스를 해야 한다면 어떻게 해야 할까. 아파치의 설정 파일에서 사용하는 포트를 지정하는 Listen 항목에서 80 대신 800 을 지정하고 아파치 웹서버를 재시작해 보면 다음과 같은 에러가 발생하고 웹서버가 구동되지 않는 것을 볼 수 있다.

service httpd restart

(13)Permission denied: make_sock: could not bind to address [::]:800
(13)Permission denied: make_sock: could not bind to address 0.0.0.0:800

아파치가 루트로 구동되지만 부여된 컨텍스트인 http_port_t 는 위에서 본 8개 포트이외에는 연결할 수 없으므로 발생하는 현상이다.

이 문제를 해결하려면 semanage 명령어를 사용하여 http_port_t 컨텍스트가 연결할 수 있는 포트를 추가해 주면 되며 port 옵션 뒤에 포트를 추가하는 옵션인 -a 와 사용할 프로토콜, 보안 컨텍스트, 포트 번호를 지정해 주면 된다. 

# semanage port -a -p tcp -t http_port_t 8080 # semanage port -l | grep http_port_t http_port_t tcp 800, 80, 81, 443, 488, 8008, 8009, 8443, 9000

HTTP 는 tcp 를 사용하므로 -p tcp 옵션과  보안 컨텍스트를 지정하는 -t http_port_t 그리고 허용할 포트 번호 800 을 지정하여 semanage 의 정책을 설정하였고 http_port_t 에 800 이 허용된 것을 확인할 수 있다.

이제 아파치 httpd 를 재구동하면 800 포트를 제대로 리슨하고 있는 것을 확인할 수 있다.


웹 서버 장비에서 톰캣의 WAS 를 포트 번호를 달리 하여 여러 개 구동하고 아파치 httpd와 연동하는 경우가 많이 있다. 이 책 후반부에 다룰 여러 서비스도 하나의 서버에서 구동되는 것을 가정하여 작성되고 있다.

이럴 경우 기본 설정된 포트 번호가 아니어서 SELinux 에 의해 차단될 수 있으므로  semanage 명령어를 사용하여 port 를 추가해 주면 문제없이 아파치와 여러 개의 톰캣을 연동할 수 있으며 이에 대한 자세한 내용은 각 서비스 항목에서 다룰 것이다.


설정된 포트는 -d 옵션으로 삭제할 수 있다. 추가할 때와 마찬가지로 -p 로 tcp 인지 udp 인지 지정해 주어야 한다.

# semanage port -d -p tcp 800 # semanage port -l | grep http_port_t

http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000


파일 컨텍스트 

독자들은 /var/www/html 밑에 cp 로 파일을 복사하거나 또는 에디터등으로 파일을 새로 만들면 자동으로 httpd_sys_content_t 컨텍스트가 부여되는 것을 알고 있다. 또 보안 컨텍스트를 복구하는 명령인 restorecon 을 사용하면 위치에 맞는 컨텍스트를 복구해 준다는 것을 알고 있다.어떻게 이게 가능한 걸까? 


SELinux 는 사용 편의성을 위해 특정 경로에 생성되는 파일이나 디렉터리는 자동으로 특정 컨텍스트를 부여하도록 설정되어 있다. 파일 컨텍스트는 바로 이런 SELinux 의 설정을 확인하고 추가/변경할 수 있는 요소이다.

파일 컨텍스트는 semanage 명령어 뒤에 fcontext 옵션을 주고 실행하면 된다. 먼저 설정된 파일 컨텍스트의 목록을 표시하는 옵션인 -l 을 사용해 보자. 많은 결과가 나오므로 httpd_sys_content_t 컨텍스트가 부여되는 경로를 확인해 보자.

"semanage fcontext -l|grep httpd_sys_content_t" 명령어를 실행하여 현재 설정값을 확인해 보자

위와 같이 /var/www/ 경로 밑에 생성되는 모든 파일은 httpd_sys_content_t 가 부여되게 설정되었음을 확인할 수 있다.

만약 웹 컨텍츠를 /data/www 디렉터리에서 서비스를 한다면 파일 컨텍스트를 어떻게 설정해야 할까. 기존에 없는 위치이므로 -a 옵션으로 추가를 하고 -t 옵션에 부여할 컨텍스트를 적고 정규식으로 설정할 경로를 적어 주면 된다.

다음은 파일 컨텍스트에 새로운 경로를 추가하는 semanage 명령어이다.

# semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"


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

# semanage fcontext -d "/data/www(/.*)?" # semanage fcontext -l|grep httpd_sys_content_t


audit2why

audit2why 는 시스템의 감사(audit) 로그에서 SELinux 가 왜 차단했는지 보여주는 유틸리티이다. 다음과 같이 파이프를 사용하여 감사 로그 파일의 경로를 지정해 주면 된다. SELinux 의 보안 로그는 /var/log/audit/audit.log 에 남으므로 관리자 권한이 있어야 볼 수 있다. 알수 없는 이유로 서비스 데몬이 차단되었다면 audit2why 로 감사 로그 파일을 먼저 확인해 보자.

# audit2why < /var/log/audit/audit.log   type=AVC msg=audit(1402847410.831:568): avc: denied { getattr } for pid=4410 comm="httpd" path="/var/new-html/index.html" dev=dm-0 ino=267545 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access.

잘못된 Type Enforcement 에 의해 차단되었다고 알려주고 audit2allow 로 보안 모듈을 만들어서 문제를 해결하라고 하고 있다. 위 에러는 잘못된 보안 컨텍스트때문이므로 간단하게 restorecon 이나 chcon 으로 해결해야 하지만 드물게 보안 정책을 새로 만들어 주어야 하는 경우가 있다.

audit2allow 는 이럴 때 사용할 수 있는 SELinux 의 보안 정책을 만드는 유틸리티로 본 도서의 범위를 넘어서므로 관심있는 독자들은 관련 설명서를 읽고 사용법을 익혀 보기 바란다.


setroubleshoot-server 패키지

SELinux 에 익숙하지 않다면 로그 파일을 보고 원인을 파악하기는 쉽지 않다. audit2why 유틸리티가 있으나 처음 접하면 난해하기는 마찬가지이고 이런 어려움때문에 SELinux 문제 발생시 대처가 어려워 사용을 망설이게 만들고는 한다.

setroubleshoot-server 는 python 으로 만들어진 유틸리티로 어려운 SELinux AVC 메시지를 알기 쉽게 번역해 주고 처리 방안도 제시해 주는 유틸리티이다. audit2why 가 익숙하지 않다면 꼭 설치해서 사용하기를 권장하는 유틸리티이다.

이제부터 설치와 사용하는 방법을 알아 보자. 


설치

기본적으로 설치되지는 않는 패키지이므로 yum 으로 설치하여 사용하면 된다.  다음 명령어로 설치해 보자.

yum install setroubleshoot-server -y


설정

setroubleshoot-server 는 dbus 패키지에 포함된 message bus 라는 데몬을 필요로 한다.기본 데몬이라 별도로 설치할 필요는 없지만 setroubleshoot-server 설치후 dbus를 재구동 해주는게 좋다.다음 명령어로 재구동을 할 수 있다.

service messagebus restart


사용

이제 setroubleshoot 를 사용할 준비가 되었으니 어떻게 동작하는지 확인해 보자.

이를 위해 잘못된 보안 컨텍스트를 갖는 파일을 웹 서버 디렉터리에 만들고 브라우저에서 이 파일을 요청하여 권한 문제를 발생시킨후에 로그 파일을 확인해 보자.

# touch /var/www/html/test.html # chcon -t admin_home_t /var/www/html/test.html

이제 텍스트 브라우저인 텍스트 브라우저인 links 로 컨텐츠를 요청하는 명령어인 "links -dump http://localhost/test.html" 를 실행하면 permission denied 에러가 발생하는 것을 확인할 수 있다.


이제 setroubleshoot 가 진단 및 분석한 메시지를 확인할 차례이다. setroubleshoot 의 메시지는 시스템 로그가 남는 파일인 /var/log/messages 파일에 남게 된다. tail -f /var/log/messages 로 로그를 확인해 보면 다음과 같은 형식으로 로그 메시지를 남는 것을 확인할 수 있다. 이제 로그를 분석해 보자.


첫 번째는 로그가 발생한 날자와 시간이 표시된다. 그 후에 SELinux 가 /usr/sbin/httpd 가 /var/www/html/test.html 에 대한 접근을 차단했다는 내용이 표시되었다. 가장 중요한 부분은 자세한 SELinux 메시지를 보려면 run sealert -l 221ff52b-ad8b-4148-9185-2e62d854f397 를 실행하라는 부분이다.

안내대로 쉘에서 다음 명령어를 실행해 보자. 

# sealert -l 221ff52b-ad8b-4148-9185-2e62d854f397 SELinux is preventing /usr/sbin/httpd from getattr access on the 파일 /var/www/html/test.html. ***** 플러그인 restorecon (99.5 confidence) 제안 ********************************* If 레이블을 수정하고자 합니다. /var/www/html/test.html 디폴트 레이블은 httpd_sys_content_t이 되어야 합니다. Then restorecon을 실행할 수 있습니다. Do # /sbin/restorecon -v /var/www/html/test.html

실행하면 위와 같이 보안 컨텍스트가 잘못 되었다는 것을 알려주고 restorecon 을 실행하는 옵션까지 제안하고 있으므로 SELinux 에서 차단된 원인을 손쉽게 찾고 문제를 해결할 수 있다. 


sealert

위에서 실행한 sealert 유틸리티는 setroubleshoot 패키지의 두 가지 컴포넌트중 하나로(다른 하나는 setroubleshootd 데몬이다)  X-Windows 에서 GUI 또는 커맨드에서 동작한다.

setroubleshoot 서버가 수집하고 분석한 SELinux 에러 로그를 사용자 단에서 조회할 수 있게 해주며 audit.log 에 남은 SELinux 로그도 분석해 준다.

sealert 은 여러 가지 옵션이 있는데 가장 많이 사용되는 옵션은 특정 이벤트 id 를 조회하는 -l 옵션이다.

또 로그 파일을 분석하는 -a 옵션을 사용하면 audit.log 파일내에서 SELinux 관련 에러 메시지만 뽑아서 사용자 친화적으로 표시해 준다.

sealert -a /var/log/audit/audit.log

이제 SELinux 의 개념과 보안 컨텍스트, SELinux 를 잘 사용하기 위한 여러 가지 유틸리티와 setroubleshoot 패키지를 살펴 보았다.

독자들은 이제 SELinux 의 구조와 기본 개념, 동작 방식에 대해서 이해 했으리라 믿는다. 

SELinux 은 리눅스 보안의 가장 중요한 요소중 하나이며 웹서비스나 FTP 서비스등을 운영시 필수로 켜 놓는 걸 레드햇사와 여러 보안 전문가들은 권장하고 있다.


이제 SELinux 사용시 문제 해결 절차에 대해서 살펴 보고 이 장을 마치도록 하자.