Every Linux VPS ships with kernel defaults designed for compatibility, not security. Tuning sysctl parameters, hardening SSH, disabling unused kernel modules, and configuring network-level protections adds meaningful defence-in-depth to your Hong Kong VPS — blocking entire categories of attacks before they reach your application layer.
Step 1: Core Sysctl Security Parameters
cat > /etc/sysctl.d/99-security.conf << 'EOF'
# =====================================================================
# NETWORK SECURITY
# =====================================================================
# Disable IP source routing (prevents source-routed packet attacks)
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# Disable ICMP redirect acceptance (prevents MITM via redirects)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
# Don't send ICMP redirects (we're not a router)
net.ipv4.conf.all.send_redirects = 0
# Enable reverse path filtering (prevent IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Disable IPv4 forwarding (unless you run WireGuard/VPN — set to 1 then)
net.ipv4.ip_forward = 0
# Enable SYN cookies (prevent SYN flood attacks)
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
# Ignore ICMP broadcast requests (Smurf attack prevention)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Ignore bogus ICMP error responses
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Log martian packets (packets with impossible source addresses)
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# Disable IPv6 if not needed (reduce attack surface)
# Comment these out if you use IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
# =====================================================================
# TCP PERFORMANCE + SECURITY
# =====================================================================
# Increase TCP connection queue
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 1440000
# Reuse TIME_WAIT sockets more aggressively
net.ipv4.tcp_tw_reuse = 1
# TCP keepalive settings
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 3
# Reduce TIME_WAIT duration
net.ipv4.tcp_fin_timeout = 30
# =====================================================================
# KERNEL SECURITY
# =====================================================================
# Restrict dmesg access to root only
kernel.dmesg_restrict = 1
# Restrict kernel pointers in /proc (prevents info leaks)
kernel.kptr_restrict = 2
# Disable kernel core dumps from setuid programs
fs.suid_dumpable = 0
# Randomise virtual address space (ASLR)
kernel.randomize_va_space = 2
# Restrict ptrace (prevents process memory inspection by unprivileged users)
kernel.yama.ptrace_scope = 1
# =====================================================================
# FILE SYSTEM SECURITY
# =====================================================================
# Protect hardlinks and symlinks
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
# =====================================================================
# SHARED MEMORY
# =====================================================================
# Restrict shared memory access
kernel.shm_rmid_forced = 1
EOF
# Apply immediately
sysctl -p /etc/sysctl.d/99-security.conf
# Verify
sysctl net.ipv4.tcp_syncookies
sysctl kernel.randomize_va_spaceStep 2: SSH Hardening
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
cat > /etc/ssh/sshd_config << 'EOF' # Port — change from default 22 to reduce scan noise Port 22222 # Only listen on IPv4 (or add ::1 for IPv6) ListenAddress 0.0.0.0 # Authentication — keys only, no passwords PermitRootLogin prohibit-password PasswordAuthentication no PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys # Disable weak/unused auth methods PermitEmptyPasswords no ChallengeResponseAuthentication no KerberosAuthentication no GSSAPIAuthentication no # Strict mode — check file permissions on keys StrictModes yes # Timeout settings LoginGraceTime 30 MaxAuthTries 3 MaxSessions 10 # Disconnect idle sessions after 15 minutes ClientAliveInterval 300 ClientAliveCountMax 3 # Disable X11 and agent forwarding unless needed X11Forwarding no AllowAgentForwarding no AllowTcpForwarding no # Set to yes if you use SSH tunnels # Restrict to specific users (uncomment and set) # AllowUsers yourusername deploy # Use strong algorithms only KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com # Log level LogLevel VERBOSE SyslogFacility AUTH # Banner (optional — deters casual scanners) Banner /etc/ssh/banner EOF echo "Unauthorized access prohibited. All sessions are logged." > /etc/ssh/banner
# Validate config before reloading
sshd -t && systemctl reload sshd
# IMPORTANT: Test SSH on new port BEFORE closing current session
# Open a NEW terminal: ssh -p 22222 user@YOUR_VPS_IP
# Confirm it works, THEN update your firewall<code"># Update firewall for new SSH port ufw allow 22222/tcp ufw delete allow 22/tcp # Only after confirming new port works! ufw reload
Step 3: Disable Unused Kernel Modules
<code">cat > /etc/modprobe.d/blacklist-security.conf << 'EOF' # Disable uncommon/unused filesystems blacklist cramfs blacklist freevxfs blacklist jffs2 blacklist hfs blacklist hfsplus blacklist squashfs blacklist udf # Disable uncommon network protocols blacklist dccp blacklist sctp blacklist rds blacklist tipc # Disable USB storage (if server has no USB drives — uncomment if applicable) # blacklist usb-storage # Disable Firewire (not needed on VPS) blacklist firewire-core blacklist firewire-ohci # Disable rare network drivers blacklist atm blacklist can blacklist n_hdlc EOF # Apply immediately for mod in cramfs freevxfs jffs2 hfs hfsplus squashfs udf dccp sctp rds tipc; do rmmod $mod 2>/dev/null || true done
Step 4: UFW Firewall Rules
<code"># Explicit firewall policy — deny everything by default ufw default deny incoming ufw default allow outgoing ufw default deny forward # Allow only required services ufw allow 22222/tcp # SSH (your custom port) ufw allow 80/tcp # HTTP ufw allow 443/tcp # HTTPS # Rate limit SSH to prevent brute force ufw limit 22222/tcp comment 'Rate limit SSH' # Allow specific service ports only if running them # ufw allow 51820/udp # WireGuard # ufw allow 25/tcp # SMTP (only if mail server) # Enable with verbose output ufw enable ufw status verbose
Step 5: auditd — Kernel-Level Security Audit Logging
<code">apt install -y auditd audispd-plugins cat > /etc/audit/rules.d/security.rules << 'EOF' # Log all authentication events -w /var/log/auth.log -p wa -k auth_log -w /etc/passwd -p wa -k user_change -w /etc/shadow -p wa -k user_change -w /etc/group -p wa -k user_change -w /etc/sudoers -p wa -k sudo_change # Log SSH key changes -w /root/.ssh -p wa -k ssh_keys -w /home -p wa -k home_ssh # Log privileged command execution -a always,exit -F arch=b64 -S execve -F euid=0 -k root_commands # Log network configuration changes -w /etc/hosts -p wa -k hosts_change -w /etc/network -p wa -k network_change # Log cron changes (attackers often add persistence via cron) -w /etc/cron.d -p wa -k cron_change -w /etc/crontab -p wa -k cron_change -w /var/spool/cron -p wa -k cron_change EOF systemctl enable --now auditd auditctl -l # Verify rules are loaded # Query recent audit events ausearch -k user_change --start today ausearch -k root_commands --start today | tail -20
Step 6: Automatic Security Updates
<code">apt install -y unattended-upgrades
cat > /etc/apt/apt.conf.d/50unattended-upgrades << 'EOF' Unattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}-security"; }; Unattended-Upgrade::AutoFixInterruptedDpkg "true"; Unattended-Upgrade::MinimalSteps "true"; Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Automatic-Reboot "false"; // Set true for auto-reboot after kernel updates Unattended-Upgrade::Mail "admin@yourdomain.com"; EOF cat > /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
EOF
systemctl enable --now unattended-upgradesStep 7: Hardening Verification Checklist
<code"># Run this verification script monthly echo "=== Security Hardening Status ===" echo "[$(sysctl -n net.ipv4.tcp_syncookies) == 1] SYN cookies" echo "[$(sysctl -n kernel.randomize_va_space) == 2] ASLR" echo "[$(sysctl -n fs.protected_symlinks) == 1] Symlink protection" echo "[$(sysctl -n kernel.dmesg_restrict) == 1] dmesg restricted" echo "" echo "SSH status:" sshd -T 2>/dev/null | grep -E "passwordauthentication|permitrootlogin|port" echo "" echo "UFW status:" ufw status | head -20 echo "" echo "Listening services:" ss -tlnp | grep LISTEN echo "" echo "Automated updates:" systemctl is-active unattended-upgrades
Conclusion
Linux kernel hardening via sysctl on your Hong Kong VPS blocks entire attack categories at the OS level — SYN floods, IP spoofing, ICMP redirects, and kernel information leaks — before any application-level defense can act. Combined with SSH key-only authentication, a minimal firewall policy, and automatic security updates, this configuration represents the security baseline every production VPS should meet.
Secure your server: Browse Server.HK Hong Kong VPS plans — apply this hardening checklist immediately after provisioning any new VPS, before deploying application services.