21.1 Manage SELinux Port Labels

Key Takeaways

  • SELinux labels TCP/UDP ports with types such as http_port_t; a service confined to a domain may only bind ports whose type its policy allows.
  • List mappings with semanage port -l (filter with grep); add with -a -t TYPE -p protocol port, modify with -m, delete with -d.
  • Changing the listen port of httpd (or similar) without updating the SELinux port type is a classic EX200 failure—firewall open is not enough.
  • Port label changes via semanage are persistent; verify after change with semanage port -l and by restarting the service under Enforcing.
  • When bind fails under Enforcing, check AVC denials with ausearch -m avc -ts recent and sealert; do not habitually disable SELinux to “fix” ports.
Last updated: August 2026

21.1 Manage SELinux Port Labels

Quick Answer: SELinux assigns types to TCP/UDP ports. List with semanage port -l. Add semanage port -a -t TYPE -p tcp|udp PORT, modify with -m, delete with -d. Common web example: non-default HTTP ports need http_port_t. Changes persist. Debug bind denials with ausearch / sealert while remaining in Enforcing.

Why port labels matter on EX200

Under Manage security, Red Hat expects you to manage SELinux port labels. Exam scenarios often look like:

  • “Configure Apache (httpd) to listen on port 8080 and allow it under SELinux.”
  • “Add TCP port 8443 as an HTTP-related SELinux port type.”
  • “Remove a custom port mapping that is no longer required.”
  • “A service fails only when SELinux is Enforcing; fix the port label without disabling SELinux.”

You already know file contexts (ls -Z, restorecon) and modes (getenforce, setenforce, /etc/selinux/config) from earlier security sections. Port types are the network-side twin of file types: the policy decides which process domain may bind/connect which port type.

Firewalld is separate. Opening a port in firewalld allows packets through the host firewall. SELinux still decides whether the confined daemon is allowed to use that port. Graders expect both when a service must be reachable on a non-default port under Enforcing.

Mental model: domains, types, and ports

ConceptExampleRole
Process domainhttpd_tLabel of the running service
File typehttpd_sys_content_tLabel of content the service may read
Port typehttp_port_tLabel of ports the service may bind

Policy rules roughly say: processes in domain X may bind ports of type Y. Default mappings already cover standard ports (for example TCP 80 and 443 map to HTTP-related types). Custom listen ports usually do not inherit those types until you map them with semanage port.

getenforce
sestatus
# Expect Enforcing on exam systems unless a task says otherwise

If you only test in Permissive, you may miss denials that Enforcing would block—practice and verify under Enforcing.

List port labels with semanage port -l

sudo semanage port -l
sudo semanage port -l | grep http
sudo semanage port -l | grep -E 'http_port_t|http_cache_port_t'
sudo semanage port -l | grep 8080

Output columns are essentially: SELinux type, protocol (tcp/udp), port list.

Example lines you will recognize (exact default lists vary slightly by policy package version):

http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
mysql_port_t                   tcp      1186, 3306, 63132-63164
ssh_port_t                     tcp      22

Read before you write. If the task’s port is already listed under the correct type, do not blindly re-add it—re-adding an existing definition often errors. If the port is listed under the wrong type, you may need modify or delete then add, depending on how it was defined.

sudo semanage port -l | grep -w 8080
sudo semanage port -lC        # when available: show local customizations only

On many RHEL systems, semanage port -l -C (or the policy’s “customized” view) highlights local overrides versus full policy defaults—useful to confirm your exam change stuck.

Add a port mapping: semanage port -a

# General form
sudo semanage port -a -t PORT_TYPE -p PROTOCOL PORT

# Classic EX200: allow httpd-style binding on TCP 8080
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage port -l | grep -w 8080
FlagMeaning
-aAdd a new port definition
-t TYPESELinux port type (e.g. http_port_t)
-p tcp / -p udpProtocol—must match how the service listens
PORTSingle port or range (syntax like 10000-10010 when supported)

httpd on a non-default port (end-to-end pattern)

  1. Configure httpd to listen (for example Listen 8080 in config under /etc/httpd/).
  2. Open the port in firewalld if remote access is required.
  3. Map the port for SELinux:
sudo semanage port -a -t http_port_t -p tcp 8080
  1. Restart and test under Enforcing:
sudo systemctl restart httpd
sudo systemctl status httpd --no-pager
ss -tlnp | grep 8080
curl -I http://127.0.0.1:8080/

If httpd fails to start or bind only under Enforcing, check port labels and file contexts on DocumentRoot/config (file contexts are covered in earlier sections)—both can cause AVC denials.

Other type examples (know the pattern)

Service scenarioTypical port typeExample
HTTP/HTTPS alt portshttp_port_tsemanage port -a -t http_port_t -p tcp 8080
SSH on non-22ssh_port_tsemanage port -a -t ssh_port_t -p tcp 2222
DNSdns_port_toften already 53; custom as required
MySQL/MariaDB custommysqld_port_t / mysql_port_tmatch what semanage port -l | grep mysql shows on the host

On the exam: discover the correct type with semanage port -l | grep service-ish-name rather than inventing type strings. Policy type names are fixed by the installed SELinux policy modules.

Modify existing mappings: semanage port -m

Use -m (modify) when a port definition already exists and you need to change its type or adjust a definition the policy already owns in a way semanage treats as modify-able:

sudo semanage port -m -t http_port_t -p tcp 8080
SituationPrefer
Port not listed for the needed type-a add
Port already defined and you must change type-m modify (or delete then add if modify fails)
Port wrongly customized and must go away-d delete
# If add fails because the port is already defined:
sudo semanage port -a -t http_port_t -p tcp 8080
# ValueError / already defined → try modify:
sudo semanage port -m -t http_port_t -p tcp 8080

Exam discipline: read the error. “Already defined” is not a reason to set SELinux Permissive; it is a reason to list, then modify or delete/re-add correctly.

Delete a mapping: semanage port -d

sudo semanage port -d -t http_port_t -p tcp 8080
sudo semanage port -l | grep -w 8080 || echo "8080 mapping removed or not present"

Delete requires the same type and protocol that defined the local mapping. You generally cannot delete built-in default ports from base policy the same way you remove local customizations—if delete fails on a default port, you were not supposed to remove it; map additional ports instead.

# Wrong expectation: deleting tcp/80 from policy entirely — not an exam goal
# Right expectation: remove a lab custom you added earlier
sudo semanage port -d -t http_port_t -p tcp 8080

Persistence and package prerequisites

semanage comes from policycoreutils-python-utils (package name on RHEL; install with dnf if missing on a practice VM). Local customizations are stored in the SELinux policy store and survive reboot. You do not put semanage lines in /etc/rc.local for persistence—the policy database is the persistence mechanism.

rpm -q policycoreutils-python-utils
sudo dnf -y install policycoreutils-python-utils   # if needed in a lab

After changes:

sudo semanage port -l | grep -w 8080
sudo systemctl restart httpd
getenforce

Troubleshooting: ausearch and sealert

When a service fails under Enforcing after a port change (or before you remembered to map the port):

# Recent AVC denials
sudo ausearch -m avc -ts recent
sudo ausearch -m avc -ts recent | grep -i http

# Human-readable guidance when setroubleshoot is installed
sudo sealert -a /var/log/audit/audit.log
# or follow the sealert command suggested in /var/log/messages

Typical port-related denial language involves name_bind on a port with a type that is not allowed for the domain (for example httpd_t trying to bind a port still typed as something other than an allowed HTTP port type).

ToolUse
ausearch -m avc -ts recentRaw recent denials from audit
ausearch -m avc -ts todayBroader time window
sealertExplains denials; may suggest semanage port or booleans
journalctl -u httpdService-level bind/start errors
ss -tlnp / ss -ulnpWhat is actually listening

Do not “fix” port problems by:

  1. Leaving the system in Permissive permanently, or
  2. Setting SELINUX=disabled in /etc/selinux/config, or
  3. Only opening firewalld while ignoring SELinux.

Those hide the objective. EX200 wants the correct label (and related policy tools) under Enforcing.

# Temporary diagnosis only — return to Enforcing
sudo setenforce 0          # Permissive — denials logged, not blocked
# reproduce; then:
sudo setenforce 1
# implement the real fix with semanage port ...

Use Permissive briefly to confirm “this is SELinux,” then apply the port type fix and re-test Enforcing.

Interaction with firewalld (do both)

# Example: public reachability on 8080 plus SELinux port type
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
sudo semanage port -a -t http_port_t -p tcp 8080
sudo systemctl restart httpd
LayerToolQuestion answered
Host firewallfirewalld / firewall-cmdMay packets reach the host port?
Mandatory accessSELinux port typeMay this domain bind/use the port?
Service confighttpd Listen, etc.Does the daemon try that port?

Fail any one layer and the exam check fails.

Exam workflows

Workflow A — Map TCP 8080 for HTTP and verify

getenforce
sudo semanage port -l | grep -w 8080
sudo semanage port -a -t http_port_t -p tcp 8080
# if already defined for another treatment:
# sudo semanage port -m -t http_port_t -p tcp 8080
sudo semanage port -l | grep -w 8080
sudo systemctl restart httpd
ss -tlnp | grep 8080

Workflow B — SSH on custom port 2222

# After sshd_config Port 2222 (and firewall if needed)
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo systemctl restart sshd
sudo semanage port -l | grep ssh_port_t

Workflow C — Remove a custom mapping

sudo semanage port -d -t http_port_t -p tcp 8080
sudo semanage port -l | grep -w 8080 || echo gone

Workflow D — Denial-driven discovery

sudo systemctl restart httpd
sudo ausearch -m avc -ts recent
# Identify name_bind / port in denial → choose type from:
sudo semanage port -l | grep http
sudo semanage port -a -t http_port_t -p tcp 8080
sudo systemctl restart httpd
getenforce   # still Enforcing

Common traps

  1. Opening firewalld only and forgetting semanage port.
  2. Using semanage port -a when the port is already defined—need -m or delete first.
  3. Wrong protocol (tcp vs udp).
  4. Wrong type name—always discover with semanage port -l | grep ....
  5. Mapping the port but never restarting the service.
  6. Fixing under Permissive and leaving the host Permissive.
  7. Editing only runtime sshd/httpd without SELinux when the failure is name_bind.
  8. Expecting file restorecon alone to fix a port problem.
  9. Deleting default ports like 22 or 80 from policy—not the skill; add custom ports.
  10. Ignoring ausearch/sealert when the reason is unclear.

Relationship to other sections

SkillWhere
SELinux modes (Enforcing/Permissive)20.x core
File/process contexts, restorecon20.x core
Port labels21.1 (this)
Booleans (setsebool)21.2
firewalldSecurity / networking chapters
httpd listen configurationService deploy skills

Section checkpoint

You should list SELinux port mappings with semanage port -l, add non-default ports with -a -t TYPE -p proto PORT (especially http_port_t for alternate HTTP ports), modify with -m, delete local mappings with -d, verify under Enforcing with service restart and ss/curl, and use ausearch/sealert when bind denials appear—without disabling SELinux. That is the EX200 bar for managing SELinux port labels on RHEL 10.

Test Your Knowledge

Apache must listen on TCP 8080 under SELinux Enforcing. Which command correctly adds the usual HTTP port type for that socket?

A
B
C
D
Test Your Knowledge

You run semanage port -a -t http_port_t -p tcp 8080 and receive an error that the port is already defined. What is the best next action?

A
B
C
D
Test Your Knowledge

Which command best lists current SELinux port type mappings so you can discover the right type name on the exam host?

A
B
C
D
Test Your Knowledge

httpd fails to bind a custom port only when getenforce shows Enforcing. Which pair is most appropriate for diagnosis and correct remediation?

A
B
C
D