편집자 - “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 nginxunconfined_u:system_r:httpd_t:s0 3234 ? Ss 0:00 nginx: master process /usr/sbin/nginx \
-c /etc/nginx/nginx.conf
unconfined_u:system_r:httpd_t:s0 3236 ? Ss 0:00 nginx: worker process
httpd_t
컨텍스트는 NGINX가 일반 웹 서버 포트에서 수신 대기하고, /etc/nginx 에 있는 구성 파일에 접근하고, 표준 docroot 위치( /usr/share/nginx )에 있는 콘텐츠에 접근할 수 있도록 허용합니다. 이는 업스트림 위치로의 프록싱이나 소켓을 통한 다른 프로세스와의 통신 등 다른 많은 작업을 허용하지 않습니다.
NGINX가 SELinux가 아닌 OS에서와 동일한 모든 작업을 수행할 수 있도록 httpd_t
컨텍스트에 대한 SELinux 제한을 일시적으로 비활성화하려면 httpd_t
컨텍스트를 허용 도메인에 할당합니다. 자세한 내용은 다음 섹션을 참조하세요.
# semanage permissive -a httpd_t
SELinux는 시행 , 허용 또는 비활성화 모드( 도메인 이라고도 함)로 실행할 수 있습니다. 기본(엄격한) 권한을 위반할 수 있는 NGINX 구성 변경을 하기 전에 테스트 환경(가능한 경우) 또는 프로덕션 환경에서 SELinux를 적용 모드에서 허용 모드로 변경할 수 있습니다. 허용 모드에서 SELinux는 모든 작업을 허용하지만, 시행 모드에서 보안 정책을 위반할 수 있는 작업은 기록합니다.
허용 도메인 목록에 httpd_t를
추가하려면 다음 명령을 실행하세요.
# semanage permissive -a httpd_t
허용 도메인 목록에서 httpd_t를
삭제하려면 다음을 실행하세요.
# semanage permissive -d httpd_t
모드를 전역적으로 허용 으로 설정하려면 다음을 실행합니다.
# setenforce 0
모드를 전역적으로 적용 으로 설정하려면 다음을 실행합니다.
# setenforce 1
SELinux 보안 예외 해결
허용 모드에서는 보안 예외가 기본 Linux 감사 로그인 /var/log/audit/audit.log 에 기록됩니다. NGINX가 적용 모드에서 실행할 때만 발생하는 문제가 발생하는 경우, 허용 모드에서 기록된 예외를 검토하고 보안 정책을 업데이트하여 이를 허용하세요.
기본적으로 SELinux 구성은 NGINX가 원격 HTTP, FastCGI 또는 다른 서버에 연결하는 것을 허용하지 않습니다. 이는 다음과 같은 감사 로그 메시지에서 나타납니다.
type=AVC msg=audit(1415714880.156:29): avc: denied { name_connect } for pid=1349 \
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 success=no \
exit=-115 a0=b \a1=16125f8 a2=10 a3=7fffc2bab440 items=0 ppid=1347 pid=1349 \
auid=1000 uid=497 gid=496 euid=497 suid=497 fsuid=497 egid=496 sgid=496 fsgid=496 \
tty=(none) ses=1 comm="nginx" exe="/usr/sbin/nginx" \
subj=unconfined_u:system_r:httpd_t:s0 key=(null)
audit2why
명령은 메시지 코드( 1415714880.156:29
)를 해석합니다.
# grep 1415714880.156:29 /var/log/audit/audit.log | audit2whytype=AVC msg=audit(1415714880.156:29): avc: denied { name_connect } for pid=1349 \
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
Was caused by:
One of the following booleans was set incorrectly.
Description:
Allow httpd to act as a relay
Allow access by executing:
# setsebool -P httpd_can_network_relay 1
Description:
Allow HTTPD scripts and modules to connect to the network using TCP.
Allow access by executing:
# 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_relayFound 10 semantic av rules:
allow httpd_t gopher_port_t : tcp_socket name_connect ;
allow httpd_t http_cache_client_packet_t : packet { send recv } ;
allow httpd_t ftp_port_t : tcp_socket name_connect ;
allow httpd_t ftp_client_packet_t : packet { send recv } ;
allow httpd_t http_client_packet_t : packet { send recv } ;
allow httpd_t squid_port_t : tcp_socket name_connect ;
allow httpd_t http_cache_port_t : tcp_socket name_connect ;
allow httpd_t http_port_t : tcp_socket name_connect ;
allow httpd_t gopher_client_packet_t : packet { send recv } ;
allow httpd_t memcache_port_t : tcp_socket name_connect ;
이 출력은 httpd_can_network_relay가
httpd_t
컨텍스트로 레이블이 지정된 프로세스(예: NGINX)가 http_port_t
유형을 포함한 다양한 유형의 포트에 연결할 수 있도록 허용함을 나타냅니다.
# semanage port -l | grep http_port_thttp_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
더 많은 포트를 추가하려면(여기서는8082
) http_port_t
에 허용된 포트 집합에 다음을 실행합니다.
# semanage port -a -t http_port_t -p tcp 8082
다음 예와 같이 이 명령의 출력에서 포트가 이미
정의되어
있다고 나오면 해당 포트는 다른 세트에 포함되어 있다는 의미입니다. 다른 서비스에 부정적인 영향을 줄 수 있으므로 http_port_t
로 다시 할당하지 마세요.
# semanage port -a -t http_port_t -p tcp 8080
/usr/sbin/semanage: Port tcp/8080 already defined
# 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_connectFound 1 semantic av rules:
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: denied { getattr } for pid=1380 \
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 | audit2whytype=AVC msg=audit(1415715270.766:31): avc: denied { getattr } for pid=1380 \
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
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access.
파일 접근이 금지된 경우, 두 가지 옵션이 있습니다.
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
module nginx 1.0;
require {
type httpd_t;
type default_t;
type http_cache_port_t;
class tcp_socket name_connect;
class file { read getattr open };
}
#============= httpd_t ==============
allow httpd_t default_t:file { read getattr open };
#!!!! This avc can be allowed using one of these booleans:
# 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 port -l | grep http_port_thttp_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: bind() to 0.0.0.0:8001 failed (13: Permission denied)
semanage를
사용하면 원하는 포트(여기서는 8001)를 http_port_t
유형에 추가할 수 있습니다.
# semanage port -a -t http_port_t -p tcp 8001
새로운 구성으로 NGINX를 다시 로드합니다.
# nginx -s reload
너무 많은 파일이 열려 있습니다
오류열린 파일 수 제한( RLIMIT_NOFILE
)을 초과하면 오류 로그에 다음 메시지가 나타납니다.
Too many files are open
대부분의 경우, NGINX 워커 프로세스가 이 오류를 보고하지만, SELinux가 setrlimit()
시스템 호출을 허용하지 않기 때문에 NGINX worker_rlimit_nofile
지시어를 사용하여 한도를 늘릴 수 없습니다. 이는 오류 및 감사 로그의 다음 메시지에서 보고되었습니다.
CentOS/RHEL 7.4+의 경우 /var/log/nginx/error.log 에서:
YYYY/MM/DD hh:mm:ss [alert] 12066#0: setrlimit(RLIMIT_NOFILE, 2342) failed (13: Permission denied)
CentOS/RHEL 8.0+의 경우 /var/log/nginx/error.log 에서:
YYYY/MM/DD hh:mm:ss [alert] 3327#0: setrlimit(RLIMIT_NOFILE, 65535) failed (1: Operation not permitted)
CentOS/RHEL 7.4+의 경우 /var/log/audit/audit.log , CentOS/RHEL 8.0+의 경우 /var/log/messages 에서:
type=AVC msg=audit(1437731200.211:366): avc: denied { setrlimit } for pid=12066 \ 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 에 다음 줄을 추가합니다.
[Service]LimitNOFILE=65535
systemd 데몬 구성을 다시 로드하고 NGINX를 다시 시작합니다.
$ systemctl daemon-reload$ systemctl restart nginx.service
추가 자료
SELinux는 운영체제 권한을 관리하는 복잡하고 강력한 기능입니다. 추가 정보는 다음 문서에서 확인할 수 있습니다.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."