web-dev-qa-db-ja.com

audit2allowなしでnginxがUNIXソケットにアクセスすることをSELinuxに許可するにはどうすればよいですか?

/run/gunicorn/socketにあるUnixソケットを介して、gunginornにnginx転送要求があります。デフォルトでは、この動作はSELinuxでは許可されていません。

grep nginx /var/log/audit/audit.log
type=SERVICE_START msg=audit(1454358912.455:5390): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
type=AVC msg=audit(1454360194.623:7324): avc:  denied  { write } for  pid=9128 comm="nginx" name="socket" dev="tmpfs" ino=76151 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=sock_file
type=SYSCALL msg=audit(1454360194.623:7324): Arch=c000003e syscall=42 success=no exit=-13 a0=c a1=1f6fe58 a2=6e a3=7ffee1da5710 items=0 ppid=9127 pid=9128 auid=4294967295 uid=995 gid=993 euid=995 suid=995 fsuid=995 egid=993 sgid=993 fsgid=993 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1454361591.701:13343): avc:  denied  { connectto } for  pid=9128 comm="nginx" path="/run/gunicorn/socket" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:initrc_t:s0 tclass=unix_stream_socket
type=SYSCALL msg=audit(1454361591.701:13343): Arch=c000003e syscall=42 success=no exit=-13 a0=c a1=1f6fe58 a2=6e a3=7ffee1da5950 items=0 ppid=9127 pid=9128 auid=4294967295 uid=995 gid=993 euid=995 suid=995 fsuid=995 egid=993 sgid=993 fsgid=993 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)

私が見ているすべての場所(例: here および here ))で、これを有効にしてnginxにリクエストを送信し、SELinuxによってリクエストが拒否されるようにしてから、audit2allowは、将来のリクエストを許可します。この動作を明示的に許可するchconまたはsemanageコマンドを理解できません。

これが唯一の方法ですか?最初に試みを拒否せずに拒否されたものを有効にするツールを実行せずにnginxがソケットに書き込むことを許可するポリシーを設定できないことはばかげているようです。何が有効になっているかを正確に知るにはどうすればよいですか?自動でマシンをセットアップする場合、これはどのように機能するはずですか?

CentOS 7を使用しています。

9
drs

最初に試みを拒否せずに拒否されたものを有効にするツールを実行せずにnginxがソケットに書き込むことを許可するポリシーを設定できないことはばかげているようです。

いいえ、SELinuxは必須アクセス制御であり、デフォルトでは拒否されており、明示的に許可する必要があります。ポリシーの作成者が特定の(フランケン)スタックを考慮していない場合、またはデーモンの作成者がそれをSELinuxに対応させ、そのためのポリシーを作成していない場合は、あなたは自分で作業します。あなたはあなたのサービスが何をしているか、そしてそれらがどのようにSELinuxと相互作用しているかを分析し、それを許可するためにあなた自身のポリシーを考え出す必要があります。 audit2whyaudit2allow などに役立つツールがあります。

...これが唯一の方法ですか?

いいえ、しかし、それはあなたが何をしようとしているのか、そしてどのような解決策をどのようにしようとしているのかに依存します。たとえば、nginx(httpd_t)をポート8010(unreserved_port_t)にバインドすることができます。 nginxを起動すると失敗する

Starting nginx: nginx: [emerg] bind() to 0.0.0.0:8010 failed (13: Permission denied)

そして、最終的には監査ログを調べて見つけます

type=AVC msg=audit(1457904756.503:41673): avc:  denied  { name_bind } for
pid=30483 comm="nginx" src=8010 scontext=unconfined_u:system_r:httpd_t:s0
tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket

これをaudit2alllowで実行し、その結果を単純に受け入れる場合があります。

allow httpd_t port_t:tcp_socket name_bind;

これにより、httpd_tが任意のTCPポートに接続できるようになります。これはあなたが望むものではないかもしれません。

sesearch を使用してポリシーを調査し、httpd_tがどのポートタイプにname_bindできるかを確認できます

sesearch --allow -s httpd_t | grep name_bind
...
allow httpd_t http_port_t : tcp_socket name_bind ;
allow httpd_t http_port_t : udp_socket name_bind ;
...

他のタイプの中でも、http_tはhttp_port_tにバインドできます。これで semanage を使用して少し深く掘ることができます。

semanage port -l | grep http_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
...

ポート8010は表示されません。 nginxをポート8010にバインドしたいので、http_port_tリストに追加することは不合理ではありません

semanage port -a -t http_port_t -p tcp 8010

これで、nginxは、上記のようにすべてのtcpポートではなく、ポート8010にname_bindすることができます。

何が有効になっているのかを正確に知るにはどうすればよいですか?

ポリシーの変更はかなり読みやすく、上記のメッセージをaudit2allowで実行すると、

allow httpd_t httpd_sys_content_t:sock_file write;
allow httpd_t initrc_t:unix_stream_socket connectto;

かなり自明のようです。

最初のファイルはinum 76151のファイルを参照します。findを使用してファイル名を取得し(find/-inum 76151)、次にsemanage fcontext -a -t ...を使用してポリシーを変更し、restoreconを使用してコンテキストを修正できます。

もう1つは/run/gunicorn/socketに関連しますが、ここでもコンテキストが間違っています。 sesearchを使用すると、http_tがタイプ(特に)http_tのunix_stream_socketsに接続できることがわかります。たとえば、それに応じてコンテキストを変更できます

semanage fcontext -a -t httpd_t "/run/gunicorn(/.*)?"
restorecon -r /run

これは/ run/gunicornとツリーのコンテキストを設定します|その下のファイルをhttpd_tに。

自動でマシンをセットアップする場合、これはどのように機能するはずですか?

システムを分析し、テストに適切な変更を加える必要があります。次に、自動化ツールを使用して変更をデプロイします。人形とansibleはこれをサポートします。

もちろん、SElinuxをpermissiveに設定すれば、すべて本番環境で実行できます。すべてのメッセージを収集し、それらを分析して変更を決定し、それらを展開します。

SELinuxについて知っておくべきことは他にもたくさんありますが、それが私のスキルの限界です。マイケルハンプトンの方が優れており、マシューイフの方がはるかに優れています。

23
user9517

使用するタイプはhttpd_sys_content_tではありません。これは、Webサーバーがユーザーエージェントに提供するための静的ファイル用です。

プロセス間通信に使用されるソケットの場合、探しているタイプはhttpd_var_run_tです。

ただし、gunicornを制限なく実行したため、通信に追加の問題が発生する可能性があることに注意してください。

2
Michael Hampton

私は以前の答えを成功させずに試しました。私の場合、Unixソケットを使用してuwsgiアプリケーションのフロントエンドとしてnginxサーバーを使用して、それらを通信しています。 Fedoraサーバー26です。

UNIXソケットは/var/local/myappディレクトリに作成されます。

/var/local/myapp/server.sock    
/var/local/myapp/stats.sock

SELinuxを構成するには、コンテキストタイプhttpd_sys_rw_content_tを追加する必要がありました。

semanage fcontext -at httpd_sys_rw_content_t "/var/local/myapp(/.*)?"
restorecon -R -v '/var/local/myapp' 
1
rsc1975