Skip to content

Server Security

Security hardening guide for SSH servers used with StormTunnel.


Security Checklist

Essential (All Environments)

  • Disable root login
  • Use SSH keys instead of passwords
  • Enable detailed logging
  • Configure firewall rules
  • Keep OpenSSH updated

Production Environments

  • Disable password authentication
  • Implement 2FA
  • Use fail2ban
  • Restrict SSH access by IP
  • Enable audit logging

SSH Hardening

Production sshd_config

# Protocol and Encryption
Protocol 2
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group-exchange-sha256
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]

# Authentication
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no

# Access Control
AllowUsers tunneluser deployuser
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30

# Port Forwarding
AllowTcpForwarding local
GatewayPorts no
PermitOpen localhost:5432 localhost:3306 localhost:6379
PermitTunnel no

# Session
ClientAliveInterval 300
ClientAliveCountMax 2

# Logging
LogLevel VERBOSE
SyslogFacility AUTH

# Security
X11Forwarding no
AllowAgentForwarding no
StrictModes yes
IgnoreRhosts yes

Apply:

sudo sshd -t                    # Test
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
sudo systemctl restart sshd

Warning

Keep a terminal open until you verify access still works!


Firewall Configuration

iptables (CentOS/RHEL)

# Set defaults
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# Allow loopback and established
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow SSH from specific IP range
sudo iptables -A INPUT -p tcp --dport 22 -s 203.0.113.0/24 -j ACCEPT

# Rate limit SSH
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP

# Save
sudo iptables-save > /etc/iptables/rules.v4

ufw (Ubuntu)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 203.0.113.0/24 to any port 22
sudo ufw limit ssh
sudo ufw enable

AWS Security Groups

# Allow SSH from office IP only
OFFICE_IP="203.0.113.0/24"
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxxxxxx \
  --protocol tcp \
  --port 22 \
  --cidr $OFFICE_IP

Two-Factor Authentication

Google Authenticator Setup

Install:

# Ubuntu
sudo apt install libpam-google-authenticator -y

# CentOS
sudo yum install epel-release google-authenticator -y

Configure PAM (/etc/pam.d/sshd):

auth required pam_google_authenticator.so

Configure sshd (/etc/ssh/sshd_config):

ChallengeResponseAuthentication yes
PubkeyAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

Setup for user:

google-authenticator
# Scan QR code with authenticator app
# Save emergency codes

Restart SSH: sudo systemctl restart sshd


fail2ban

Install

# Ubuntu
sudo apt install fail2ban -y

# CentOS
sudo yum install epel-release fail2ban -y

Configure

Create /etc/fail2ban/jail.local:

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16

[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3

Start:

sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status sshd

Compliance

SOC 2

  • SSH key-only authentication
  • Comprehensive connection logging
  • Access controls with least privilege
  • Configuration in version control

HIPAA

  • Strong cipher suites only
  • 6-year log retention
  • Automatic session termination

PCI DSS

  • Multi-factor authentication for remote access
  • Key rotation every 90 days
  • Quarterly log reviews
  • Real-time alerting

Security Audit Script

#!/bin/bash
echo "SSH Security Audit - $(date)"

# Check config
sudo sshd -T | grep -E "passwordauthentication|permitrootlogin|pubkeyauthentication"

# Failed attempts today
echo "Failed attempts: $(sudo grep "Failed password" /var/log/auth.log | grep "$(date +%b\ %d)" | wc -l)"

# fail2ban status
sudo fail2ban-client status sshd 2>/dev/null || echo "fail2ban not configured"

Next Steps