블로그 | NGINX

SELinux와 함께 NGINX 및 NGINX Plus 사용

NGINX-F5-수평-검정-유형-RGB의 일부
오웬 개렛 썸네일
오웬 개렛
2018년 8월 17일 게시

편집자 - “NGINX: RHEL 6.6/CentOS 6.6으로 업그레이드할 때 SELinux가 변경됩니다. 여기로 리디렉션됩니다. 이 기사에서는 최신의 일반화된 정보를 제공합니다.

최신 Red Hat Enterprise Linux(RHEL) 및 관련 배포판의 SELinux(Security-Enhanced Linux)에 대한 기본 설정은 편의성보다는 보안에 더 중점을 두어 매우 엄격할 수 있습니다. 기본 설정은 기본 구성에서 NGINX Open Source 및 NGINX Plus의 기능을 제한하지 않지만 SELinux에서 명시적으로 허용하지 않는 한 사용자가 구성할 수 있는 다른 기능은 차단될 수 있습니다. 이 문서에서는 발생 가능한 문제와 이를 해결하기 위해 권장되는 방법을 설명합니다.

[편집자 - 이 문서는 NGINX Open Source와 NGINX Plus에 모두 적용됩니다. 읽기 편하도록 전체적으로 "NGINX"라는 용어를 사용합니다.

CentOS는 원래 RHEL에서 파생된 관련 배포판으로 NGINX 및 NGINX Plus에서 지원됩니다. 또한 NGINX Plus는 관련 Amazon Linux 및 Oracle Linux 배포판을 지원합니다. 기본 SELinux 설정은 CentOS 및 RHEL과 다를 수 있습니다. 공급업체의 설명서를 참조하세요.]

SELinux 개요

 

SELinux는 최신 RHEL 및 CentOS 서버에서는 기본적으로 활성화되어 있습니다. 각 운영 체제 객체(프로세스, 파일 설명자, 파일 등)에는 객체가 수행할 수 있는 권한과 작업을 정의하는 SELinux 컨텍스트가 지정됩니다. RHEL 6.6/CentOS 6.6 이상에서는 NGINX가 httpd_t 컨텍스트로 표시됩니다.

# ps auZ | grep nginx unconfined_u:system_r: httpd_t :s0 3234 ? Ss 0:00 nginx: 마스터 프로세스 /usr/sbin/nginx \ -c /etc/nginx/nginx.conf unconfined_u:system_r: httpd_t :s0 3236 ? Ss 0:00 nginx: 워커 프로세스

httpd_t 컨텍스트는 NGINX가 일반 웹 서버 포트에서 수신 대기하고, /etc/nginx 에 있는 구성 파일에 접근하고, 표준 docroot 위치( /usr/share/nginx )에 있는 콘텐츠에 접근할 수 있도록 허용합니다. 이는 업스트림 위치로의 프록싱이나 소켓을 통한 다른 프로세스와의 통신 등 다른 많은 작업을 허용하지 않습니다.

NGINX에 대한 SELinux를 일시적으로 비활성화

NGINX가 SELinux가 아닌 OS에서와 동일한 모든 작업을 수행할 수 있도록 httpd_t 컨텍스트에 대한 SELinux 제한을 일시적으로 비활성화하려면 httpd_t 컨텍스트를 허용 도메인에 할당합니다. 자세한 내용은 다음 섹션을 참조하세요.

# semanage 허용 -a httpd_t

SELinux 모드 변경

SELinux는 시행 , 허용 또는 비활성화 모드( 도메인 이라고도 함)로 실행할 수 있습니다. 기본(엄격한) 권한을 위반할 수 있는 NGINX 구성 변경을 하기 전에 테스트 환경(가능한 경우) 또는 프로덕션 환경에서 SELinux를 적용 모드에서 허용 모드로 변경할 수 있습니다. 허용 모드에서 SELinux는 모든 작업을 허용하지만, 시행 모드에서 보안 정책을 위반할 수 있는 작업은 기록합니다.

허용 도메인 목록에 httpd_t를 추가하려면 다음 명령을 실행하세요.

# semanage 허용 -a httpd_t

허용 도메인 목록에서 httpd_t를 삭제하려면 다음을 실행하세요.

# semanage 허용 -d httpd_t

모드를 전역적으로 허용 으로 설정하려면 다음을 실행합니다.

# 강제 0

모드를 전역적으로 적용 으로 설정하려면 다음을 실행합니다.

# 강제 1

SELinux 보안 예외 해결

허용 모드에서는 보안 예외가 기본 Linux 감사 로그인 /var/log/audit/audit.log 에 기록됩니다. NGINX가 적용 모드에서 실행할 때만 발생하는 문제가 발생하는 경우, 허용 모드에서 기록된 예외를 검토하고 보안 정책을 업데이트하여 이를 허용하세요.

문제 1: 프록시 연결이 금지되었습니다

기본적으로 SELinux 구성은 NGINX가 원격 HTTP, FastCGI 또는 다른 서버에 연결하는 것을 허용하지 않습니다. 이는 다음과 같은 감사 로그 메시지에서 나타납니다.

type=AVC msg=audit(1415714880.156:29): avc: pid=1349에 대한 { name_connect } 거부됨 \
comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 \
tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket
type=SYSCALL msg=audit(1415714880.156:29): arch=c000003e syscall=42 성공=아니요 \
종료=-115 a0=b \a1=16125f8 a2=10 a3=7fffc2bab440 항목=0 ppid=1347 pid=1349 \
auid=1000 uid=497 gid=496 euid=497 suid=497 fsuid=497 egid=496 sgid=496 fsgid=496 \
tty=(없음) ses=1 comm="nginx" exe="/usr/sbin/nginx" \
subj=unconfined_u:system_r:httpd_t:s0 키=(null)

audit2why 명령은 메시지 코드( 1415714880.156:29 )를 해석합니다.

# grep 1415714880.156:29 /var/log/audit/audit.log | audit2why type=AVC msg=audit(1415714880.156:29): avc: pid=1349에 대해 { name_connect }가 거부되었습니다. \ comm="nginx" dest=8080 scontext=unconfined_u:system_r:httpd_t:s0 \ tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket 다음에 의해 발생했습니다.
        다음 부울 중 하나가 잘못 설정되었습니다.
        설명:
        httpd가 릴레이 역할을 하도록 허용하려면 다음을 실행하여 액세스를 허용합니다. # setsebool -P httpd_can_network_relay 1 설명:
        HTTPD 스크립트와 모듈이 TCP를 사용하여 네트워크에 연결하도록 허용합니다.
 
        다음을 실행하여 액세스를 허용하세요: # setsebool -P httpd_can_network_connect 1

audit2why 의 출력은 httpd_can_network_relayhttpd_can_network_connect 부울 옵션 중 하나 또는 둘 다를 활성화하여 NGINX가 프록시 연결을 만들 수 있음을 나타냅니다. 이러한 기능은 일시적으로 또는 영구적으로 활성화할 수 있습니다. 영구적으로 활성화하려면 출력에 표시된 대로 ‑P 플래그를 추가합니다.

부울 옵션 이해

sesearch 명령은 부울 옵션에 대한 자세한 정보를 제공하며, setools 패키지를 설치한 경우 사용할 수 있습니다( yum install setools ). 여기서는 httpd_can_network_relayhttpd_can_network_connect 옵션에 대한 출력을 보여줍니다.

httpd_can_network_relay 부울 옵션

다음은 httpd_can_network_relay 옵션에 대한 sesearch 명령의 출력입니다.

# sesearch -A -s httpd_t -b httpd_can_network_relay 10개의 의미적 av 규칙을 찾았습니다. httpd_t gopher_port_t : tcp_socket name_connect 허용; httpd_t http_cache_client_packet_t : 패킷 { 수신 보내기 } 허용; httpd_t ftp_port_t : tcp_socket name_connect 허용; httpd_t ftp_client_packet_t : 패킷 { 수신 보내기 } 허용; httpd_t http_client_packet_t : 패킷 { 수신 보내기 } 허용; httpd_t squid_port_t : tcp_socket name_connect 허용; httpd_t http_cache_port_t : tcp_socket name_connect 허용; httpd_t http_port_t : tcp_socket name_connect 허용; httpd_t gopher_client_packet_t : 패킷 { send recv } 허용; httpd_t memcache_port_t : tcp_socket name_connect 허용;

이 출력은 httpd_can_network_relay가 httpd_t 컨텍스트로 레이블이 지정된 프로세스(예: NGINX)가 http_port_t 유형을 포함한 다양한 유형의 포트에 연결할 수 있도록 허용함을 나타냅니다.

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

더 많은 포트를 추가하려면(여기서는8082 ) http_port_t 에 허용된 포트 집합에 다음을 실행합니다.

# semanage 포트 -a -t http_port_t -p tcp 8082

다음 예와 같이 이 명령의 출력에서 포트가 이미 정의되어 있다고 나오면 해당 포트는 다른 세트에 포함되어 있다는 의미입니다. 다른 서비스에 부정적인 영향을 줄 수 있으므로 http_port_t 로 다시 할당하지 마세요.

# semanage 포트 -a -t http_port_t -p tcp 8080 /usr/sbin/semanage: 포트 tcp/8080이 이미 정의되어 있습니다 # semanage port -l | grep 8080 http_cache_port_t tcp 3128, 8080, 8118, 8123, 10001-10010

httpd_can_network_connect 부울 옵션

다음은 httpd_can_network_connect 옵션에 대한 sesearch 명령의 출력입니다.

# sesearch -A -s httpd_t -b httpd_can_network_connect 1개의 의미적 av 규칙을 찾았습니다: allow httpd_t port_type : tcp_socket name_connect ;

이 출력은 httpd_can_network_connect가 httpd_t 컨텍스트로 레이블이 지정된 프로세스(예: NGINX)가 port_type 속성이 있는 모든 TCP 소켓 유형에 연결할 수 있도록 허용함을 나타냅니다. 나열하려면 다음을 실행하세요.

# seinfo -aport_type -x

2호: 파일 접근이 금지되었습니다

기본적으로 SELinux 구성은 NGINX가 잘 알려진 승인된 위치 외부의 파일에 액세스하는 것을 허용하지 않습니다. 이는 다음과 같은 감사 로그 메시지에서 표시됩니다.

type=AVC msg=audit(1415715270.766:31): avc: pid=1380에 대한 {getattr} 거부됨 \
comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 \
scontext=unconfined_u:system_r:httpd_t:s0 \
tcontext=unconfined_u:object_r:default_t:s0 tclass=file

audit2why 명령은 메시지 코드( 1415715270.766:31 )를 해석합니다.

# grep 1415715270.766:31 /var/log/audit/audit.log | audit2why type=AVC msg=audit(1415715270.766:31): avc: pid=1380에 대해 { getattr } 거부 \ comm="nginx" path="/www/t.txt" dev=vda1 ino=1084 \ scontext=unconfined_u:system_r:httpd_t:s0 \ tcontext=unconfined_u:object_r:default_t:s0 tclass=file 다음에 의해 발생:
        유형 적용(TE) 허용 규칙이 없습니다.
 
        audit2allow를 사용하면 이 액세스를 허용하기 위한 로드 가능한 모듈을 생성할 수 있습니다.

파일 접근이 금지된 경우, 두 가지 옵션이 있습니다.

옵션 1: 파일 레이블 수정

NGINX( httpd_t 컨텍스트로 레이블이 지정된 프로세스)가 파일에 액세스할 수 있도록 파일 레이블을 수정합니다.

# chcon -v --type=httpd_sys_content_t /www/t.txt

기본적으로 이 수정 사항은 파일 시스템의 레이블이 변경되면 삭제됩니다. 변경 사항을 영구적으로 적용하려면 다음을 실행하세요.

# semanage fcontext -a -t httpd_sys_content_t /www/t.txt # restorecon -v /www/t.txt

파일 그룹의 파일 레이블을 수정하려면 다음을 실행하세요.

# semanage fcontext -a -t httpd_sys_content_t '/www(/.*)?' # restorecon -Rv /www

옵션 2: httpd_t 도메인 권한 확장

추가 파일 위치에 대한 액세스를 허용하도록 httpd_t 에 대한 정책을 확장합니다.

# grep nginx /var/log/audit/audit.log | audit2allow -m nginx > nginx.te # cat nginx.te 모듈 nginx 1.0; require { 유형 httpd_t; 유형 default_t; 유형 http_cache_port_t; 클래스 tcp_socket name_connect; 클래스 파일 { 읽기 getattr 열기 }; } #============== httpd_t =============== 허용 httpd_t default_t:파일 { 읽기 getattr 열기 }; #!!!! 다음 부울 값 중 하나를 사용하여 이 avc를 허용할 수 있습니다. # httpd_can_network_relay, httpd_can_network_connect allow httpd_t http_cache_port_t:tcp_socket name_connect;

컴파일된 정책을 생성하려면 -M 옵션을 포함하세요.

# grep nginx /var/log/audit/audit.log | audit2allow -M nginx

정책을 로드하려면 semodule -i를 실행한 다음 semodule -l 로 성공을 확인하세요.

# semodule -i nginx.pp # semodule -l | grep nginx nginx 1.0

이 변경 사항은 재부팅 후에도 유지됩니다.

3호: NGINX가 추가 포트에 바인딩할 수 없음

기본적으로 SELinux 구성은 NGINX가 http_port_t 유형에서 허용 목록에 있는 기본 포트 외의 TCP 또는 UDP 포트를 수신( bind() )하는 것을 허용하지 않습니다.

# semanage 포트 -l | grep http_port_t http_port_t tcp 80, 443, 488, 8008, 8009, 8443

NGINX 구성에서 http , stream 또는 mail 컨텍스트의 listen 지시어를 사용하여 허용 목록에 없는 포트에서 수신하도록 NGINX를 구성하려고 하면 이 NGINX 로그 항목에서 표시된 대로 NGINX 구성을 확인( nginx -t )하거나 다시 로드할 때 오류가 발생합니다.

YYYY / MM / DD hh : mm : ss [emerg] 46123#0: 0.0.0.0:8001에 대한 bind()가 실패했습니다(13: 허가 거부)

semanage를 사용하면 원하는 포트(여기서는 8001)를 http_port_t 유형에 추가할 수 있습니다.

# semanage 포트 -a -t http_port_t -p tcp 8001

새로운 구성으로 NGINX를 다시 로드합니다.

# nginx -s 다시 로드

4호: 너무 많은 파일이 열려 있습니다 오류

열린 파일 수 제한( RLIMIT_NOFILE )을 초과하면 오류 로그에 다음 메시지가 나타납니다.

너무 많은 파일이 열려 있습니다

NGINX Worker 프로세스가 오류를 생성하는 경우

대부분의 경우, NGINX 워커 프로세스가 이 오류를 보고하지만, SELinux가 setrlimit() 시스템 호출을 허용하지 않기 때문에 NGINX worker_rlimit_nofile 지시어를 사용하여 한도를 늘릴 수 없습니다. 이는 오류 및 감사 로그의 다음 메시지에서 보고되었습니다.

  • CentOS/RHEL 7.4+의 경우 /var/log/nginx/error.log 에서:

    YYYY / MM / DD hh : mm : ss [경고] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) 실패(13: 허가 거부)
    
  • CentOS/RHEL 8.0+의 경우 /var/log/nginx/error.log 에서:

    YYYY / MM / DD hh : mm : ss [경고] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) 실패(1: 작업이 허용되지 않습니다)
    
  • CentOS/RHEL 7.4+의 경우 /var/log/audit/audit.log , CentOS/RHEL 8.0+의 경우 /var/log/messages 에서:

    type=AVC msg=audit(1437731200.211:366): avc: pid=12066에 대해 { setrlimit } 거부됨 \ comm="nginx" scontext=system_u:system_r:httpd_t:s0 \
    tcontext=system_u:system_r:httpd_t:s0 tclass=process
    

한도를 늘리려면 대신 루트 사용자로 다음 명령을 실행하세요.

$ setsebool -P httpd_setrlimit 1

NGINX 마스터 프로세스가 오류를 생성하는 경우

NGINX 마스터 프로세스가 오류를 보고하면 NGINX의 systemd 단위 파일을 업데이트해야 합니다. 이렇게 하면 마스터 및 워커 프로세스 모두에 대한 파일 설명자 제한이 설정됩니다.

  1. nginx.service 구성을 위한 디렉토리를 만듭니다.

    $ mkdir /etc/systemd/system/nginx.service.d
    
  2. /etc/systemd/system/nginx.service.d/nofile_limit.conf 에 다음 줄을 추가합니다.

    [서비스]LimitNOFILE=65535
    
  3. systemd 데몬 구성을 다시 로드하고 NGINX를 다시 시작합니다.

    $ systemctl 데몬 재로드 $ systemctl 재시작 nginx.service
    

추가 자료

SELinux는 운영체제 권한을 관리하는 복잡하고 강력한 기능입니다. 추가 정보는 다음 문서에서 확인할 수 있습니다.


"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."