Làm cách nào tôi có thể yêu cầu SELinux cho phép nginx truy cập vào ổ cắm unix mà không cần aud2allow?


9

Tôi có yêu cầu chuyển tiếp nginx đến gunicorn thông qua một ổ cắm unix tại /run/gunicorn/socket. Theo mặc định, hành vi này không được cho phép bởi 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)

Ở mọi nơi tôi nhìn (ví dụ, ở đâyở đây ), các hướng dẫn để kích hoạt tính năng nói này để đưa ra yêu cầu cho nginx, yêu cầu bị từ chối bởi SELinux, sau đó chạy audit2allowđể cho phép các yêu cầu trong tương lai. Tôi không thể tìm ra bất kỳ chconhoặc semanagelệnh nào cho phép hành vi này rõ ràng.

đây có phải cách duy nhất không? Có vẻ nực cười khi bạn không thể thiết lập một chính sách cho phép nginx ghi vào ổ cắm mà không cần phải từ chối trước và sau đó chạy một công cụ cho phép những thứ bị từ chối. Làm thế nào để bạn biết chính xác những gì đang được kích hoạt? Làm thế nào điều này được cho là hoạt động nếu thiết lập máy của bạn theo tự động hóa?

Tôi đang sử dụng CentOS 7.


Bạn cần cho chúng tôi xem các tin nhắn bị từ chối AVC và thật tốt khi biết bạn đang chạy hệ điều hành và phiên bản nào.
dùng9517

@lain điểm tốt.
DRS

Câu trả lời:


23

Có vẻ nực cười khi bạn không thể thiết lập một chính sách cho phép nginx ghi vào ổ cắm mà không cần phải từ chối trước và sau đó chạy một công cụ cho phép những thứ bị từ chối.

À không, SELinux là Kiểm soát truy cập bắt buộc, mọi thứ bị từ chối theo mặc định và bạn phải cho phép rõ ràng một cái gì đó. Nếu các tác giả chính sách chưa xem xét một ngăn xếp (franken) cụ thể hoặc các tác giả của daemon đã không làm cho nó tự nhận biết và chính sách bằng văn bản cho nó thì bạn sẽ tự mình thực hiện. Bạn phải phân tích những gì dịch vụ của bạn đang làm và cách chúng tương tác với SELinux và đưa ra chính sách của riêng bạn để cho phép nó. Có các công cụ có sẵn để giúp bạn aud2why , aud2allow , v.v.

... Đây có phải cách duy nhất không?

Không, nhưng nó phụ thuộc vào những gì bạn đang cố gắng làm và cách bạn đang cố gắng làm điều đó như giải pháp là gì. Ví dụ: bạn có thể muốn liên kết nginx (httpd_t) với cổng 8010 (unreserved_port_t). Khi bạn bắt đầu nginx, nó thất bại

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

và bạn (cuối cùng) nhìn vào nhật ký kiểm toán và tìm

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

Bạn có thể chạy nó thông qua aud2alllow và ngây thơ chấp nhận kết quả của nó

allow httpd_t port_t:tcp_socket name_bind;

sau đó cho phép httpd_t kết nối với bất kỳ cổng tcp nào. Đây có thể không phải là những gì bạn muốn.

Bạn có thể sử dụng Sesearch để điều tra chính sách và xem loại cổng nào httpd_t có thể đặt tên_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 ;
...

Trong số các loại khác, http_t có thể liên kết với http_port_t. Bây giờ bạn có thể sử dụng semanage để đào sâu hơn một chút.

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

Cổng 8010 không được liệt kê. Vì chúng tôi muốn nginx liên kết với cổng 8010, việc thêm nó vào danh sách http_port_t không phải là không hợp lý

semanage port -a -t http_port_t -p tcp 8010

Bây giờ nginx sẽ được phép đặt tên_bind cho cổng 8010 chứ không phải mọi cổng tcp như trên.

Làm thế nào để bạn biết chính xác những gì đang được kích hoạt?

Thay đổi chính sách khá dễ đọc, chạy các tin nhắn của bạn ở trên thông qua aud2allow chúng tôi nhận được

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

mà có vẻ khá tự giải thích.

Đầu tiên trong số đó đề cập đến tệp có inum 76151. Bạn có thể sử dụng find để lấy tên của nó (find / -inum 76151) và sau đó sử dụng semanage fcontext -a -t ...để thay đổi chính sách và phục hồi để sửa lỗi ngữ cảnh.

Thứ hai liên quan đến /run/gunicorn/socketmột lần nữa có bối cảnh sai. Sử dụng Sesearch chúng ta có thể thấy rằng http_t có thể kết nối với unix_stream_sockets loại (trong số những người khác) http_t. Vì vậy, chúng ta có thể thay đổi bối cảnh cho phù hợp chẳng hạn

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

Điều này đặt bối cảnh của / run / gunicorn và cây | các tập tin bên dưới để httpd_t.

Làm thế nào điều này được cho là hoạt động nếu thiết lập máy của bạn theo tự động hóa?

Bạn cần phân tích hệ thống và thực hiện các thay đổi phù hợp trong thử nghiệm. Sau đó, bạn sử dụng các công cụ tự động hóa của mình để triển khai các thay đổi, con rối và ansible có hỗ trợ cho việc này.

Tất nhiên bạn có thể làm tất cả trong sản xuất với SElinux được đặt thành cho phép. Thu thập tất cả các tin nhắn, phân tích chúng quyết định thay đổi của bạn và triển khai chúng.

Có nhiều điều hơn để biết về SELinux nhưng đó là giới hạn về kỹ năng của tôi, Michael Hampton tốt hơn và Mathew Ife tốt hơn một lần nữa, họ có thể có nhiều thứ để thêm.


1
Lời khuyên của bạn rất thấu đáo và giúp tôi tiến gần hơn đến việc tự mình giải quyết những vấn đề này, mặc dù vậy vẫn khiến tôi hơi hụt hẫng. allow httpd_t httpd_sys_content_t:sock_file write;không phải là tự giải thích cho tôi như bạn hy vọng. Những gì được này nói chính sách mà nhu cầu tập tin phải được thay đổi để (ví dụ, những gì diễn ra sau -ttrong semanagelệnh?
DRS

Ngoài ra, tôi nhận được hướng dẫn sử dụng khi sử dụng semanagelệnh của bạn trực tiếp. Tôi cần thêm một --addđối số.
drs

Trên thực tế, tôi cũng nên nói rằng sau khi thay đổi loại tệp ổ cắm thành httpd_var_run_tnhư Michael Hampton đã lưu ý bên dưới, audit2allowthông báo là:allow httpd_t var_run_t:sock_file write;
drs

Có vẻ như bạn đặt nó thành var_run_tkhông httpd_var_run_t.
dùng9517

@lain, hmm .. không có xúc xắc. Bây giờ audit2allownóiallow httpd_t var_run_t:sock_file write;
drs

2

Loại bạn muốn sử dụng là không httpd_sys_content_t. Điều này là cho các tệp tĩnh mà máy chủ web có nghĩa là để phục vụ cho các tác nhân người dùng.

Đối với một ổ cắm được sử dụng để liên lạc giữa các quá trình, loại bạn đang tìm kiếm là httpd_var_run_t.

Mặc dù vậy, xin lưu ý rằng vì bạn đã chạy gunicorn không được kiểm soát, có thể có thêm các vấn đề giao tiếp với nó.


3
Cảm ơn! Có vẻ như điều này đã giải quyết một trong những vấn đề của SELinux. Bất kỳ con trỏ về cách thiết lập gunicorn (hoặc bất kỳ dịch vụ nào khác) bị giới hạn?
drs

1

Tôi đã thử các câu trả lời trước nhưng không thành công, trong trường hợp của tôi, tôi đang sử dụng máy chủ nginx làm giao diện cho ứng dụng uwsgi sử dụng ổ cắm unix để liên lạc với họ, hệ điều hành của tôi Đó là máy chủ Fedora 26.

Các ổ cắm unix được tạo trong thư mục /var/local/myapp:

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

Để cấu hình SELinux, tôi phải thêm kiểu ngữ cảnh: httpd_sys_rw_content_t

semanage fcontext -at httpd_sys_rw_content_t "/var/local/myapp(/.*)?"
restorecon -R -v '/var/local/myapp' 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.