Advanced SSH Capabilities
Beyond basic remote access, SSH provides a powerful set of features for secure network tunneling, file transfer, and connection optimization. This guide covers:
- Port forwarding (local, remote, dynamic)
- File transfer with SCP and SFTP
- SSH multiplexing for performance
- Server hardening to reduce attack surface
- Troubleshooting and debugging
Tunneling and Port Forwarding
SSH port forwarding (also called SSH tunneling) allows you to securely route traffic for other protocols through an encrypted SSH connection. This is useful for:
- Accessing internal services through a firewall
- Encrypting otherwise cleartext protocols
- Bypassing network restrictions securely
Local Port Forwarding (-L)
Forward a local port through the SSH server to a remote destination. Traffic sent to the local port is forwarded through the SSH tunnel to the remote host.
ssh -L 8080:localhost:80 user@remote_host
# Explanation:
# -L 8080:localhost:80
# 8080 → local port on your machine
# localhost → destination from the SSH server's perspective
# 80 → destination port on the remote end
After running this, accessing http://localhost:8080 on your machine sends traffic through the SSH tunnel to port 80 on remote_host.
Use Case: Access a web server running on remote_host:80
locally via localhost:8080, even if port 80 is firewalled.
Your Machine:8080 --> SSH Tunnel --> remote_host:80
Remote Port Forwarding (-R)
Forward a port on the remote server back to your local machine. Allows the remote server to access a service running locally.
ssh -R 9090:localhost:22 user@remote_host
# Explanation:
# -R 9090:localhost:22
# 9090 → port opened on remote_host
# localhost → destination from your machine's perspective
# 22 → local port to forward to (SSH on your machine)
After running this, anyone connecting to remote_host:9090 is forwarded back to port 22 on your local machine.
Use Case: Allow remote_host to SSH back into your local machine
when your machine is behind NAT or a firewall.
remote_host:9090 --> SSH Tunnel --> YourMachine:22
Dynamic SOCKS Proxy (-D)
Create a SOCKS proxy server that routes traffic dynamically through the SSH connection. Works with any application that supports SOCKS5.
ssh -D 8080 user@remote_host
After running this, configure your browser or application to use localhost:8080 as a SOCKS5 proxy — all traffic routes through remote_host.
Use Case: Route web browsing through a remote server
to access geo-restricted content or bypass local network restrictions.
Application --> SOCKS5 localhost:8080 --> SSH Tunnel --> remote_host --> Internet
Copying Files with SCP
SCP (Secure Copy Protocol) transfers files securely over SSH. It uses the same authentication and encryption as SSH.
Copy File TO Remote Server
# Basic copy to remote
scp file.txt user@remote_host:/path/to/destination
# Copy with non-default SSH port
scp -P 2222 /local-files user@ip-address:remote-files
# Practical example
scp -P 2222 /opt/test user@192.168.1.100:~/Downloads
Copy File FROM Remote Server
# Copy file from remote to current local directory
scp user@remote_host:/path/to/file.txt .
# Copy directory recursively
scp -r user@remote_host:/remote/directory/ ./local-copy/
SCP Options
| Option | Description |
|---|---|
-P <port> | Specify non-default SSH port |
-r | Recursively copy directories |
-i <keyfile> | Use specific identity file |
-v | Verbose output for debugging |
-C | Enable compression |
Secure File Transfer with SFTP
SFTP (SSH File Transfer Protocol) provides an interactive file transfer session with a command-line interface similar to FTP, but fully encrypted.
# Connect to remote SFTP server
sftp user@remote_host
# Connect on a custom port
sftp -P 2222 user@remote_host
SFTP Interactive Commands
Once connected:
# Download a file from remote to local
get remote_file.txt
# Download entire directory
get -r remote_directory/
# Upload a local file to remote
put local_file.txt
# Upload entire directory
put -r local_directory/
# List remote directory contents
ls
# List local directory contents
lls
# Change remote directory
cd /path/on/remote
# Change local directory
lcd /path/on/local
# Create remote directory
mkdir new_directory
# Remove remote file
rm remote_file.txt
# Exit SFTP session
exit
SSH Multiplexing for Faster Connections
SSH multiplexing allows multiple SSH sessions to share a single TCP connection. This dramatically speeds up subsequent connections to the same host because the authentication handshake only happens once.
# Add to ~/.ssh/config
echo "
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 10m" >> ~/.ssh/config
Create the sockets directory:
mkdir -p ~/.ssh/sockets
With multiplexing:
First connection: full SSH handshake (normal speed)
Subsequent connections to same host: reuse socket (near-instant)
Useful for: deployment scripts, Ansible, git operations over SSH
SSH Escape Sequences
When connected to a remote host, SSH provides escape sequences for session control. The escape character is ~ (tilde) followed by a command:
| Sequence | Action |
|---|---|
~. | Kill a hung or unresponsive SSH session |
~^Z | Suspend the SSH session (send to background) |
~# | List forwarded connections |
~? | Display help for escape sequences |
The escape character only works when typed after a newline.
Securing the SSH Server
Change the Default SSH Port
Moving SSH off port 22 reduces exposure to automated scanners and brute-force bots that target the default port.
sudo nano /etc/ssh/sshd_config
# Find and change:
Port 22
# To:
Port 2222
sudo systemctl restart ssh
Disable Root Login
Never allow direct root SSH access. Require users to authenticate as a regular user and escalate with sudo:
# In /etc/ssh/sshd_config:
PermitRootLogin no
Restrict Which Users Can Connect
Limit SSH access to specific users:
# In /etc/ssh/sshd_config:
AllowUsers user1 user2
Disable Password Authentication
Once key-based authentication is configured and tested, disable password authentication to prevent brute-force attacks:
# In /etc/ssh/sshd_config:
PasswordAuthentication no
PubkeyAuthentication yes
Complete Hardened sshd_config Snippet
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers user1 user2
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
Using Fail2Ban to Prevent Brute-Force Attacks
Fail2Ban monitors SSH log files and automatically blocks IP addresses that show signs of brute-force attacks (multiple failed authentication attempts).
# Install Fail2Ban
sudo apt install fail2ban
# Enable and start the service
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Fail2Ban's default SSH jail monitors /var/log/auth.log and bans IPs with more than 5 failed attempts within 10 minutes for 10 minutes.
Troubleshooting SSH Issues
Checking SSH Logs
# View recent SSH log entries
journalctl -u ssh --no-pager | tail -n 20
# Watch SSH logs in real time
journalctl -u ssh -f
Common log messages and their meanings:
Accepted publickey for user— successful key authenticationFailed password for user— failed password attemptInvalid user admin— attempt to log in as a non-existent userConnection closed by authenticating user— connection dropped during auth
Debugging SSH Connection
# Maximum verbosity SSH connection debug
ssh -vvv user@remote_host
# Look for:
# "Offering public key:" → which keys are being offered
# "Authenticated to host" → successful auth
# "Permission denied" → auth failed
The three levels of -v progressively reveal more internal SSH negotiation detail:
-v— basic connection and authentication steps-vv— key exchange and cipher negotiation-vvv— full packet-level debugging
SSH Security Hardening Summary
Essential SSH Hardening Checklist:
├── Change default port from 22 to a high port
├── Disable root login (PermitRootLogin no)
├── Disable password authentication after setting up keys
├── Restrict access to specific users (AllowUsers)
├── Install and configure Fail2Ban
├── Set MaxAuthTries to 3
├── Use strong key types: Ed25519 or RSA-4096
├── Rotate SSH keys periodically
└── Monitor /var/log/auth.log for suspicious patterns