Troubleshooting 'Git SSH connection closed by foreign host Port 22 fatal protocol'
Resolve 'Git SSH connection closed by foreign host Port 22 fatal protocol' errors. A deep dive into SSH key issues, firewall blocks, and server configurations.
When interacting with a remote Git repository over SSH, encountering the error “SSH connection closed by foreign host Port 22 fatal protocol” can be a frustrating experience. This issue indicates that the remote server abruptly terminated the SSH connection before the Git protocol negotiation could successfully complete. Unlike simple authentication failures, this error suggests a more fundamental problem at the network or SSH daemon level on the server, rather than an incorrect Git command or repository issue.
Symptom & Error Signature
Users typically encounter this error when attempting to clone, push, pull, or fetch from a Git repository via SSH. The exact output might vary slightly but will consistently mention the connection being closed by the foreign host, often followed by a fatal protocol error.
$ git push origin main
fatal: write error: Connection reset by peer
Connection closed by foreign host.
fatal: The remote end hung up unexpectedly
fatal: protocol error: bad line length character
Another common manifestation:
$ git clone [email protected]:user/repo.git
ssh_exchange_identification: Connection closed by remote host
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Root Cause Analysis
The “connection closed by foreign host” message points directly to the remote server terminating the connection. This can be due to various underlying reasons:
- SSH Key Misconfiguration: This is the most frequent culprit. The server might reject your key due to incorrect permissions, the wrong key being presented, the key not being registered in
authorized_keys, or issues with thessh-agent. - Server-Side Firewall Restrictions: The server’s firewall (e.g., UFW, iptables, or cloud security groups) might be blocking inbound connections on port 22 from your client’s IP address, or from specific geographic regions.
- SSH Daemon (sshd) Issues:
- The
sshdservice might not be running or could have crashed. sshd_configparameters likeMaxAuthTriesmight be exceeded, orAllowUsers/DenyUsersdirectives might be preventing your connection.- There might be
Matchblocks insshd_configapplying specific restrictions.
- The
- Host-Based Access Control: Legacy
hosts.alloworhosts.denyfiles could be blocking your IP. - Network Instability or Interference: Intermittent network connectivity, aggressive network proxies, or VPNs can sometimes lead to abrupt connection terminations.
- Server Resource Exhaustion: If the remote server is severely overloaded (CPU, memory, disk I/O) or has run out of disk space, the
sshdprocess might fail to handle new connections or existing ones, leading to premature closure. - SSH Protocol Negotiation Failure: While rare with modern systems, significant version mismatches between the client and server’s SSH implementations could lead to negotiation failures.
Step-by-Step Resolution
Troubleshooting this error requires a methodical approach, starting with basic connectivity checks and progressing to deeper SSH and server configuration diagnostics.
1. Verify Basic Network Connectivity & SSH Daemon Status
First, confirm that your client can reach the server and that the SSH daemon is operational on the remote host.
# From your local machine:
# Test basic reachability (replace your-repo.com with the actual hostname or IP)
ping -c 4 your-repo.com
# Test if port 22 is open and listening
telnet your-repo.com 22
# Expected output: Trying X.X.X.X... Connected to your-repo.com. Escape character is '^]'.
# If you see "Connection refused" or "No route to host", it's a network/firewall issue.
If telnet fails, it strongly suggests a network or firewall block. If it connects, the issue is likely at a higher layer.
On the remote server (if you have alternative access like a console or a different SSH key):
# Check if the SSH daemon is running
sudo systemctl status sshd
# Review SSH daemon logs for recent connection attempts and errors
# For systemd-based systems (Ubuntu 22.04 LTS):
sudo journalctl -u sshd -n 50 --no-pager
# For older systems or more direct log viewing:
sudo tail -f /var/log/auth.log | grep -i "ssh"
[!IMPORTANT] The
journalctlorauth.logoutput is crucial. Look for entries related to your IP address attempting to connect, and any messages indicating authentication failures, connection resets, or daemon issues.
2. Diagnose SSH Client-Side Configuration
Incorrect client-side SSH configuration or key management is a very common cause.
# From your local machine:
# Run SSH in verbose mode to see the connection process in detail
ssh -vT [email protected]
# Replace 'git' with the actual username if it's not 'git'.
# Look for "Authenticating with public key..." lines to see which keys are being tried.
# Also, look for "debug1: read_passphrase: can't open /dev/tty: No such file or directory" if a key needs a passphrase.
# List loaded SSH keys in your ssh-agent
ssh-add -l
# If your key is not listed, add it to the agent
ssh-add ~/.ssh/id_rsa_yourkey # Replace with your actual private key path
# Check permissions for your SSH keys and config directory
ls -la ~/.ssh/
# Expected permissions:
# ~/.ssh directory: drwx------ (700)
# Private keys (id_rsa, id_ed25519, etc.): -rw------- (600)
# Public keys (id_rsa.pub): -rw-r--r-- (644)
# config file: -rw------- (600) or -rw-r--r-- (644)
# Correct permissions if needed
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa # Or your specific private key file
[!WARNING] Incorrect permissions on your
~/.sshdirectory or private key files will causesshto silently ignore the keys for security reasons, leading to authentication failures or connection drops.
If you use a ~/.ssh/config file, ensure it’s correctly configured:
# Example ~/.ssh/config entry
Host your-repo.com
Hostname your-repo.com
User git
IdentityFile ~/.ssh/id_rsa_my_repo_key
IdentitiesOnly yes # Ensures only specified keys are tried
3. Inspect Server-Side SSH Configuration and Permissions
If client-side settings are fine, the problem likely lies on the server. You’ll need access to the server via console, a different SSH key, or a rescue mode.
On the remote server:
# Check permissions for the user's home directory and .ssh directory (e.g., for user 'git')
ls -lad /home/git
ls -lad /home/git/.ssh
ls -la /home/git/.ssh/authorized_keys
# Expected permissions for user 'git' (or the user you're connecting as):
# /home/git: drwxr-xr-x (755) or drwx------ (700)
# /home/git/.ssh: drwx------ (700)
# /home/git/.ssh/authorized_keys: -rw------- (600)
# Correct permissions if necessary (replace 'git' with your actual user)
sudo chmod 700 /home/git/.ssh
sudo chmod 600 /home/git/.ssh/authorized_keys
sudo chown -R git:git /home/git/.ssh # Ensure ownership matches the user
# Verify the public key is correctly installed in authorized_keys
# Ensure your public key (from your local machine's ~/.ssh/id_rsa_yourkey.pub) is present.
cat /home/git/.ssh/authorized_keys
Next, review the main SSH daemon configuration:
sudo cat /etc/ssh/sshd_config | grep -E "PermitRootLogin|PasswordAuthentication|MaxAuthTries|AllowUsers|DenyUsers|AllowGroups|DenyGroups"
Look for settings that might be too restrictive:
PermitRootLogin no: If you’re trying to connect asroot.PasswordAuthentication no: If you’re relying on password-based authentication.MaxAuthTries X: If you’ve tried too many times with incorrect keys/passwords.AllowUsers,DenyUsers,AllowGroups,DenyGroups: Ensure your user/group is explicitly allowed or not explicitly denied.Matchblocks: Look forMatch User,Match Address, etc., directives which can apply specific configurations to certain connections.
If you make any changes to /etc/ssh/sshd_config, you must restart the SSH daemon:
sudo systemctl restart sshd
[!IMPORTANT] Always be cautious when editing
sshd_config. Make sure you have alternative access (e.g., console, different SSH key) before restartingsshdif you are unsure of your changes. A syntax error can lock you out.
4. Check Server-Side Firewall Rules
A firewall blocking port 22 is a very common reason for “Connection closed by foreign host”.
For UFW (Uncomplicated Firewall) on Ubuntu/Debian:
sudo ufw status verbose
If UFW is enabled, ensure ssh or port 22/tcp is allowed:
sudo ufw allow ssh # Allows SSH connections on the default port (22)
# OR
sudo ufw allow 22/tcp # Explicitly allows TCP port 22
sudo ufw reload # Apply changes
For IPTables:
sudo iptables -L -n
Look for rules in the INPUT chain that might block TCP port 22. If you see a REJECT or DROP rule without a preceding ACCEPT rule for port 22, that’s likely the issue.
Cloud Provider Security Groups/Network ACLs:
If your server is hosted on a cloud platform (AWS EC2, Google Cloud, Azure, DigitalOcean, etc.), check the associated security groups, network ACLs, or firewall rules. Ensure that inbound TCP port 22 is allowed from your client’s IP address range (or 0.0.0.0/0 for testing, though less secure).
[!WARNING] While allowing
0.0.0.0/0for port 22 might resolve the issue, it exposes your server to the entire internet. For production environments, restrict SSH access to specific trusted IP addresses or IP ranges.
5. Review Host-Based Access Control and sshd_config Restrictions
Beyond general firewall rules, some systems use more granular access controls.
# Check for hosts.allow and hosts.deny files
cat /etc/hosts.allow
cat /etc/hosts.deny
These files might explicitly allow or deny SSH access based on IP addresses. Ensure your IP is not denied and potentially explicitly allowed if a hosts.deny rule is broad.
Also, revisit the /etc/ssh/sshd_config for specific Match blocks that could be causing the issue:
sudo grep -i "Match" /etc/ssh/sshd_config -A 5
These blocks can override global settings for specific users, groups, or IP addresses.
6. Examine Server Resources
A severely overloaded server can cause unexpected connection drops.
On the remote server:
top # Or htop, to view CPU and memory usage
free -h # Check available memory
df -h # Check disk space
If any resources (CPU, RAM, disk I/O) are consistently at 90%+ utilization, or disk space is full, it could be interfering with sshd’s ability to maintain connections. Address resource bottlenecks if found.
By systematically working through these steps, you should be able to identify and resolve the underlying cause of the “Git SSH connection closed by foreign host Port 22 fatal protocol” error. Remember that the verbose SSH output and server-side logs are your best friends in pinpointing the exact failure point.
