Basic Linux server and workstation security for internet-facing systems

Server Hardening

Linux Server
Security Checklist

This is a basic security checklist for a Linux server or workstation that is connected to the internet. The goal is not to make the system impossible to attack, but to reduce the most common risks: outdated packages, weak SSH configuration, unnecessary open ports, unmanaged services and brute-force login attempts.

Security
SSH
Firewall
Fail2ban

Step 01

1. Keep the operating system updated

The first security rule is simple: keep the system and installed packages updated. Security updates should be installed regularly, especially on internet-facing servers.

Debian, Ubuntu, Linux Mint:

sudo apt update
sudo apt upgrade

Fedora, RHEL, Rocky Linux, AlmaLinux:

sudo dnf upgrade

Arch, Manjaro, EndeavourOS:

sudo pacman -Syu

openSUSE:

sudo zypper update

Network Protocol

2. IPv6: disable only if you really do not use it

Older security guides often recommend disabling IPv6 completely. On modern Linux systems, this should not be treated as a universal rule. If IPv6 is used by your network, router, VPN, hosting provider or firewall policy, do not disable it blindly.

If your system uses only IPv4 and you are sure IPv6 is not needed, you can disable IPv6. On systems using NetworkManager, it is better to disable IPv6 per connection.

Show NetworkManager connections:

nmcli connection show

Disable IPv6 for a selected connection:

sudo nmcli connection modify “CONNECTION_NAME” ipv6.method disabled
sudo nmcli connection down “CONNECTION_NAME”
sudo nmcli connection up “CONNECTION_NAME”

Alternative sysctl method:

sudo nano /etc/sysctl.d/99-disable-ipv6.conf

Add:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Apply the change:

sudo sysctl –system
Important: if IPv6 remains enabled, secure it with firewall rules. Do not protect only IPv4 while leaving IPv6 open.

Local Services

3. Avahi & 4. Samba Hardening

3. Avahi / mDNS service discovery

Avahi provides mDNS / DNS-SD service discovery on local networks. It is useful on trusted LANs, but it is usually not needed on internet-facing servers.

Check whether Avahi is running:

systemctl status avahi-daemon

If Avahi is not needed, disable it:

sudo systemctl disable –now avahi-daemon

If you need Avahi only on IPv4, edit:

sudo nano /etc/avahi/avahi-daemon.conf

Useful options:

use-ipv6=no
publish-a-on-ipv6=no

Then restart Avahi:

sudo systemctl restart avahi-daemon

4. Samba / SMB hardening

If Samba is not needed, disable it completely:

sudo systemctl disable –now smbd nmbd

If Samba is needed but you want to avoid old NetBIOS-style behavior, edit:

sudo nano /etc/samba/smb.conf

In the [global] section, you can use:

[global]
disable netbios = yes
smb ports = 445

Then restart Samba:

sudo systemctl restart smbd

Port 445 is used for direct SMB over TCP. Port 139 is related to older NetBIOS-based SMB access. If you do not need legacy clients, avoid old SMB/NetBIOS behavior.

Access Control

5. Root Account & 6. SSH Hardening

5. Root account and administrator access

Do not allow direct remote SSH login as root. Use a normal user account with sudo privileges instead.

Check users with sudo/admin rights:

getent group sudo
getent group wheel

On Debian/Ubuntu systems, sudo users are usually in the sudo group. On Fedora/RHEL/Arch-based systems, sudo users are often in the wheel group.

Create an admin user if needed:

sudo adduser adminuser
sudo usermod -aG sudo adminuser

On Fedora/RHEL/Arch-style systems:

sudo usermod -aG wheel adminuser

Before disabling root SSH login, test that the new admin user can log in and run sudo.

6. SSH hardening

The SSH server configuration is usually here: /etc/ssh/sshd_config. Before editing, keep an active SSH session open. This helps prevent accidental lockout.

sudo nano /etc/ssh/sshd_config

Recommended baseline:

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
X11Forwarding no

After changing SSH configuration, test the syntax:

sudo sshd -t

Restart SSH:

sudo systemctl restart sshd

On Debian/Ubuntu, the service may be named ssh: sudo systemctl restart ssh

Changing the SSH port from 22 to another port can reduce automated bot noise, but it is not a replacement for real security. SSH keys, disabled root login, disabled password login and firewall rules are more important.

Example custom SSH port:

Port 2222

Before changing the port, check whether the new port is already used:

sudo ss -ltnp ‘sport = :2222’

Allow the new port in the firewall before restarting SSH.

Network Defense

Firewalls, Ports & Scanning

7. Firewall basics

Every internet-facing Linux system should have a firewall policy. Allow only services that should be reachable from the network.

Check open listening TCP/UDP ports & established connections:

sudo ss -ltnup
sudo ss -tnp state established

Modern Linux systems often use nftables directly or through tools such as firewalld or ufw.

Ubuntu/Debian simple firewall example with UFW:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp
sudo ufw enable
sudo ufw status verbose

firewalld example:

sudo firewall-cmd –add-port=2222/tcp –permanent
sudo firewall-cmd –reload
sudo firewall-cmd –list-all

nftables ruleset check:

sudo nft list ruleset

8. Replace netstat with ss

Older guides often use netstat. On modern Linux, use ss instead.

# Old command:
netstat -a | grep tcp

# Modern replacement:
ss -ta

# Show listening TCP sockets with PID and program:
sudo ss -ltnp

# Show listening TCP and UDP sockets:
sudo ss -ltnup

# Show all IPv4 TCP connections:
ss -4 -tan

# Show all IPv6 TCP connections:
ss -6 -tan

9. Port scanning and service discovery

Use nmap to check what is visible from the network. A local scan is useful, but an external scan from another machine is even better.

# Scan localhost:
nmap 127.0.0.1

# Scan the server IP:
nmap SERVER_IP

# Detect service versions:
nmap -sV SERVER_IP

# Scan all TCP ports:
nmap -p- SERVER_IP

Important: nmap shows open ports and detected services. It does not show which local PID owns the port. For PID and process name, use ss or lsof.

Example:

sudo ss -ltnp ‘sport = :22’
sudo lsof -nP -iTCP:22 -sTCP:LISTEN

10. Understand port ranges correctly

Ports 1-1023 are privileged / well-known ports. Services such as SSH, HTTP, HTTPS, DNS and SMTP often use this range.
Ports 1024-49151 are registered ports.
Ports 49152-65535 are the IANA dynamic/private port range.

Linux also has its own local ephemeral port range for outgoing connections. Check it with:

cat /proc/sys/net/ipv4/ip_local_port_range

A common Linux default is: 32768 60999

Do not simply assume that all ports below 32768 are incoming and all ports above 32768 are outgoing. Direction depends on the connection and firewall rules.

Monitoring & Intrusion

Fail2ban, Logs & Services

11. Protection against SSH brute-force attacks

For SSH brute-force protection, use Fail2ban or SSHGuard. DenyHosts exists, but Fail2ban is more commonly used today and can protect more services, not only SSH.

# Install Fail2ban on Debian/Ubuntu:
sudo apt install fail2ban

# Install Fail2ban on Fedora/RHEL/Rocky/AlmaLinux:
sudo dnf install fail2ban

Create a local SSH jail:

sudo nano /etc/fail2ban/jail.d/sshd.local

Example:

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
findtime = 10m
bantime = 1h

If your SSH still uses the default port 22, set: port = 22

Start, enable and check status:

sudo systemctl enable –now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

12. Check system logs

View failed SSH login attempts:

sudo journalctl -u ssh
sudo journalctl -u sshd

On Debian/Ubuntu, authentication logs may also be here:

sudo grep “Failed password” /var/log/auth.log

On RHEL/Fedora-like systems:

sudo grep “Failed password” /var/log/secure

13. Disable services you do not use

List running services:

systemctl –type=service –state=running

Disable an unnecessary service:

sudo systemctl disable –now SERVICE_NAME

Check which process owns a listening port before disabling anything: sudo ss -ltnup

Conclusion

14. Practical security baseline

A practical minimum baseline for an internet-facing Linux system:

  1. Keep the OS updated.
  2. Use a firewall and allow only required ports.
  3. Disable direct SSH root login.
  4. Use SSH keys instead of passwords.
  5. Disable SSH password login after testing key login.
  6. Use Fail2ban or SSHGuard against brute-force attempts.
  7. Disable unused services.
  8. Monitor open ports with ss and scan externally with nmap.
  9. Secure both IPv4 and IPv6, or disable IPv6 only if it is truly unused.
  10. Keep backups and test recovery.

Quick command summary

ip -br addr
ip route
sudo ss -ltnup
sudo ss -tnp state established
nmap -sV SERVER_IP
sudo nft list ruleset
sudo ufw status verbose
sudo firewall-cmd –list-all
sudo sshd -t
sudo systemctl restart sshd
sudo fail2ban-client status sshd
cat /proc/sys/net/ipv4/ip_local_port_range

In short: do not rely on one trick such as changing the SSH port or disabling IPv6. Real security comes from updates, correct SSH configuration, a strict firewall, minimal exposed services, login protection and regular monitoring.

Komentáře jsou uzavřeny.