如何在执行模式下使用SELinux运行Flask + Nginx + uWSGI?

时间:2017-07-01 04:05:18

标签: python nginx flask uwsgi wsgi

我正在关注this tutorial在Nginx服务器上运行Flask。我几乎可以使用它,其中当SELinux设置为Permissive时页面加载,但当SELinux处于502 Bad Gateway模式时显示Enforcing

以下是一些相关文件:

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.conf Nginx配置

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文件+ dirs的位置是/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)

/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"

尝试了一些步骤:

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

唯一有效的方法是将SELinux更改为Permissive。我可以进行一些更改/添加,以便SELinux保持Enforcing

编辑: http(s)已被允许firewalld

[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

5 个答案:

答案 0 :(得分:0)

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

semanage port -a -t http_port_t -p tcp 80

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

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

答案 1 :(得分:0)

不确定以下内容是否有效,但是:

  • 套接字需要与httpd_sys_content_rw_t类型相关联,以便与httpd_t关联的进程可以编写它。创建“myproject / runtime”并将类型httpd_sys_content_rw_t与“runtime”关联,以便使用httpd_sys_content_rw_t type

  • 创建套接字
  • 让systemd手动将uwsgi app进程与httpd_sys_script_t类型相关联,以便SELinux定位Web应用程序(不确定是否允许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 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

CONF:

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

答案 2 :(得分: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

答案 3 :(得分:0)

尝试将其添加到您的myproject.ini文件中:

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

答案 4 :(得分:0)

谢谢大家的回答。 我的目标是通过 uWSGI 使用 NGINX 运行 Python Flask 应用程序 SELINUX 启用强制模式。我最初使用的是 Unix 套接字,但是当 SELINUX 被强制执行时,NGINX 无法访问套接字文件。有一种解决方法可以使用命令“semanage permissive -a httpd_t”将 httpd_t 设置为 permissive。但我不想有安全漏洞,所以唯一的选择是使用 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 Conf:

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。