編集者 – 「NGINX: 「RHEL 6.6 / CentOS 6.6 へのアップグレード時の SELinux の変更」はここにリダイレクトされます。 この記事では、最新かつ一般的な情報を提供します。
最新の Red Hat Enterprise Linux (RHEL) および関連ディストリビューションの Security-Enhanced Linux (SELinux) のデフォルト設定は非常に厳格で、利便性よりもセキュリティが優先されることがあります。 デフォルト設定では、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の概要
最新の RHEL および CentOS サーバーでは、SELinux がデフォルトで有効になっています。 各オペレーティング システム オブジェクト (プロセス、ファイル記述子、ファイルなど) には、オブジェクトが実行できる権限と操作を定義する 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 は一般的な Web サーバー ポートをリッスンし、 /etc/nginx内の設定ファイルにアクセスし、標準の docroot の場所 ( /usr/share/nginx ) 内のコンテンツにアクセスできるようになります。 アップストリームの場所へのプロキシやソケットを介した他のプロセスとの通信など、他の多くの操作は許可されません。
httpd_t
コンテキストの SELinux 制限を一時的に無効にして、NGINX が非 SELinux OS と同じ操作をすべて実行できるようにするには、 httpd_t
コンテキストを許可ドメインに割り当てます。 詳細については次のセクションを参照してください。
# semanage 許可 -a httpd_t
SELinux は、 enforcing モード、 permissiveモード、またはdisabledモード (ドメインとも呼ばれます) で実行できます。 デフォルトの (厳格な) 権限に違反する可能性がある NGINX 構成変更を行う前に、テスト環境 (使用可能な場合) または実稼働環境で SELinux を強制モードから許可モードに変更できます。 許可モードでは、SELinux はすべての操作を許可しますが、強制モードではセキュリティ ポリシーに違反する操作をログに記録します。
許可ドメインのリストにhttpd_t を
追加するには、次のコマンドを実行します。
# semanage 許可 -a httpd_t
許可ドメインのリストからhttpd_t を
削除するには、次のコマンドを実行します。
# semanage 許可 -d httpd_t
モードをグローバルにpermissiveに設定するには、次のコマンドを実行します。
#強制0を設定する
モードをグローバルにenforcingに設定するには、次のコマンドを実行します。
#強制 1 を設定する
SELinux セキュリティ例外の解決
許可モードでは、セキュリティ例外はデフォルトの Linux 監査ログ/var/log/audit/audit.logに記録されます。 NGINX が強制モードで実行されている場合にのみ発生する問題が発生した場合は、許可モードで記録された例外を確認し、それらを許可するようにセキュリティ ポリシーを更新します。
デフォルトでは、SELinux 構成では、次のような監査ログ メッセージで示されるように、NGINX がリモート HTTP、FastCGI、またはその他のサーバーに接続することを許可しません。
type=AVC メッセージ=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 メッセージ=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=(なし) 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 | Audit2why 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 原因:
次のブール値の 1 つが正しく設定されていません。
説明:
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
ブール オプションの 1 つまたは両方を有効にすることで、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 ルールが見つかりました: 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; httpd_t gopher_client_packet_t : packet { send recv } を許可します。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_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: 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 原因:
タイプ強制 (TE) 許可ルールがありません。
このアクセスを許可するロード可能なモジュールを生成するには、audit2allow を使用します。
ファイルへのアクセスが禁止されている場合、2 つのオプションがあります。
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 }; #!!!! この 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 port -l | grep http_port_t http_port_t tcp 80、443、488、8008、8009、8443
NGINX を許可リストに登録されていないポートで listen するように設定しようとすると (NGINX 設定のhttp
、 stream
、またはmail
コンテキストでlisten
ディレクティブを使用)、NGINX 設定を検証 ( nginx
-t
) または再ロードすると、次の NGINX ログ エントリに示すようにエラーが発生します。
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
制限を増やすには、代わりにroot
ユーザーとして次のコマンドを実行します。
$ 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 コンテンツにリダイレクトされます。"