Setting up a basic security baseline is essential for any public- or local-facing Linux server. This guide covers firewalls, SSH key authentication, Tailscale SSH, Fail2ban, and locking down SSH access.
1. Configure the Firewall (UFW) #
- install ufw
sudo apt update && sudo apt install -y ufw- enable ssh in firewall
# Allow SSH first to avoid locking yourself out
sudo ufw allow ssh
sudo ufw default deny incoming
sudo ufw default allow outgoing
# HTTP & HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Only if your application actually needs public access
# sudo ufw allow 8080/tcp
# Enable the firewall
sudo ufw enable
# Verify status
sudo ufw status verbose2. Restrict Access to the Local Subnet(optional) #
To limit specific administrative or internal services (e.g., custom web dashboards) to your local network, specify the IP subnet.
First, check your local subnet range:
Step 1: Identify Local Subnet
ip routeIt depends,local network in 192.168.0.0/24 and local ip address as 192.168.0.50. Like access web pedal of Pi-hole or AdGuard Home
# Allow local subnet access to port 8000
sudo ufw allow from 192.168.0.0/24 to any port 8000 proto tcp
# Reload UFW to apply rules
sudo ufw reload3. Set Up SSH Keys & Passwordless Login #
Using SSH keys instead of passwords significantly reduces the risk of brute-force attacks.
- Generate an SSH key pair:
ssh-keygen -t ed25519It is encourage to protect the private key with a passphrase.
1. Copy the public key to the server #
install ssh-copy-id and Copy the public key to the server:
ssh-copy-id username@192.168.0.50If ssh-copy-id is not available, create folder in remote device:
mkdir -p ~/.ssh && chmod 700 ~/.sshThen transmit to server via scp:
scp ~/ .ssh/ssh_ed25519.pub name@ip: ~/.ssh/authorized_keys
- Configure local SSH aliases (~/.ssh/config):
Host my-server
HostName ip-address
User username
IdentityFile ~/.ssh/ssh_ed25519Then can connect simply by typing: ssh my-server
2. Set Up Tailscale SSH (Optional) #
Tailscale SSH provides SSH access between devices on your tailnet without requiring you to manually distribute SSH public keys. Authentication and authorization are handled through Tailscale and its access-control policies.
Install Tailscale following the official installation instructions and create a tailscale account if needed.
Enable Tailscale SSH on the server:
sudo tailscale set --sshFor Tailscale SSH, use your tailnet’s access-control policies to determine which users and devices are allowed to connect to the server.
4. Create a non-root sudo user (optional) #
Create a regular administrative user. Replace example as username
sudo adduser example
sudo usermod -aG sudo exampleVerify the user premission:
groups exampleIt should display sudo users
5. Harden SSH Daemon Settings #
Once key authentication or tailsacle is working properly, disable root login and password-based access (optional).
Open the SSH daemon configuration file:
open ssh config setting
sudo nano /etc/ssh/sshd_configfind the line and modify to no (default is yes), or add at the bottom: Set the following parameters:
Set PermitRootLogin no to explicitly prevent SSH logins as root.
Set PasswordAuthentication no for disable password-based authentication (optional)
Verify the format:
sudo sshd -tIf there is no output, the configuration syntax is valid.
Then restart the SSH service:
sudo systemctl restart sshd6. Set up fail2ban (optional if disable password-based authentication) #
Fail2ban automatically blocks IP addresses that show malicious signs like too many password failures in service like sshd, FTP, and web server.
Installation and Setup
# Install Fail2ban
sudo apt update && sudo apt install -y fail2ban
# Create a local configuration copy
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# edit the local configuration
sudo nano /etc/fail2ban/jail.localEdit Configuration #
Open /etc/fail2ban/jail.local and add or modify the [sshd] section:
[sshd]
enabled = true # Activates protection for SSH
mode = aggressive # Catches failed password attempts, invalid users, and preauth failures.
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3 # ban an ip after 3 failed attempts.
findtime = 10m # Counts retries occurring within a 10-minute window.
bantime = 1h # Blocks the IP for 1 hourApply Changes and Monitor
# Restart Fail2ban
sudo systemctl restart fail2ban
# Check service status
sudo systemctl status fail2ban
# Monitor active jail statistics
sudo fail2ban-client status sshdAfter the configured number of failed attempts within the detection window, Fail2ban temporarily bans the source IP address. Depending on the firewall action and network conditions, subsequent connections may be refused or time out.
Tailscale SSH is a separate access path from traditional SSH exposed on the server’s network interface. Fail2ban protects the traditional SSH service by monitoring its authentication attempts; it should not be considered the mechanism that controls access through Tailscale SSH.