如何在SELinux强制模式下运行Flask+Nginx+uWSGI?

9
我正在遵循这篇教程在Nginx服务器上运行Flask。当SELinux设置为Permissive时,页面几乎可以正常加载,但当SELinux处于Enforcing模式时,则会显示502 Bad Gateway错误。
以下是一些相关文件: myproject.ini
[uwsgi]
module = wsgi

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

myproject.service

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=thisuser
Group=nginx
WorkingDirectory=/home/thisuser/public_html
Environment="PATH=/home/thisuser/thisuser_env/bin"
ExecStart=/home/thisuser/thisuser_env/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

thisuser.com.confNginx配置文件

server {
    listen  80;

    server_name thisuser.com www.thisuser.com;
    access_log /home/thisuser/logs/access.log;
    error_log /home/thisuser/logs/error.log;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/thisuser/public_html/myproject.sock;
        try_files $uri $uri/ =404;
    }

}

Flask文件和目录的位置为/home/thisuser/,其上下文设置如下:
[root@dev ~]# ls -ldZ /home/thisuser/
drwx--x--x. thisuser thisuser unconfined_u:object_r:user_home_dir_t:s0 /home/thisuser/
[root@dev ~]# ls -ldZ /home/thisuser/public_html/
drwxrwxr-x. thisuser thisuser unconfined_u:object_r:httpd_sys_content_t:s0 /home/thisuser/public_html/

以下是错误信息:

/var/log/audit/audit.log


该文件路径指向审计日志文件。
type=AVC msg=audit(1498880449.864:156): avc:  denied  { write } for  pid=2667 comm="nginx" name="myproject.sock" dev="dm-2" ino=67165858 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(1498880449.864:156): arch=c000003e syscall=42 success=no exit=-13 a0=f a1=7f526e12e548 a2=6e a3=7ffdf52991b0 items=0 ppid=2666 pid=2667 auid=4294967295 uid=997 gid=995 euid=997 suid=997 fsuid=997 egid=995 sgid=995 fsgid=995 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)

and

/home/thisuser/logs/error.log

2017/06/30 23:40:49 [crit] 2667#0: *1 connect() to unix:/home/thisuser/public_html/myproject.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.1.15, server: thisuser.com, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/home/thisuser/public_html/myproject.sock:", host: "thisuser.com"

尝试的步骤:

  • 尝试将sock权限更改为chmod-socket = 666
  • 使用setsebool -P httpd_can_network_connect 1
  • user=thisuser更改为user=nginx
  • thisuser添加到nginx组中

唯一有效的方法是将SELinux更改为Permissive。是否有一些更改/添加可以使SELinux保持Enforcing状态?

编辑:已经在firewalld中允许了http(s)

[root@dev ~]# firewall-cmd --permanent --zone=public --add-service=https
[root@dev ~]# firewall-cmd --permanent --zone=public --add-service=http
[root@dev ~]# firewall-cmd --reload

这个回答是否解决了你的问题?Nginx在CentOS 7上无法访问uWSGI unix套接字 - MT0
5个回答

2

不确定以下内容是否可行:

  • 套接字需要与httpd_sys_content_rw_t类型相关联,以便与httpd_t相关的进程可以对其进行写入。创建“myproject/runtime”,并将类型httpd_sys_content_rw_t与“runtime”关联,以便套接字被创建时带有httpd_sys_content_rw_t类型。

  • 手动使systemd将进程与httpd_sys_script_t类型相关联,以便SELinux定位到web应用程序(不确定policy是否允许systemd这样做)。

要点如下:

avc:  denied  { write } for  pid=2667 comm="nginx" name="myproject.sock" dev="dm-2" ino=67165858 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=sock_file

表示与httpd_t相关联的nginx进程未被允许写入myproject.sock套接字文件,因为它与“只读”httpd系统内容类型相关联。它应该与“读写”httpd系统内容类型相关联。ini:
[uwsgi]
module = wsgi

master = true
processes = 5

socket = /home/thisuser/public_html/myproject/runtime/myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

单位:

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=thisuser
Group=nginx
WorkingDirectory=/home/thisuser/public_html/myproject
Environment="PATH=/home/thisuser/thisuser_env/bin"
ExecStart=/home/thisuser/thisuser_env/bin/uwsgi --ini myproject.ini
SELinuxContext=system_u:system_r:httpd_sys_script_t:s0

[Install]
WantedBy=multi-user.target

配置文件:

server {
    listen  80;

    server_name thisuser.com www.thisuser.com;
    access_log /home/thisuser/logs/access.log;
    error_log /home/thisuser/logs/error.log;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/thisuser/public_html/myproject/runtime/myproject.sock;
        try_files $uri $uri/ =404;
    }

}

关联标签:

chcon -t httpd_sys_script_exec_t /home/thisuser/thisuser_env/bin/uwsgi
chcon -Rt httpd_sys_content_rw_t /home/thisuser/public_html/myproject/runtime

0

您需要在semanage上启用端口80,才能通过该端口发送流量。

semanage port -a -t http_port_t -p tcp 80

你可能还需要在firewalld上启用端口:

firewall-cmd --zone=public --permanent --add-port=80/tcp

http服务已在防火墙中启用,http端口上下文已应用于端口80:`[root@dev ~]# semanage port -l | grep http_port_thttp_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000` - rahuL

0

将uwsgi.ini文件修改为以下内容:

[uwsgi]
plugins = python
project = /home/thisuser/public_html/myproject
chdir = %(project)
module = application  # This is the application.py in myproject, you should replace it.
callable = app  # This is the call module name of application.py you run
master = true
process = 5
socket = /home/thisuser/public_html/myproject/runtime/myproject.sock
chmod-socket = 666
vacumm = true
die-on-term = true

0

尝试将以下内容添加到您的myproject.ini文件中:

plugins = python
project = /home/thisuser/public_html/myproject
chdir = %(project)

0

感谢大家的答案。 我的目标是使用SELINUX强制模式通过uWSGI使Python Flask应用程序在NGINX上运行。我最初使用了Unix套接字,但是当SELINUX被强制执行时,NGINX无法访问套接字文件。有一个解决方法是使用命令"semanage permissive -a httpd_t"在宽容模式下设置httpd_t。但我不想留下安全漏洞,所以唯一的选择是使用HTTP作为uwsgi与我的应用程序通信的协议。这是我使用本主题中建议的思路实现的:

myapp.ini 文件

;This is uWSGI config file
[uwsgi]
module = wsgi:app
; Allow the Python processes to spawn threads
; uWSGI disables Python threads by default
enable-threads = true
callable = app  # This is the call module name of application.py you run

master = true
processes = 1

plugins = python3
project = /usr/local/myapp/bin
chdir = %(project)

socket = 127.0.0.1:3031

chmod-socket = 660
chown-socket=bma:nginx
uid = bma
gid = nginx

socket-timeout = 3600
harakiri = 3600

; remove the socket when the process stops
vacuum = true

; uWSGI will kill the process instead of reloading it
die-on-term = true

我的 NGINX 配置文件包含:

location /rest/ {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:3031;
}

启动uWSGI,我使用了这个命令(来自我的.service文件)

/usr/local/bin/uwsgi --socket 127.0.0.1:3031 --ini bma.ini

最后运行以下命令,允许httpd作为中继:
# setsebool -P httpd_can_network_relay 1

这就是我需要做的全部。SELinux已经完全强制执行了。无需将httpd_t设置为宽容模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接