我有nginx通过/run/gunicorn/socket上的unix套接字将请求转发到gunicorn。 默认情况下,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)
在我看来的任何地方(例如, 在这里和这里 ),说明这个说法是向nginx请求,请求被SELinux拒绝,然后运行audit2allow来允许将来的请求。 我找不到任何明确允许这种行为的chcon或semanage命令。
这是唯一的方法吗? 看起来很荒谬,你不能设置一个策略,允许nginx写入到一个套接字,而不是先拒绝一个尝试,然后运行一个允许被拒绝的东西的工具。 你怎么知道什么是启用? 如果你在自动化环境下设置机器,这应该如何工作?
我正在使用CentOS 7。
看起来很荒谬,你不能设置一个策略,允许nginx写入到一个套接字,而不是先拒绝一个尝试,然后运行一个允许被拒绝的东西的工具。
那么不,SELinux是强制性的访问控制,默认情况下被拒绝,你必须明确允许的东西。 如果策略作者没有考虑一个特定的(已知的)堆栈,或者一个守护进程的作者没有把SELinux感知和写入策略,那么你就是自己的。 您必须分析您的服务在做什么以及如何与SELinux进行交互,并提出您自己的策略来允许它。 有工具可以帮助你audit2why , audit2allow等。
这是唯一的方法吗?
不,但这取决于你想要做什么,以及你如何努力做到这一点。 例如,您可能希望将nginx(httpd_t)绑定到端口8010(unreserved_port_t)。 当你启动nginx时失败
Starting nginx: nginx: [emerg] bind() to 0.0.0.0:8010 failed (13: Permission denied)
和你(最终)查看审计日志并find
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的端口types
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 ; ...
其他typeshttp_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 nd不是每个tcp端口如上。
你怎么知道什么是启用?
政策的变化相当容易阅读,通过我们得到的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可以连接到types(其中包括)http_t的unix_stream_sockets。 所以我们可以相应地改变这个背景
semanage fcontext -a -t httpd_t "/run/gunicorn(/.*)?" restorecon -r /run
这设置了/ run / gunicorn和tree |的上下文 下面的文件到httpd_t。
如果你在自动化环境下设置机器,这应该如何工作?
您需要分析系统并对testing进行适当的更改。 然后,您可以使用自动化工具来部署这些更改,傀儡和可靠的支持。
当然,您可以在SElinux设置为宽容的情况下完成所有这些工作。 收集所有的消息,分析他们决定你的变化,并部署他们。
还有很多关于SELinux的知识,但这是我的技能的限制,迈克尔汉普顿更好,马修伊夫又好了,他们可能有更多的补充。
您要使用的types不是httpd_sys_content_t 。 这是用于Web服务器用于用户代理的静态文件。
对于用于进程间通信的套接字,您正在查找的types是httpd_var_run_t 。
不过,请注意,因为你跑的是无人驾驶飞机,可能还会有其他问题与之沟通。
我尝试了以前的答案没有成功,在我的情况下,我使用nginx服务器作为uwsgi应用程序使用unix套接字来沟通他们的前端,我的操作系统这是一个Fedora服务器26。
unix套接字是在目录/var/local/myapp :
/var/local/myapp/server.sock /var/local/myapp/stats.sock
要configurationSELinux,我必须添加上下文types: httpd_sys_rw_content_t
semanage fcontext -at httpd_sys_rw_content_t "/var/local/myapp(/.*)?" restorecon -R -v '/var/local/myapp'