G
GuideDevOps
Lesson 15 of 17

Security & Firewalls

Part of the Linux Fundamentals tutorial series.

Linux Security Fundamentals

As a DevOps engineer, securing your servers is as critical as deploying them. A default Linux installation requires hardening before exposure to any network.


Firewall Fundamentals

A firewall filters network traffic based on rules. Linux's packet filtering framework is netfilter, managed through frontend tools.


UFW — Uncomplicated Firewall

UFW is the default firewall for Ubuntu/Debian. It simplifies iptables.

# Check UFW status
$ sudo ufw status verbose
Status: inactive
 
# Enable UFW (always allow SSH first!)
$ sudo ufw allow 22/tcp comment 'SSH access'
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation? y
Firewall is active and enabled on startup
 
# After enabling, verify SSH is allowed
$ sudo ufw status verbose
Status: active
 
To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                   # SSH access
80/tcp                     ALLOW       Anywhere                   # HTTP
443/tcp                    ALLOW       Anywhere                   # HTTPS

Common UFW Commands

# Allow SSH (by service name)
$ sudo ufw allow ssh
 
# Allow by port number
$ sudo ufw allow 22/tcp
$ sudo ufw allow 80/tcp
 
# Allow from specific IP
$ sudo ufw allow from 192.168.1.100
 
# Allow from subnet
$ sudo ufw allow from 192.168.1.0/24
 
# Allow to specific port from anywhere
$ sudo ufw allow 8080/tcp
 
# Deny a connection
$ sudo ufw deny from 192.168.1.100
 
# Delete a rule
$ sudo ufw delete allow 80/tcp
 
# Allow established connections (for outgoing traffic)
$ sudo ufw allow out on eth0
 
# Show numbered rules
$ sudo ufw status numbered
[ 1] 22/tcp                     ALLOW IN     Anywhere
[ 2] 80/tcp                     ALLOW IN     Anywhere
 
# Delete rule by number
$ sudo ufw delete 2

Application Profiles

UFW ships with profiles for common apps:

# List application profiles
$ sudo ufw app list
Available applications:
  Apache
  Apache Full
  Apache Secure
  CUPS
  Dovecot
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
  Postfix
  Postfix SMTPS
  Postfix Submission
 
# Allow using a profile
$ sudo ufw allow 'Nginx Full'
 
# View profile details
$ sudo ufw app info 'Nginx Full'
Profile: Nginx Full
Title: Web Server (Nginx, HTTP + HTTPS)
Description: Full Nginx Web Server
Ports:
  80,443/tcp

UFW with Docker

# If using Docker, Docker manages its own firewall rules
# UFW and Docker can conflict
 
# Option 1: Allow Docker to manage iptables
# In /etc/docker/daemon.json:
# { "iptables": true }
 
# Option 2: Configure UFW for Docker
# In /etc/default/ufw:
# DEFAULT_FORWARD_POLICY="ACCEPT"

Firewalld — RHEL/CentOS/Fedora

Firewalld uses zones to define trust levels for network connections.

# Check if running
$ sudo firewall-cmd --state
running
 
# Get active zones
$ sudo firewall-cmd --get-active-zones
public
  interfaces: eth0
 
# List all zones
$ sudo firewall-cmd --get-zones
 
# List services in current zone
$ sudo firewall-cmd --list-services
dhcpv6-client ssh
 
# List ports in current zone
$ sudo firewall-cmd --list-ports

Managing Services

# Allow HTTP and HTTPS permanently
$ sudo firewall-cmd --zone=public --add-service=http --permanent
$ sudo firewall-cmd --zone=public --add-service=https --permanent
$ sudo firewall-cmd --reload
 
# Allow a custom port
$ sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
$ sudo firewall-cmd --reload
 
# Remove a service
$ sudo firewall-cmd --zone=public --remove-service=http --permanent
$ sudo firewall-cmd --reload
 
# Allow SSH from specific IP
$ sudo firewall-cmd --zone=trusted --add-source=192.168.1.0/24 --permanent
$ sudo firewall-cmd --zone=trusted --add-service=ssh --permanent
$ sudo firewall-cmd --reload

Creating a Custom Zone

# Create a zone for web traffic
$ sudo firewall-cmd --new-zone=webserver --permanent
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --zone=webserver --add-service=http --permanent
$ sudo firewall-cmd --zone=webserver --add-service=https --permanent
$ sudo firewall-cmd --zone=webserver --add-interface=eth1 --permanent

Iptables — The Classic Tool

iptables is the foundational firewall tool. UFW and Firewalld are abstractions over it.

# List current rules
$ sudo iptables -L -n -v
Chain INPUT (policy ACCEPT)
target  prot opt source       destination
ACCEPT  all  --  0.0.0.0/0  0.0.0.0/0   state RELATED,ESTABLISHED
ACCEPT  tcp  --  0.0.0.0/0  0.0.0.0/0   tcp dpt:22
ACCEPT  tcp  --  0.0.0.0/0  0.0.0.0/0   tcp dpt:80
DROP    all  --  0.0.0.0/0  0.0.0.0/0
 
# Allow incoming SSH
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
 
# Allow HTTP/HTTPS
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
 
# Drop all other incoming traffic
$ sudo iptables -A INPUT -j DROP
 
# Save rules (Ubuntu)
$ sudo netfilter-persistent save

Chains:

ChainPurpose
INPUTIncoming traffic to the host
OUTPUTOutgoing traffic from the host
FORWARDTraffic being routed through the host

Targets:

TargetEffect
ACCEPTAllow the packet
DROPSilently discard the packet
REJECTDiscard and send error response

Mandatory Access Control — SELinux & AppArmor

Standard Linux permissions (rwx) are Discretionary Access Control (DAC). MAC systems provide additional enforcement.

SELinux (RHEL/CentOS)

# Check SELinux status
$ getenforce
Enforcing
 
# Modes:
# Enforcing  - SELinux policy is enforced
# Permissive - SELinux logs but doesn't block
# Disabled   - SELinux is off
 
# Temporarily set to permissive (for troubleshooting)
$ sudo setenforce Permissive
 
# Permanently set in /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
 
# Check SELinux context on files
$ ls -Z /var/log/nginx/
system_u:object_r:httpd_log_t:s0  access.log
system_u:object_r:httpd_log_t:s0  error.log
 
# Check processes
$ ps auxZ | grep nginx
system_u:system_r:httpd_t:s0    nginx: master process /usr/sbin/nginx
 
# Allow a service to access a directory
$ sudo setsebool -P httpd_read_user_content 1

AppArmor (Ubuntu/Debian)

# Check AppArmor status
$ sudo aa-status
apparmor module is loaded.
35 profiles are loaded.
32 profiles are in enforce mode.
3 profiles are in complain mode.
 
# View a specific profile
$ sudo aa-status --show=nginx
 
# Set a profile to complain mode (logs violations but allows)
$ sudo aa-complain /usr/sbin/nginx
 
# Set back to enforce mode
$ sudo aa-enforce /usr/sbin/nginx

Essential Security Hardening

1. Disable Root Login Over SSH

# Edit /etc/ssh/sshd_config
$ sudo nano /etc/ssh/sshd_config
PermitRootLogin no
 
# Reload SSH
$ sudo systemctl reload ssh

2. Use Key-Based SSH Only

# In /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes

3. Keep the System Updated

# Ubuntu/Debian
$ sudo apt update && sudo apt upgrade -y
 
# RHEL/CentOS
$ sudo dnf update -y

4. Principle of Least Privilege

# Don't run services as root
# Configure web server to run as www-data
$ sudo chown -R www-data:www-data /var/www/html
 
# Don't give sudo to everyone
$ sudo usermod -aG sudo alice    # Only if absolutely needed

5. Configure Fail2Ban

# Install fail2ban (blocks brute-force attackers)
$ sudo apt install fail2ban -y
 
# Configure
$ sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
 
[sshd]
enabled = true
 
$ sudo systemctl enable fail2ban
$ sudo systemctl start fail2ban

Quick Reference

TaskCommand
Check UFW statussudo ufw status verbose
Allow SSHsudo ufw allow ssh
Allow portsudo ufw allow 80/tcp
Deny IPsudo ufw deny from IP
Enable firewallsudo ufw enable
List firewalld zonessudo firewall-cmd --get-active-zones
Allow servicesudo firewall-cmd --add-service=http --permanent
List iptables rulessudo iptables -L -n -v
Check SELinuxgetenforce
Check AppArmorsudo aa-status

Practice Challenge

  1. Check if UFW or firewalld is installed: which ufw firewall-cmd
  2. Run sudo ufw status verbose if UFW is installed
  3. List all iptables rules: sudo iptables -L -n
  4. Check your SSH configuration: grep "^PermitRootLogin" /etc/ssh/sshd_config
  5. View system open ports: ss -tuln