The Connection refused error on port 22 usually happens because your ISP placed you behind a Carrier-Grade NAT, making traditional port forwarding completely useless. Bypassing this restriction requires a strict diagnosis of your home network to decide whether you need a dynamic DNS setup or a zero-configuration mesh VPN.
- Default Port: 22 (Requires an immediate change to a custom port like 2222)
- Windows Requirement: Windows 10 (version 1709) or newer
- Linux Requirement:
openssh-serverpackage - Key Algorithm: Ed25519 (Faster and more secure than RSA)
- Remote Access Methods: Port Forwarding (Static IP/DDNS) or Mesh VPN (Tailscale)
SSH Server Decision Tree: Port Forwarding vs. Tailscale
If your ISP provides a real public IP, standard port forwarding with a Dynamic DNS works perfectly. You control the entire traffic flow. If your router status page shows a WAN IP starting with 10.x.x.x or 100.x.x.x, you are behind a CGNAT. Tailscale bypasses this entirely without touching a single router setting.
Step 1: Installing OpenSSH on Your Local Machine
Ubuntu/Debian Setup (Linux)
Open your terminal and run sudo apt update && sudo apt install openssh-server. The background service starts automatically right after the installation. Check its current status with sudo systemctl status ssh. The terminal output shows active (running) if everything went well.
Windows Native OpenSSH Setup (And the administrators_authorized_keys Trap)
Windows 10 and 11 include a native OpenSSH server directly in the system. Open PowerShell as Administrator and run Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0. Start the service with Start-Service sshd and make it persistent across reboots using Set-Service -Name sshd -StartupType 'Automatic'.
Here is the biggest trap for Windows users: If your Windows account is an Administrator, the SSH server completely ignores the standard ~/.ssh/authorized_keys file. You must place your public key in C:\ProgramData\ssh\administrators_authorized_keys. You also need to set the strict NTFS permissions exactly to SYSTEM and Administrators, manually removing all other users from the properties tab.
Running Windows VMs alongside your SSH server? If you use Hyper-V on Windows 11, each VM gets its own SSH config and authorized_keys file; the CGNAT and administrators_authorized_keys rules apply inside VMs too.
Step 2: Hardening Security and Key-Based Authentication
Generating and Copying SSH Keys
Never rely on passwords for remote access. Run ssh-keygen -t ed25519 -C "your_email@example.com" on your client machine. The Ed25519 algorithm provides better performance and stronger security against modern brute-force attempts. Use ssh-copy-id username@target_ip to push the newly generated key directly to your Linux server.
Disabling Root Login and Password Authentication
Open /etc/ssh/sshd_config on Linux or C:\ProgramData\ssh\sshd_config on Windows using your preferred text editor. Find the line #PasswordAuthentication yes and change it to PasswordAuthentication no. Do the exact same thing for PermitRootLogin no. Restart the SSH service immediately to apply these critical security rules.
Step 3: Beating Dynamic IPs and Carrier-Grade NAT
Setting up DDNS (DuckDNS / ddclient)
Home IPs change frequently after modem reboots. Register a free domain on DuckDNS and install ddclient on your Linux machine. This small background service pings DuckDNS every five minutes, keeping your custom domain seamlessly tied to your current home IP address.
Port Forwarding Basics on a Home Router
Log into your home router interface, typically located at 192.168.1.1 or 192.168.0.1. Navigate to the NAT or Port Forwarding section. Create a new rule pointing external port 2222 to internal port 22 of your server's local IP address. Exposing the default port 22 directly to the internet invites thousands of automated bot attacks every single day.
The Tailscale Alternative (Zero Router Config)
Install Tailscale on both your client laptop and your home server. It automatically assigns a static 100.x.x.x IP address to your server machine. You connect using ssh username@100.x.x.x from anywhere in the world. The connection feels instantaneous, and your router ports remain completely closed to the outside world.
Step 4: Adding Fail2Ban for Brute Force Protection
If you expose a port, malicious bots will scan it. Install Fail2Ban with sudo apt install fail2ban on your Linux server. It actively monitors your authentication logs and automatically drops IP addresses at the firewall level after five failed login attempts. The default ban time is 10 minutes, but you can easily increase it to 24 hours in the /etc/fail2ban/jail.local configuration file.
SSH Troubleshooting: Decoding Connection Errors
Connection refused vs Connection timed out vs Permission denied
Connection refused: The server is reachable, but the SSH service is down or a local firewall (like UFW on Linux or Windows Defender) is actively blocking the specific port. If the service is running but you still get refused, check what process is holding port 22 with ss -tlnp | grep :22.
Connection timed out: Your packets are dropping somewhere before they reach the target machine. This almost always means your router port forwarding rule is incorrect or your ISP is actively blocking the port at their network level.
Permission denied (publickey): The server sees you, but explicitly rejects your cryptographic credentials. Double-check your administrators_authorized_keys permissions on Windows or ensure your private key matches the target user on the remote machine.
Bonus: Using \~/.ssh/config for Quick Access Aliases
Stop typing long connection strings every time you want to log in. Create a simple text file at ~/.ssh/config on your client machine. Add a block specifying the HostName, User, and Port under a short alias like Host home-pc. Next time, just type ssh home-pc and hit enter.
Comments (0)
Sign in to comment
Report