편집자 - “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가 아닌 OS에서와 동일한 모든 작업을 수행할 수 있도록 httpd_t
컨텍스트에 대한 SELinux 제한을 일시적으로 비활성화하려면 httpd_t
컨텍스트를 허용 도메인에 할당합니다. 자세한 내용은 다음 섹션을 참조하세요.
# semanage 허용 -a httpd_t
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가 적용 모드에서 실행할 때만 발생하는 문제가 발생하는 경우, 허용 모드에서 기록된 예외를 검토하고 보안 정책을 업데이트하여 이를 허용하세요.
기본적으로 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_relay
및 httpd_can_network_connect
부울 옵션 중 하나 또는 둘 다를 활성화하여 NGINX가 프록시 연결을 만들 수 있음을 나타냅니다. 이러한 기능은 일시적으로 또는 영구적으로 활성화할 수 있습니다. 영구적으로 활성화하려면 출력에 표시된 대로 ‑P
플래그를 추가합니다.
sesearch
명령은 부울 옵션에 대한 자세한 정보를 제공하며, setools 패키지를 설치한 경우 사용할 수 있습니다( yum
install
setools
). 여기서는 httpd_can_network_relay
및 httpd_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
기본적으로 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를 사용하면 이 액세스를 허용하기 위한 로드 가능한 모듈을 생성할 수 있습니다.
파일 접근이 금지된 경우, 두 가지 옵션이 있습니다.
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
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
이 변경 사항은 재부팅 후에도 유지됩니다.
기본적으로 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 다시 로드
너무 많은 파일이 열려 있습니다
오류열린 파일 수 제한( RLIMIT_NOFILE
)을 초과하면 오류 로그에 다음 메시지가 나타납니다.
너무 많은 파일이 열려 있습니다
대부분의 경우, 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의 systemd
단위
파일을 업데이트해야 합니다. 이렇게 하면 마스터 및 워커 프로세스 모두에 대한 파일 설명자 제한이 설정됩니다.
nginx.service
구성을 위한 디렉토리를 만듭니다.
$ mkdir /etc/systemd/system/nginx.service.d
/etc/systemd/system/nginx.service.d/nofile_limit.conf 에 다음 줄을 추가합니다.
[서비스]LimitNOFILE=65535
systemd 데몬 구성을 다시 로드하고 NGINX를 다시 시작합니다.
$ systemctl 데몬 재로드 $ systemctl 재시작 nginx.service
추가 자료
SELinux는 운영체제 권한을 관리하는 복잡하고 강력한 기능입니다. 추가 정보는 다음 문서에서 확인할 수 있습니다.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."