ブログ | NGINX

SELinux で NGINX と NGINX Plus を使用する

NGINX-F5 水平黒タイプ RGB の一部
オーウェン・ギャレット サムネイル
オーウェン・ギャレット
2018年8月17日公開

編集者 – 「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 ) 内のコンテンツにアクセスできるようになります。 アップストリームの場所へのプロキシやソケットを介した他のプロセスとの通信など、他の多くの操作は許可されません。

NGINX の SELinux を一時的に無効にする

httpd_tコンテキストの SELinux 制限を一時的に無効にして、NGINX が非 SELinux OS と同じ操作をすべて実行できるようにするには、 httpd_tコンテキストを許可ドメインに割り当てます。 詳細については次のセクションを参照してください。

# semanage 許可 -a httpd_t

SELinux モードの変更

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 が強制モードで実行されている場合にのみ発生する問題が発生した場合は、許可モードで記録された例外を確認し、それらを許可するようにセキュリティ ポリシーを更新します。

問題 1: プロキシ接続は禁止されています

デフォルトでは、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_relayhttpd_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

問題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: 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 つのオプションがあります。

オプション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 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

この変更は再起動後も維持されます。

問題3: NGINX は追加ポートにバインドできません

デフォルトでは、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 設定のhttpstream 、または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 リロード

問題4: 開いているファイルが多すぎますエラー

開いているファイルの数の制限 ( RLIMIT_NOFILE ) を超えると、エラー ログに次のメッセージが表示されます。

開いているファイルが多すぎます

NGINXワーカープロセスがエラーを生成する場合

ほとんどの場合、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 マスター プロセスがエラーを報告する場合は、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 コンテンツにリダイレクトされます。"