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.
解决方法
It seems ridiculous that you can’t set up a policy that allows Nginx to write to a socket without first having an attempt denied and then running a tool that enables things that were denied.
不,SELinux是强制访问控制,默认情况下拒绝事项,你必须明确允许.如果策略作者没有考虑特定的(法兰克福)堆栈或守护程序的作者没有让它成为SELinux意识和书面政策,那么你就是靠自己.您必须分析您的服务正在做什么以及他们如何与SELinux进行交互,并提出自己的政策以允许它.有工具可以帮助您audit2why,audit2allow等.
… Is this the only way?
不,但这取决于您正在尝试做什么以及您如何尝试解决方案是什么.例如,您可能希望将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将被允许name_bind到端口8010而不是每个tcp端口,如上所述.
How do you know exactly what is being enabled?
对策略的更改相当容易阅读,通过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来修复上下文.
第二个涉及/ 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.
How is this supposed to work if your setting up machines under automation?
您需要分析系统并在测试中进行适当的更改.然后,您使用自动化工具来部署更改,puppet和ansible都支持此更改.
当然,你可以在生产中完成所有这一切,SElinux设置为允许.收集所有消息,分析它们决定您的更改并将它们部署.
还有更多关于SELinux的知识,但这是我技能的极限,迈克尔汉普顿更好,Mathew Ife再好一点,他们可能还有更多要补充.