SELinux και AppArmor το 2026: Πλήρης Οδηγός Θωράκισης με MAC

Πλήρης οδηγός SELinux και AppArmor: custom policy modules, hardening booleans, MCS container isolation, AppArmor profiles, αυτοματοποίηση Ansible και ενσωμάτωση DevSecOps. Ό,τι χρειάζεστε για θωράκιση Linux servers.

Εισαγωγή: Γιατί ο Υποχρεωτικός Έλεγχος Πρόσβασης Δεν Είναι Προαιρετικός

Ας πούμε τα πράγματα με το όνομά τους: αν τρέχετε 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

Κρατήστε αυτή τη λίστα κοντά σας — θα σας φανεί χρήσιμη:

  1. Βεβαιωθείτε ότι το SELinux είναι σε Enforcing modegetenforce πρέπει να δείχνει Enforcing
  2. Ελέγξτε τους confined users — αντιστοιχίστε __default__ σε user_u
  3. Σφίξτε τα Booleans — απενεργοποιήστε httpd_can_network_connect, httpd_can_sendmail, κ.λπ.
  4. Ελέγξτε για unconfined processesps auxZ | grep unconfined_t
  5. Ελέγξτε file contextsrestorecon -Rvn / (dry-run) για εντοπισμό mislabeled αρχείων
  6. Αναθεωρήστε custom modulessemodule -l και αφαιρέστε αχρείαστα modules
  7. Ενεργοποιήστε audit logging — βεβαιωθείτε ότι ο auditd τρέχει
  8. Ρυθμίστε MCS για containers — επαληθεύστε ότι κάθε container έχει μοναδικά categories
  9. Εφαρμόστε deny_execmem — αποτροπή code injection σε memory
  10. Αυτοματοποιήστε με Ansible — εξασφαλίστε επαναληπτικότητα και consistency

AppArmor Production Checklist

  1. Βεβαιωθείτε ότι το AppArmor είναι ενεργόaa-status
  2. Ελέγξτε ότι ΟΛΑ τα profiles είναι σε enforce mode — κανένα σε complain στο production
  3. Δημιουργήστε profiles για κάθε εκτεθειμένο service — web servers, databases, custom apps
  4. Χρησιμοποιήστε deny rules — ρητή απαγόρευση πρόσβασης σε ευαίσθητα αρχεία
  5. Αποτρέψτε εκτέλεση shellsdeny /bin/sh x κ.λπ. σε web services
  6. Ελέγξτε τα capabilities — μόνο τα απαραίτητα capabilities ανά profile
  7. Παρακολουθήστε τα logsjournalctl -k για denials
  8. Ενημερώνετε τα profiles — μετά από κάθε αναβάθμιση εφαρμογών
  9. Αυτοματοποιήστε — deploy profiles μέσω Ansible ή configuration management
  10. Δοκιμάστε σε 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 πολιτικές για τις εφαρμογές σας. Κάθε βήμα — ακόμα και το μικρότερο — μειώνει σημαντικά την επιφάνεια επίθεσης του συστήματός σας. Η ασφάλεια δεν είναι εφάπαξ ρύθμιση, αλλά μια συνεχής διαδικασία.

Σχετικά με τον Συγγραφέα Editorial Team

Our team of expert writers and editors.