Εισαγωγή: Γιατί ο Υποχρεωτικός Έλεγχος Πρόσβασης Δεν Είναι Προαιρετικός
Ας πούμε τα πράγματα με το όνομά τους: αν τρέχετε Linux servers το 2026 χωρίς ενεργοποιημένο SELinux ή AppArmor, αφήνετε ένα τεράστιο κενό στην ασφάλειά σας. Και δεν υπερβάλλω. Τα παραδοσιακά δικαιώματα Unix (owner, group, other) — γνωστά και ως Discretionary Access Control (DAC) — σχεδιάστηκαν σε μια εποχή που οι απειλές ήταν εντελώς διαφορετικές. Σήμερα; Ένα μοναδικό ευπαθές process που τρέχει ως root μπορεί να θέσει σε κίνδυνο ολόκληρο το σύστημα.
Εδώ μπαίνει στο παιχνίδι ο Υποχρεωτικός Έλεγχος Πρόσβασης (Mandatory Access Control — MAC). Σε αντίθεση με το DAC, όπου ο ιδιοκτήτης ενός αρχείου αποφασίζει ποιος έχει πρόσβαση, στο MAC οι πολιτικές ασφαλείας ορίζονται κεντρικά από τον διαχειριστή και κανένα process — ούτε καν το root — δεν μπορεί να τις παρακάμψει. Αυτό πρακτικά σημαίνει ότι ακόμα κι αν ένας εισβολέας αποκτήσει root access, τα MAC labels και οι πολιτικές θα περιορίσουν σημαντικά τις κινήσεις του.
Τα δύο κυρίαρχα MAC frameworks στο Linux είναι το SELinux (Security-Enhanced Linux) και το AppArmor. Και τα δύο υλοποιούνται μέσω του Linux Security Modules (LSM) framework, αλλά ακολουθούν ριζικά διαφορετικές φιλοσοφίες. Σε αυτόν τον οδηγό θα τα εξετάσουμε και τα δύο σε βάθος — αρχιτεκτονική, πρακτική ρύθμιση, custom πολιτικές, hardening τεχνικές, και πώς να αποφασίσετε ποιο ταιριάζει στο δικό σας περιβάλλον.
SELinux: Η Θωράκιση Επιπέδου Στρατιωτικής Ασφάλειας
Ιστορία και Φιλοσοφία
Το SELinux αναπτύχθηκε αρχικά από την NSA (National Security Agency) των ΗΠΑ και ενσωματώθηκε στον Linux kernel από την έκδοση 2.6. Η φιλοσοφία του είναι απλή αλλά αυστηρή: deny by default. Δηλαδή, τα πάντα απαγορεύονται εκτός αν υπάρχει ρητή πολιτική που τα επιτρέπει. Αυτή η προσέγγιση, αν και πιο πολύπλοκη στη διαχείριση, παρέχει ασυναγώνιστο επίπεδο ελέγχου.
Ένα σημαντικό update για 2025-2026: η openSUSE αποφάσισε να αντικαταστήσει το AppArmor με SELinux ως προεπιλογή στο Tumbleweed. Από τις 11 Φεβρουαρίου 2025, κάθε νέα εγκατάσταση Tumbleweed χρησιμοποιεί SELinux σε enforcing mode. Η ίδια αλλαγή ισχύει και για το SUSE Linux Enterprise / openSUSE Leap 16. Ειλικρινά, αυτή η στρατηγική μετάβαση δείχνει μια ξεκάθαρη τάση: η βιομηχανία κατευθύνεται σταθερά προς το SELinux για κρίσιμα περιβάλλοντα.
Βασικές Έννοιες: Contexts, Labels και Policies
Το θεμέλιο του SELinux είναι η ετικετοποίηση (labeling). Κάθε αντικείμενο στο σύστημα — αρχεία, processes, ports, sockets — φέρει ένα SELinux context (ετικέτα ασφαλείας) που αποτελείται από τέσσερα πεδία:
# Μορφή: user:role:type:level
# Παράδειγμα:
system_u:system_r:httpd_t:s0
- User (
system_u): Ο SELinux χρήστης (διαφορετικός από τον Linux χρήστη) - Role (
system_r): Ο ρόλος που καθορίζει ποιοι τύποι μπορούν να εκτελεστούν - Type (
httpd_t): Ο τύπος — και είναι το πιο κρίσιμο πεδίο για τον έλεγχο πρόσβασης - Level (
s0): Το επίπεδο ασφαλείας (χρησιμοποιείται στο MLS/MCS)
Η βασική μηχανή ελέγχου λέγεται Type Enforcement (TE): οι κανόνες πολιτικής ορίζουν ποιοι τύποι processes μπορούν να αλληλεπιδράσουν με ποιους τύπους αντικειμένων. Για παράδειγμα, ένα process τύπου httpd_t μπορεί να διαβάσει αρχεία τύπου httpd_content_t, αλλά δεν μπορεί να αγγίξει αρχεία τύπου shadow_t (δηλαδή το /etc/shadow).
Λειτουργίες SELinux: Enforcing, Permissive, Disabled
Το SELinux λειτουργεί σε τρεις καταστάσεις. Ας τις δούμε μαζί με τις εντολές διαχείρισης:
# Έλεγχος τρέχουσας κατάστασης
getenforce
# Αποτέλεσμα: Enforcing | Permissive | Disabled
# Εναλλαγή σε Permissive (προσωρινά)
sudo setenforce 0
# Εναλλαγή σε Enforcing (προσωρινά)
sudo setenforce 1
# Μόνιμη ρύθμιση — /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
- Enforcing: Η πολιτική εφαρμόζεται ενεργά — οι παραβιάσεις μπλοκάρονται και καταγράφονται
- Permissive: Οι παραβιάσεις καταγράφονται αλλά δεν μπλοκάρονται — ιδανικό για debugging
- Disabled: Πλήρης απενεργοποίηση — ΜΗΝ το χρησιμοποιείτε σε production, σοβαρά
Σημαντική σημείωση: η μετάβαση από Disabled σε Enforcing απαιτεί relabeling ολόκληρου του filesystem. Ανάλογα με το μέγεθος του δίσκου, αυτό μπορεί να πάρει αρκετή ώρα (έχω δει περιπτώσεις που χρειάστηκε πάνω από μισή ώρα σε μεγάλα servers):
# Δημιουργία αρχείου για αυτόματο relabeling κατά τον επόμενο restart
sudo touch /.autorelabel
sudo reboot
Βασικές Εντολές Διαχείρισης SELinux
Πριν προχωρήσουμε σε hardening, ας δούμε τις βασικές εντολές που θα χρειάζεστε καθημερινά:
# Εμφάνιση SELinux context αρχείων
ls -Z /var/www/html/
# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
# Εμφάνιση SELinux context process
ps auxZ | grep httpd
# system_u:system_r:httpd_t:s0 root 1234 ... /usr/sbin/httpd
# Αλλαγή context αρχείου
sudo chcon -t httpd_sys_content_t /var/www/html/newfile.html
# Μόνιμη αλλαγή context (επιβιώνει restorecon)
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebapp(/.*)?"
sudo restorecon -Rv /srv/mywebapp
# Έλεγχος SELinux Booleans
getsebool -a | grep httpd
# httpd_can_network_connect --> off
# httpd_can_sendmail --> off
# Ενεργοποίηση Boolean (μόνιμα)
sudo setsebool -P httpd_can_network_connect on
# Διαχείριση SELinux ports
sudo semanage port -l | grep http
# http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
sudo semanage port -a -t http_port_t -p tcp 8080
Δημιουργία Custom SELinux Policy Modules
Ανάλυση AVC Denials με audit2why
Όταν το SELinux μπλοκάρει κάποια ενέργεια, δημιουργεί ένα AVC (Access Vector Cache) denial στο audit log. Η δημιουργία custom πολιτικών ξεκινάει πάντα — και τονίζω πάντα — με την ανάλυση αυτών των denials:
# Εμφάνιση πρόσφατων AVC denials
sudo ausearch -m AVC -ts recent
# Ανάλυση γιατί συνέβη η απόρριψη
sudo ausearch -m AVC -ts recent | audit2why
# Παράδειγμα εξόδου:
# type=AVC msg=audit(1708345678.123:456): avc: denied { read } for
# pid=1234 comm="myapp" name="config.yml" dev="sda1" ino=789012
# scontext=system_u:system_r:myapp_t:s0
# tcontext=system_u:object_r:etc_t:s0 tclass=file
#
# Was caused by:
# Missing type enforcement (TE) allow rule.
Δημιουργία Module με audit2allow
Αφού κατανοήσουμε τις απορρίψεις, χρησιμοποιούμε το audit2allow για να φτιάξουμε custom policy module. Η διαδικασία είναι αρκετά straightforward:
# Βήμα 1: Εγκατάσταση απαραίτητων εργαλείων
# RHEL/CentOS/Fedora:
sudo dnf install policycoreutils-devel setools-console
# Βήμα 2: Εξαγωγή AVC denials για τη συγκεκριμένη εφαρμογή
sudo ausearch -m AVC -c myapp -ts today > /tmp/myapp_avcs.log
# Βήμα 3: Δημιουργία TE module
sudo audit2allow -i /tmp/myapp_avcs.log -M myapp_custom
# Αυτό δημιουργεί δύο αρχεία:
# myapp_custom.te - ο πηγαίος κώδικας πολιτικής
# myapp_custom.pp - το compiled module
# Βήμα 4: Επιθεώρηση του .te ΠΡΙΝ φορτωθεί
cat myapp_custom.te
# module myapp_custom 1.0;
#
# require {
# type myapp_t;
# type etc_t;
# class file { read open getattr };
# }
#
# allow myapp_t etc_t:file { read open getattr };
# Βήμα 5: Εγκατάσταση του module
sudo semodule -i myapp_custom.pp
# Βήμα 6: Επαλήθευση
sudo semodule -l | grep myapp_custom
Μια κρίσιμη προειδοποίηση εδώ: ποτέ μην εφαρμόζετε τυφλά τα rules που δημιουργεί το audit2allow. Κάντε πάντα review στο .te αρχείο πρώτα. Ένα allow rule που είναι πολύ ευρύ μπορεί κυριολεκτικά να ανοίξει τρύπες στην ασφάλεια. Σε κρίσιμα συστήματα, χρησιμοποιήστε audit2allow -R για rules βασισμένα σε reference policies — είναι πολύ πιο ασφαλή.
Χειροκίνητη Δημιουργία SELinux Policy
Για εφαρμογές που χρειάζονται ακριβή πολιτική, η χειροκίνητη δημιουργία είναι ξεκάθαρα η καλύτερη προσέγγιση. Ναι, είναι πιο χρονοβόρα, αλλά αξίζει τον κόπο:
# Δομή αρχείου .te για custom service
policy_module(mywebservice, 1.0)
########################################
# Declarations
########################################
# Δήλωση νέου τύπου για το process
type mywebservice_t;
type mywebservice_exec_t;
init_daemon_domain(mywebservice_t, mywebservice_exec_t)
# Δήλωση τύπων για αρχεία
type mywebservice_var_run_t;
files_pid_file(mywebservice_var_run_t)
type mywebservice_log_t;
logging_log_file(mywebservice_log_t)
type mywebservice_conf_t;
files_config_file(mywebservice_conf_t)
########################################
# Policy rules
########################################
# Ανάγνωση configuration
allow mywebservice_t mywebservice_conf_t:file read_file_perms;
allow mywebservice_t mywebservice_conf_t:dir list_dir_perms;
# Εγγραφή logs
allow mywebservice_t mywebservice_log_t:file manage_file_perms;
logging_log_filetrans(mywebservice_t, mywebservice_log_t, file)
# Εγγραφή PID file
allow mywebservice_t mywebservice_var_run_t:file manage_file_perms;
files_pid_filetrans(mywebservice_t, mywebservice_var_run_t, file)
# Network access
corenet_tcp_bind_generic_port(mywebservice_t)
corenet_tcp_connect_http_port(mywebservice_t)
# Σύνδεση DNS
sysnet_dns_name_resolve(mywebservice_t)
# Μεταγλώττιση και εγκατάσταση χειροκίνητα
sudo checkmodule -M -m -o mywebservice.mod mywebservice.te
sudo semodule_package -o mywebservice.pp -m mywebservice.mod
sudo semodule -i mywebservice.pp
SELinux Hardening για Production Servers
Θωράκιση Booleans
Τα SELinux Booleans είναι, κατά τη γνώμη μου, ο πιο εύκολος τρόπος για να σφίξετε τις πολιτικές χωρίς να γράψετε custom modules. Σκεφτείτε τα σαν διακόπτες on/off για συγκεκριμένες δυνατότητες. Ακολουθεί ένα hardening checklist για τυπικούς web servers:
# === Web Server (Apache/Nginx) Hardening ===
# Αποτροπή σύνδεσης σε εξωτερικά δίκτυα (εκτός αν χρειάζεται proxy)
sudo setsebool -P httpd_can_network_connect off
# Αποτροπή αποστολής email
sudo setsebool -P httpd_can_sendmail off
# Αποτροπή εκτέλεσης CGI scripts
sudo setsebool -P httpd_enable_cgi off
# Αποτροπή πρόσβασης σε home directories
sudo setsebool -P httpd_enable_homedirs off
# === SSH Hardening ===
# Αποτροπή χρήσης SSH agent forwarding
sudo setsebool -P ssh_sysadm_login off
# === Γενικές Ρυθμίσεις ===
# Αποτροπή εκτέλεσης κώδικα από stack/heap (protection against exploits)
sudo setsebool -P deny_execmem on
sudo setsebool -P deny_ptrace on
# Αποτροπή χρήσης unconfined domains
sudo setsebool -P unconfined_login off
# Εμφάνιση ΟΛΩΝ των Booleans με τις τρέχουσες τιμές
sudo semanage boolean -l | sort
Multi-Category Security (MCS) για Container Isolation
Ένα από τα πιο δυνατά χαρακτηριστικά του SELinux είναι το Multi-Category Security (MCS), που χρησιμοποιείται εκτενώς στην απομόνωση containers. Η ιδέα είναι απλή: κάθε container λαμβάνει ένα μοναδικό ζεύγος κατηγοριών (π.χ. c123,c456), κι αυτό εγγυάται ότι ένα compromised container δεν μπορεί να δει τα δεδομένα άλλων containers.
# Εμφάνιση SELinux labels σε containers (Podman)
podman ps --format "{{.ID}} {{.Names}} {{.MountLabel}}"
# a1b2c3d4 webapp system_u:object_r:container_file_t:s0:c512,c768
# e5f6g7h8 redis system_u:object_r:container_file_t:s0:c234,c890
# Κάθε container παίρνει αυτόματα μοναδικά MCS labels
# Αυτό σημαίνει ότι ακόμα κι αν ένα container κάνει escape,
# δεν μπορεί να διαβάσει volumes άλλων containers
# Χειροκίνητος ορισμός label για container
podman run --security-opt label=level:s0:c100,c200 --name secure-app my-image
# Εκτέλεση container χωρίς SELinux (ΜΗ ΣΥΝΙΣΤΑΤΑΙ)
podman run --security-opt label=disable my-image
Udica: Αυτόματη Δημιουργία SELinux Policies για Containers
Το Udica είναι ένα εργαλείο που λύνει ένα πολύ πρακτικό πρόβλημα: αναλύει τα containers σας και δημιουργεί αυτόματα εξατομικευμένες SELinux πολιτικές. Αν δουλεύετε πολύ με containers, αξίζει σίγουρα να το γνωρίσετε:
# Εγκατάσταση udica
sudo dnf install udica
# Βήμα 1: Εξαγωγή container inspect
podman inspect my-webapp > container_inspect.json
# Βήμα 2: Δημιουργία custom SELinux policy
udica -j container_inspect.json my_webapp_policy
# Βήμα 3: Φόρτωση πολιτικής
sudo semodule -i my_webapp_policy.cil /usr/share/udica/templates/{base_container.cil,net_container.cil}
# Βήμα 4: Εκτέλεση container με custom policy
podman run --security-opt label=type:my_webapp_policy.process --name secure-webapp my-image
AppArmor: Ευελιξία και Απλότητα στον Έλεγχο Πρόσβασης
Αρχιτεκτονική και Φιλοσοφία
Το AppArmor ακολουθεί μια εντελώς διαφορετική φιλοσοφία. Αντί για labels, χρησιμοποιεί path-based access control: οι πολιτικές ορίζουν σε ποια μονοπάτια (paths) έχει πρόσβαση ένα πρόγραμμα. Αυτό κάνει το AppArmor σημαντικά ευκολότερο στην εκμάθηση, ιδιαίτερα αν δεν έχετε εμπειρία με MAC συστήματα.
Το AppArmor είναι η προεπιλογή σε Ubuntu, Debian και τα παράγωγά τους. Με το AppArmor 4.0, το project εισάγει σημαντικές αλλαγές στη σύνταξη πολιτικών (που δεν είναι backwards-compatible, αξίζει να σημειωθεί), δημιουργώντας μια γέφυρα προς τη νέα γενιά AppArmor 4.x. Η έκδοση 4.0.2 κυκλοφόρησε ως bug fix release, ενώ η επερχόμενη 4.1 θα είναι η πρώτη πλήρως λειτουργική έκδοση της νέας σειράς.
Βασικές Εντολές AppArmor
# Έλεγχος κατάστασης AppArmor
sudo aa-status
# apparmor module is loaded.
# 47 profiles are loaded.
# 42 profiles are in enforce mode.
# 5 profiles are in complain mode.
# Εναλλαγή profile σε complain mode (logging only)
sudo aa-complain /usr/sbin/nginx
# Εναλλαγή σε enforce mode
sudo aa-enforce /usr/sbin/nginx
# Φόρτωση νέου profile
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
# Απενεργοποίηση συγκεκριμένου profile
sudo aa-disable /etc/apparmor.d/usr.sbin.nginx
# Εμφάνιση logs — AppArmor denials
sudo dmesg | grep "apparmor.*DENIED"
# ή
sudo journalctl -k | grep "apparmor.*DENIED"
Δομή ενός AppArmor Profile
Τα AppArmor profiles είναι αρχεία κειμένου στον φάκελο /etc/apparmor.d/. Η δομή τους — κι αυτό είναι κάτι που μου αρέσει πολύ — είναι αρκετά διαισθητική ακόμα κι αν τα βλέπετε πρώτη φορά:
# /etc/apparmor.d/usr.local.bin.myapp
#include <tunables/global>
/usr/local/bin/myapp {
# Βασικές βιβλιοθήκες
#include <abstractions/base>
#include <abstractions/nameservice>
# Network permissions
network inet tcp,
network inet udp,
# Εκτελέσιμο — αυτο-ανάγνωση
/usr/local/bin/myapp mr,
# Configuration — μόνο ανάγνωση
/etc/myapp/ r,
/etc/myapp/** r,
# Data directory — ανάγνωση και εγγραφή
/var/lib/myapp/ rw,
/var/lib/myapp/** rwk,
# Logs — εγγραφή μόνο
/var/log/myapp/ rw,
/var/log/myapp/** w,
# Temporary files
/tmp/myapp-* rw,
# PID file
/run/myapp.pid rw,
# Deny access — ρητή αποτροπή
deny /etc/shadow r,
deny /etc/passwd w,
deny /home/** rwx,
# Capabilities
capability net_bind_service,
capability setuid,
capability setgid,
}
Τα δικαιώματα στο AppArmor είναι εύκολα κατανοητά: r (read), w (write), x (execute), m (mmap), k (lock), l (link). Η χρήση deny rules επιτρέπει ρητή απαγόρευση που δεν μπορεί να παρακαμφθεί ούτε από allow rules — κάτι πολύ χρήσιμο για defense-in-depth σενάρια.
Δημιουργία Custom AppArmor Profiles
Μέθοδος 1: Αυτόματη δημιουργία με aa-genprof
Το aa-genprof είναι ένα διαδραστικό εργαλείο που σας βοηθά να δημιουργήσετε profiles παρατηρώντας τη συμπεριφορά μιας εφαρμογής σε πραγματικό χρόνο. Ιδανικό αν δεν θέλετε να γράψετε profile από το μηδέν:
# Βήμα 1: Ξεκινήστε τη δημιουργία profile
sudo aa-genprof /usr/local/bin/myapp
# Βήμα 2: Σε ΑΛΛΟ τερματικό, εκτελέστε την εφαρμογή
# και δοκιμάστε ΟΛΕΣ τις λειτουργίες της
/usr/local/bin/myapp --serve --port 8080
# Βήμα 3: Στο aa-genprof τερματικό, πατήστε (S)can
# Θα εμφανιστούν οι προσβάσεις που κατέγραψε
# Βήμα 4: Για κάθε πρόσβαση, αποφασίστε:
# (A)llow - Επίτρεψε αυτή την πρόσβαση
# (D)eny - Απόρριψε αυτή την πρόσβαση
# (G)lob - Χρησιμοποίηση wildcard
# (N)ew - Δημιουργία νέου abstraction
# Βήμα 5: Επαναλάβετε Scan → εκτέλεση μέχρι να
# καλυφθούν όλες οι λειτουργίες
# Βήμα 6: Πατήστε (F)inish
# Το profile μπαίνει σε enforce mode
Μέθοδος 2: Αναβάθμιση υπάρχοντος profile με aa-logprof
Αν μια εφαρμογή ήδη τρέχει με profile σε complain mode, μπορείτε να αναλύσετε τα denials και να ενημερώσετε το profile. Αυτή η μέθοδος είναι εξαιρετική για iterative tuning:
# Θέστε το profile σε complain mode
sudo aa-complain /usr/local/bin/myapp
# Αφήστε την εφαρμογή να τρέξει για κάποιο χρονικό διάστημα
# Αναλύστε τα logs και ενημερώστε το profile
sudo aa-logprof
# Επαναφέρετε σε enforce mode
sudo aa-enforce /usr/local/bin/myapp
Hardening AppArmor Profile για Nginx
Λοιπόν, ας δούμε ένα production-ready AppArmor profile για τον Nginx web server. Αυτό μπορεί να χρησιμεύσει ως βάση για τα δικά σας profiles:
# /etc/apparmor.d/usr.sbin.nginx
#include <tunables/global>
/usr/sbin/nginx {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/openssl>
# Capabilities
capability net_bind_service,
capability setuid,
capability setgid,
capability dac_override,
# Εκτελέσιμο
/usr/sbin/nginx mr,
# Configuration
/etc/nginx/ r,
/etc/nginx/** r,
/etc/ssl/certs/ r,
/etc/ssl/certs/** r,
/etc/ssl/private/ r,
/etc/ssl/private/** r,
# Web content — μόνο ανάγνωση
/var/www/ r,
/var/www/** r,
# Logs
/var/log/nginx/ rw,
/var/log/nginx/** w,
# PID και runtime
/run/nginx.pid rw,
/run/nginx/ rw,
/run/nginx/** rw,
# Temporary files
/var/lib/nginx/ rw,
/var/lib/nginx/** rw,
/var/cache/nginx/ rw,
/var/cache/nginx/** rw,
# Proc filesystem
/proc/sys/kernel/random/boot_id r,
# Ρητές απαγορεύσεις
deny /etc/shadow r,
deny /etc/gshadow r,
deny /root/** rwx,
deny /home/** rwx,
deny /proc/*/mem rwx,
deny /sys/firmware/** rwx,
# Αποτροπή εκτέλεσης shells
deny /bin/sh x,
deny /bin/bash x,
deny /bin/dash x,
deny /usr/bin/python* x,
deny /usr/bin/perl x,
}
SELinux vs AppArmor: Σύγκριση σε Βάθος
Αρχιτεκτονική Σύγκριση
Η θεμελιώδης διαφορά μεταξύ SELinux και AppArmor εντοπίζεται στον τρόπο αναγνώρισης αντικειμένων. Και αυτή η διαφορά δεν είναι καθόλου ασήμαντη:
- SELinux: Label-based — κάθε αντικείμενο (αρχείο, process, port) φέρει μια ετικέτα ασφαλείας. Ακόμα κι αν μετακινήσετε ένα αρχείο, η ετικέτα του ακολουθεί (εκτός αν γίνει relabeling). Αυτό δίνει ισχυρότερη ασφάλεια αλλά και μεγαλύτερη πολυπλοκότητα.
- AppArmor: Path-based — οι πολιτικές αναφέρονται σε μονοπάτια αρχείων. Αν μετακινήσετε ένα αρχείο σε νέα τοποθεσία, οι κανόνες δεν το ακολουθούν. Πιο απλό, ναι, αλλά δυνητικά λιγότερο ασφαλές σε κάποια σενάρια.
Πρακτική Σύγκριση
Ας δούμε πώς συγκρίνονται στην πράξη — γιατί η θεωρία είναι ωραία, αλλά τα πραγματικά παραδείγματα βοηθάνε περισσότερο:
# === Σενάριο: Αποτροπή πρόσβασης Apache στο /etc/shadow ===
# SELinux — Αυτόματο! Ο Apache (httpd_t) δεν μπορεί
# να αλληλεπιδράσει με shadow_t αρχεία
# Δεν χρειάζεται κανένα rule — αρκεί η targeted policy
# AppArmor — Χρειάζεται ρητό rule:
# deny /etc/shadow r,
# === Σενάριο: Custom web εφαρμογή στο /opt/myapp ===
# SELinux — Χρειάζεται labeling:
sudo semanage fcontext -a -t httpd_sys_content_t "/opt/myapp(/.*)?"
sudo restorecon -Rv /opt/myapp
# AppArmor — Προσθήκη path στο profile:
# /opt/myapp/ r,
# /opt/myapp/** r,
Πίνακας Σύγκρισης
Ακολουθεί μια συνοπτική σύγκριση για να βγάλετε τα δικά σας συμπεράσματα:
- Μέθοδος ελέγχου: SELinux — Labels/Types | AppArmor — File Paths
- Προεπιλογή: SELinux — RHEL, Fedora, openSUSE Tumbleweed | AppArmor — Ubuntu, Debian
- Πολυπλοκότητα: SELinux — Υψηλή | AppArmor — Χαμηλή-Μεσαία
- Granularity: SELinux — Πολύ υψηλό (MLS/MCS, TE, RBAC) | AppArmor — Μεσαίο
- Container isolation: SELinux — Εξαιρετικό (MCS labels) | AppArmor — Καλό (profiles)
- Debugging: SELinux —
audit2why,sealert| AppArmor —aa-logprof,dmesg - Compliance: SELinux — Απαιτείται για PCI-DSS, STIG | AppArmor — Αποδεκτό
- Καμπύλη εκμάθησης: SELinux — Απότομη | AppArmor — Ομαλή
Πότε να Επιλέξετε SELinux
- Κυβερνητικά, στρατιωτικά ή χρηματοοικονομικά περιβάλλοντα με αυστηρές απαιτήσεις compliance
- RHEL/Fedora-based συστήματα (είναι ήδη ενεργοποιημένο, γιατί να το αλλάξετε;)
- Container environments που χρειάζονται fine-grained isolation
- Κρίσιμα συστήματα όπου η ασφάλεια υπερισχύει της ευκολίας χρήσης
- Multi-tenant environments με αυστηρή απομόνωση δεδομένων
Πότε να Επιλέξετε AppArmor
- Ubuntu/Debian-based συστήματα (ήδη ενεργοποιημένο και δοκιμασμένο)
- Ομάδες με μικρή εμπειρία σε MAC συστήματα — η καμπύλη εκμάθησης είναι πολύ πιο ήπια
- Σενάρια που απαιτούν γρήγορο deployment profiles
- Web servers και application servers με σαφείς ανάγκες πρόσβασης
- Περιβάλλοντα ανάπτυξης όπου η απλότητα μειώνει τα λάθη configuration
Προχωρημένες Τεχνικές Hardening
SELinux: Confined Users και RBAC
Μια πολύ ισχυρή τεχνική hardening (και συχνά παραβλεπόμενη) είναι η αντιστοίχιση Linux χρηστών σε SELinux confined users. Αυτό περιορίζει τις ενέργειες τους ακόμα κι αν έχουν sudo δικαιώματα:
# Εμφάνιση τρέχουσας αντιστοίχισης χρηστών
sudo semanage login -l
# Login Name SELinux User MLS/MCS Range Service
# __default__ unconfined_u s0-s0:c0.c1023 *
# root unconfined_u s0-s0:c0.c1023 *
# Αντιστοίχιση χρήστη σε confined user
sudo semanage login -a -s user_u regularuser
# user_u: δεν μπορεί να εκτελέσει su/sudo, δεν μπορεί
# να αλλάξει ρόλο, περιορισμένη πρόσβαση δικτύου
# Αντιστοίχιση χρήστη σε staff_u (περιορισμένο sudo)
sudo semanage login -a -s staff_u adminuser
# staff_u: μπορεί να κάνει sudo αλλά με περιορισμούς TE
# Αντιστοίχιση default χρηστών σε confined user
sudo semanage login -m -s user_u __default__
# Αποτροπή εκτέλεσης μη εγκεκριμένων εκτελέσιμων
# από χρήστες τύπου user_u
sudo setsebool -P user_exec_content off
AppArmor: Stacking Profiles και Hat Profiles
Το AppArmor υποστηρίζει hat profiles (subprofiles) που επιτρέπουν σε μια εφαρμογή να αλλάζει security context κατά την εκτέλεση. Αυτό είναι ιδιαίτερα χρήσιμο για web servers με πολλαπλά virtual hosts:
# /etc/apparmor.d/usr.sbin.apache2
/usr/sbin/apache2 {
#include <abstractions/base>
capability net_bind_service,
# Βασικά δικαιώματα Apache
/var/www/html/ r,
/var/www/html/** r,
# Hat profiles — αλλαγή context ανά vhost
^wordpress {
/var/www/wordpress/ r,
/var/www/wordpress/** r,
/var/www/wordpress/wp-content/uploads/** rw,
deny /var/www/wordpress/wp-config.php w,
}
^api_backend {
/var/www/api/ r,
/var/www/api/** r,
network inet tcp,
/run/php/php-fpm.sock rw,
}
}
Αυτοματοποίηση MAC Hardening με Ansible
Σε μεγάλα περιβάλλοντα, η χειροκίνητη διαχείριση γίνεται γρήγορα αδύνατη. Η αυτοματοποίηση με Ansible είναι η φυσική λύση. Ακολουθεί ένα playbook για SELinux hardening:
---
# selinux_hardening.yml
- name: SELinux Hardening Playbook
hosts: all
become: yes
vars:
selinux_booleans:
- { name: 'httpd_can_network_connect', state: 'off' }
- { name: 'httpd_can_sendmail', state: 'off' }
- { name: 'httpd_enable_homedirs', state: 'off' }
- { name: 'deny_execmem', state: 'on' }
- { name: 'deny_ptrace', state: 'on' }
tasks:
- name: Ensure SELinux is in enforcing mode
ansible.posix.selinux:
policy: targeted
state: enforcing
- name: Set SELinux booleans
ansible.posix.seboolean:
name: "{{ item.name }}"
state: "{{ item.state }}"
persistent: yes
loop: "{{ selinux_booleans }}"
- name: Set file contexts for web application
community.general.sefcontext:
target: "/opt/webapp(/.*)?"
setype: httpd_sys_content_t
state: present
notify: restorecon webapp
- name: Map default users to confined SELinux user
ansible.builtin.command: >
semanage login -m -s user_u __default__
changed_when: true
handlers:
- name: restorecon webapp
ansible.builtin.command: restorecon -Rv /opt/webapp
Αντίστοιχα, για AppArmor hardening με Ansible:
---
# apparmor_hardening.yml
- name: AppArmor Hardening Playbook
hosts: all
become: yes
tasks:
- name: Ensure AppArmor is enabled and started
ansible.builtin.systemd:
name: apparmor
state: started
enabled: yes
- name: Deploy custom AppArmor profiles
ansible.builtin.copy:
src: "profiles/{{ item }}"
dest: "/etc/apparmor.d/{{ item }}"
owner: root
group: root
mode: '0644'
loop:
- usr.sbin.nginx
- usr.local.bin.myapp
notify: reload apparmor profiles
- name: Set all profiles to enforce mode
ansible.builtin.command: aa-enforce /etc/apparmor.d/*
changed_when: true
- name: Verify no profiles in complain mode
ansible.builtin.command: aa-status --complaining
register: complain_check
failed_when: complain_check.stdout | int > 0
handlers:
- name: reload apparmor profiles
ansible.builtin.command: >
apparmor_parser -r /etc/apparmor.d/{{ item }}
loop:
- usr.sbin.nginx
- usr.local.bin.myapp
Troubleshooting και Διάγνωση Προβλημάτων
SELinux Troubleshooting
Ας είμαστε ειλικρινείς: το debugging του SELinux μπορεί να γίνει αρκετά frustrating, ειδικά στην αρχή. Αλλά με τα σωστά εργαλεία, η κατάσταση βελτιώνεται δραματικά:
# === Εργαλείο 1: sealert (setroubleshoot) ===
# Εγκατάσταση
sudo dnf install setroubleshoot-server
# Ανάλυση audit log
sudo sealert -a /var/log/audit/audit.log
# Εμφάνιση σε πραγματικό χρόνο
sudo sealert -l "*"
# === Εργαλείο 2: ausearch ===
# Αναζήτηση AVC denials τις τελευταίες 10 λεπτά
sudo ausearch -m AVC -ts recent
# Αναζήτηση denials για συγκεκριμένο service
sudo ausearch -m AVC -c httpd -ts today
# === Εργαλείο 3: sesearch ===
# Εύρεση ποιοι κανόνες επιτρέπουν πρόσβαση
sudo sesearch --allow --source httpd_t --target httpd_sys_content_t
# === Εργαλείο 4: seinfo ===
# Εμφάνιση στατιστικών πολιτικής
sudo seinfo
# Εμφάνιση όλων των τύπων
sudo seinfo -t | grep httpd
# === Κοινά προβλήματα και λύσεις ===
# Πρόβλημα: Apache δεν μπορεί να διαβάσει αρχεία
# Λύση: Ελέγξτε file context
ls -Z /var/www/html/
sudo restorecon -Rv /var/www/html/
# Πρόβλημα: Service δεν ξεκινά μετά από αλλαγή port
# Λύση: Προσθέστε τον port στο SELinux
sudo semanage port -a -t http_port_t -p tcp 8443
# Πρόβλημα: Custom app δεν μπορεί να γράψει σε /var/log
# Λύση: Δημιουργήστε file context
sudo semanage fcontext -a -t var_log_t "/var/log/myapp(/.*)?"
sudo restorecon -Rv /var/log/myapp
AppArmor Troubleshooting
Το troubleshooting στο AppArmor είναι γενικά πιο εύκολο, αλλά θέλει κι αυτό τη μέθοδό του:
# Εμφάνιση denials σε πραγματικό χρόνο
sudo journalctl -k -f | grep "apparmor.*DENIED"
# Λεπτομερής ανάλυση denial:
# type=1400 audit(1708345678.123:456):
# apparmor="DENIED"
# operation="open"
# profile="/usr/sbin/nginx"
# name="/srv/extra/data.txt"
# pid=1234
# comm="nginx"
# requested_mask="r"
# denied_mask="r"
# Ερμηνεία:
# - profile: ποιο profile εφαρμόστηκε
# - name: ποιο αρχείο ζητήθηκε
# - requested_mask: τι ζητήθηκε (r=read)
# - denied_mask: τι απορρίφθηκε
# Γρήγορη διόρθωση: θέστε σε complain mode
sudo aa-complain /usr/sbin/nginx
# Ενημερώστε το profile
sudo aa-logprof
# Επαναφέρετε σε enforce
sudo aa-enforce /usr/sbin/nginx
Ολοκληρωμένο Hardening Checklist
SELinux Production Checklist
Κρατήστε αυτή τη λίστα κοντά σας — θα σας φανεί χρήσιμη:
- Βεβαιωθείτε ότι το SELinux είναι σε Enforcing mode —
getenforceπρέπει να δείχνειEnforcing - Ελέγξτε τους confined users — αντιστοιχίστε
__default__σεuser_u - Σφίξτε τα Booleans — απενεργοποιήστε
httpd_can_network_connect,httpd_can_sendmail, κ.λπ. - Ελέγξτε για unconfined processes —
ps auxZ | grep unconfined_t - Ελέγξτε file contexts —
restorecon -Rvn /(dry-run) για εντοπισμό mislabeled αρχείων - Αναθεωρήστε custom modules —
semodule -lκαι αφαιρέστε αχρείαστα modules - Ενεργοποιήστε audit logging — βεβαιωθείτε ότι ο auditd τρέχει
- Ρυθμίστε MCS για containers — επαληθεύστε ότι κάθε container έχει μοναδικά categories
- Εφαρμόστε deny_execmem — αποτροπή code injection σε memory
- Αυτοματοποιήστε με Ansible — εξασφαλίστε επαναληπτικότητα και consistency
AppArmor Production Checklist
- Βεβαιωθείτε ότι το AppArmor είναι ενεργό —
aa-status - Ελέγξτε ότι ΟΛΑ τα profiles είναι σε enforce mode — κανένα σε complain στο production
- Δημιουργήστε profiles για κάθε εκτεθειμένο service — web servers, databases, custom apps
- Χρησιμοποιήστε deny rules — ρητή απαγόρευση πρόσβασης σε ευαίσθητα αρχεία
- Αποτρέψτε εκτέλεση shells —
deny /bin/sh xκ.λπ. σε web services - Ελέγξτε τα capabilities — μόνο τα απαραίτητα capabilities ανά profile
- Παρακολουθήστε τα logs —
journalctl -kγια denials - Ενημερώνετε τα profiles — μετά από κάθε αναβάθμιση εφαρμογών
- Αυτοματοποιήστε — deploy profiles μέσω Ansible ή configuration management
- Δοκιμάστε σε complain mode πρώτα — πάντα πριν μεταβείτε σε enforce
Ενσωμάτωση MAC σε DevSecOps Pipelines
Ο Υποχρεωτικός Έλεγχος Πρόσβασης δεν πρέπει να αποτελεί afterthought — και δυστυχώς, σε πολλές ομάδες ακόμα αντιμετωπίζεται έτσι. Σε ένα σωστό DevSecOps pipeline, τα SELinux/AppArmor profiles αναπτύσσονται μαζί με τον κώδικα:
# .gitlab-ci.yml — MAC Profile Testing Stage
stages:
- build
- test
- security
- deploy
mac_profile_test:
stage: security
image: registry.example.com/selinux-builder:latest
script:
# SELinux policy compilation test
- checkmodule -M -m -o myapp.mod selinux/myapp.te
- semodule_package -o myapp.pp -m myapp.mod
- echo "SELinux policy compiled successfully"
# AppArmor profile syntax check
- apparmor_parser -p apparmor/usr.local.bin.myapp
- echo "AppArmor profile syntax is valid"
artifacts:
paths:
- myapp.pp
- apparmor/usr.local.bin.myapp
deploy_mac_profiles:
stage: deploy
script:
# Deploy SELinux module
- sudo semodule -i myapp.pp
- sudo restorecon -Rv /opt/myapp
# Ή deploy AppArmor profile
- sudo cp apparmor/usr.local.bin.myapp /etc/apparmor.d/
- sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myapp
- sudo aa-enforce /usr/local/bin/myapp
Συμπεράσματα
Ο Υποχρεωτικός Έλεγχος Πρόσβασης δεν είναι πολυτέλεια — είναι αναγκαιότητα. Είτε πάτε με SELinux είτε με AppArmor, το σημαντικό είναι να μην αφήνετε τα συστήματά σας γυμνά χωρίς MAC protection. Η μετάβαση του openSUSE στο SELinux το 2025 δείχνει ξεκάθαρα προς ποια κατεύθυνση κινείται η βιομηχανία, αλλά το AppArmor παραμένει εξαιρετική επιλογή, ιδιαίτερα σε Ubuntu/Debian περιβάλλοντα.
Ανεξαρτήτως ποιο σύστημα χρησιμοποιείτε, τα βασικά βήματα είναι τα ίδια: ενεργοποιήστε enforcing mode, δημιουργήστε εξειδικευμένα profiles για κάθε εκτεθειμένο service, παρακολουθήστε τα logs, αυτοματοποιήστε τις διαδικασίες, και ενσωματώστε τα profiles στο CI/CD pipeline σας.
Ξεκινήστε σήμερα: τρέξτε ένα getenforce ή aa-status στους servers σας, αναθεωρήστε τα υπάρχοντα profiles, και δημιουργήστε custom πολιτικές για τις εφαρμογές σας. Κάθε βήμα — ακόμα και το μικρότερο — μειώνει σημαντικά την επιφάνεια επίθεσης του συστήματός σας. Η ασφάλεια δεν είναι εφάπαξ ρύθμιση, αλλά μια συνεχής διαδικασία.