HỌC BẰNG THỰC HÀNH
← Lộ trình học
01 · Linux Administration

SELinux: context, port và boolean

Thực hiện trên server của bạn, rồi kiểm tra từng tiêu chí.

Mở rộng · tùy chọn

Vì sao cần học

Khi gặp lỗi do SELinux, nhiều người chọn cách tắt nó, và bỏ đi một lớp bảo vệ quan trọng: dù kẻ tấn công chiếm được tiến trình web, SELinux vẫn chặn nó đọc file của dịch vụ khác. Cách làm đúng là đọc audit log, hiểu policy muốn gì và cấp đúng nhãn. RHCSA chấm bài trên máy SELinux enforcing.

Mục tiêu

  • Giải thích SELinux type enforcement: tiến trình có domain, file và port có type.
  • Đọc context bằng ls -Z, ps -Z, và tìm lỗi bằng ausearch.
  • Gán port bằng semanage port, gán file context bền vững bằng semanage fcontext + restorecon.
  • Tra và bật boolean bằng getsebool/setsebool -P.

Điều kiện tiên quyết

  • Bài Firewall với firewalld.
  • getenforce trả Enforcing.

Mental model

Quyền Unix (owner, group, mode) được kiểm tra trước. Sau đó SELinux kiểm tra thêm: domain của tiến trình có được làm việc này với type của đối tượng không?

httpd (domain httpd_t) ──đọc──▶ /srv/kdc-www/index.html (type ?)
httpd (domain httpd_t) ──bind──▶ tcp/8088 (type ?)
  • File trong /var/www/html có type httpd_sys_content_t: httpd đọc được.
  • File mới trong /srv nhận type var_t: httpd không đọc được, dù quyền Unix cho phép.
  • Port 8088 chưa có type web: httpd không bind được. Port 80, 443, 8443 thuộc http_port_t.

chcon đổi nhãn ngay nhưng mất khi relabel toàn hệ thống. semanage fcontext ghi quy tắc vào policy; restorecon áp quy tắc đó. Luôn dùng cách thứ hai.

Thực hành (Guided Lab)

1. Kiểm tra trạng thái

getenforce
sestatus
grep ^SELINUX= /etc/selinux/config
ps -eZ | grep -E 'sshd|systemd' | head -3
ls -Zd /var/www /srv
Giải thích lệnh và tham số

getenforce in mode SELinux hiện tại; sestatus in thông tin chi tiết. ps -eZ gộp xem mọi tiến trình (-e) và context SELinux (-Z); ls -Zd xem context (-Z) của chính thư mục (-d). grep ^SELINUX= lọc dòng cấu hình mode khi boot. setenforce 1 chuyển runtime sang Enforcing; không tự sửa /etc/selinux/config.

Nếu getenforce trả Permissive, chạy sudo setenforce 1 và sửa /etc/selinux/config thành SELINUX=enforcing.

2. Dựng site trên port và thư mục không mặc định

sudo dnf install -y httpd policycoreutils-python-utils
sudo install -d /srv/kdc-www
echo '<h1>KDC-SELINUX</h1>' | sudo tee /srv/kdc-www/index.html
sudo tee /etc/httpd/conf.d/kdc-www.conf <<'EOF'
Listen 8088
<VirtualHost *:8088>
    DocumentRoot /srv/kdc-www
    <Directory /srv/kdc-www>
        Require all granted
    </Directory>
</VirtualHost>
EOF
sudo apachectl configtest
sudo systemctl enable --now httpd
Giải thích lệnh và tham số

apachectl configtest kiểm tra cú pháp cấu hình Apache trước khi bật service. Các dòng Listen, VirtualHost, DocumentRoot là cấu hình trong file, không phải lệnh shell. Nếu service không chạy, đọc trạng thái/log để phân biệt lỗi cú pháp với SELinux từ chối bind port.

Lệnh cuối thất bại. Thu thập evidence:

systemctl status httpd --no-pager | tail -5
sudo ausearch -m AVC -ts recent | tail -5
Giải thích lệnh và tham số

ausearch tìm bản ghi audit: -m AVC chọn loại thông điệp SELinux Access Vector Cache, -ts recent chọn thời điểm bắt đầu gần đây. tail -5 giới hạn số dòng hiển thị, không thay phạm vi truy vấn của ausearch.

Audit log ghi denied { name_bind } cho httpd_t trên port 8088: SELinux chặn, không phải lỗi cấu hình Apache.

3. Gán type cho port

sudo semanage port -a -t http_port_t -p tcp 8088
sudo semanage port -l | grep ^http_port_t
sudo systemctl restart httpd
curl -s http://127.0.0.1:8088/ | head -3
Giải thích lệnh và tham số

semanage port quản lý mapping port ↔ SELinux type: -a thêm, -t http_port_t chọn type, -p tcp chọn giao thức, 8088 là port. -l liệt kê mapping. Nếu port đã có mapping phù hợp để chỉnh, -m là sửa thay cho -a thêm. Các thay đổi này lưu trong policy local, khác mở port trong firewall.

httpd đã chạy, nhưng trả trang lỗi 403 Forbidden. Đọc evidence lần nữa:

ls -Z /srv/kdc-www/index.html
sudo ausearch -m AVC -ts recent | tail -3
Giải thích lệnh và tham số

ls -Z in SELinux context của file. ausearch -m AVC -ts recent lọc audit theo loại AVC (-m) và thời điểm bắt đầu gần đây (-ts). tail -3 chỉ lấy ba dòng cuối.

4. Gán file context bền vững

sudo semanage fcontext -a -t httpd_sys_content_t '/srv/kdc-www(/.*)?'
sudo restorecon -Rv /srv/kdc-www
ls -Z /srv/kdc-www/index.html
curl -s http://127.0.0.1:8088/
Giải thích lệnh và tham số

semanage fcontext -a -t httpd_sys_content_t '<mẫu>' khai báo type mặc định cho đường dẫn khớp regex. Mẫu /srv/kdc-www(/.*)? gồm thư mục và mọi đường dẫn con; nháy đơn giữ mẫu nguyên vẹn. restorecon -Rv áp mapping lên file thật (-R đệ quy, -v in thay đổi). ls -Z xác nhận type thực tế sau khi áp dụng.

5. Boolean (tham khảo, không chấm)

Boolean bật/tắt các nhóm quyền có sẵn trong policy:

getsebool -a | grep httpd_can_network_connect
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_connect off
Giải thích lệnh và tham số

getsebool -a liệt kê mọi boolean SELinux; setsebool -P <tên> on/off đổi boolean và lưu bền vững nhờ -P. Đây là P hoa, khác -p tcp của semanage. Thử bật rồi tắt theo bài để không giữ quyền kết nối mạng rộng hơn cần thiết.

-P lưu bền vững. Boolean này cần khi Apache làm reverse proxy tới một backend (Module 04).

Tự kiểm tra (Verification)

getenforce
sudo semanage port -l | grep 8088
sudo semanage fcontext -l -C
ls -Z /srv/kdc-www/index.html
curl -s http://127.0.0.1:8088/
Giải thích lệnh và tham số

semanage fcontext -l -C liệt kê (-l) chỉ các tùy chỉnh local (-C). -d trong semanage port/fcontext ở phần dọn dẹp xóa mapping local; không có nghĩa xem thư mục như ls -d.

semanage fcontext -l -C chỉ liệt kê các quy tắc bạn thêm. Chọn server và bấm Kiểm tra kết quả.

Lỗi thường gặp

  • setenforce 0 "để thử": lỗi biến mất nên bạn không học được gì, và máy mất lớp bảo vệ. Nếu cần chẩn đoán, đặt riêng một domain sang permissive (semanage permissive -a httpd_t) rồi bỏ đi ngay.
  • mv file từ thư mục home vào /srv/kdc-www: file giữ nhãn cũ. cp thì nhận nhãn của thư mục đích. Sau mv, chạy restorecon.
  • Dùng chcon: đúng tới lần relabel tiếp theo.
  • semanage port -a báo đã tồn tại: port thuộc type khác, dùng -m để sửa.

Ghi chú production

  • Nhiều sự cố "permission denied" trên RHEL là SELinux. Hãy kiểm tra audit log trước khi đổi quyền file.
  • setroubleshoot-server cài thêm lệnh sealert, giải thích AVC bằng ngôn ngữ dễ đọc và gợi ý lệnh sửa. Đọc kỹ trước khi làm theo.
  • Container trên RHEL cũng được SELinux bảo vệ; Module 05 sẽ gặp tùy chọn :Z khi mount volume.

Ghi chú Ubuntu

Ubuntu dùng AppArmor, không có SELinux; bài này chỉ làm được trên RHEL-family.

Dọn dẹp

sudo systemctl disable --now httpd
sudo rm -f /etc/httpd/conf.d/kdc-www.conf
sudo semanage port -d -t http_port_t -p tcp 8088
sudo semanage fcontext -d '/srv/kdc-www(/.*)?'
sudo rm -rf /srv/kdc-www
Giải thích lệnh và tham số

systemctl disable --now bỏ cấu hình tự chạy khi boot và dừng service ngay. daemon-reload yêu cầu systemd đọc lại unit file sau khi sửa/xóa. rm -f xóa file và không hỏi xác nhận; -r thêm xóa đệ quy thư mục cùng nội dung, nên -rf gộp hai tùy chọn này. semanage port -d xóa mapping port; -t http_port_t chọn type và -p tcp chọn giao thức. semanage fcontext -d xóa quy tắc đường dẫn local được chỉ định.

Tài liệu chính thức