From 太極
Jump to navigation Jump to search


Best security practices

  • The Best Ways to Secure Your SSH Server
  • OpenSSH Security Hardening Guide for Linux
  • 3 ways I configure SSH for privacy Change the default port, No more passwords, Decide who can log in.
  • Top 20 OpenSSH Server Best Security Practices
    1. Use SSH public key based login
    2. Disable root user login
    3. Disable password based login
    4. Limit Users’ ssh access
    5. Disable Empty Passwords
    6. Use strong passwords and passphrase for ssh users/keys
    7. Firewall SSH TCP port # 22
    8. Change SSH Port and limit IP binding
    9. Use TCP wrappers (optional)
    10. Thwart SSH crackers/brute force attacks such as using fail2ban and DenyHosts software
    11. Rate-limit incoming traffic at TCP port # 22 (optional)
    12. Use port knocking (optional)
    13. Configure idle log out timeout interval
    14. Enable a warning banner for ssh users
    15. Disable .rhosts files (verification)
    16. Disable host-based authentication (verification)
    17. Patch OpenSSH and operating systems
    18. Chroot OpenSSH (Lock down users to their home directories)
    19. Disable OpenSSH server on client computer
    20. Bonus tips from Mozilla

Install OpenSSL

How to Install the latest OpenSSL version from Source on Linux

Install ssh client

sudo apt install openssh-client


How to open ssh port using ufw on Ubuntu/Debian Linux

sudo ufw allow ssh
# OR
sudo ufw allow 22/tcp

How to limit SSH connections with ufw

How to limit SSH (TCP port 22) connections with ufw on Ubuntu Linux

Configuration file ~/.ssh/config, avoid ssh connection timeout

Put the following in your ~/.ssh/config.

Host remotehost
  Port 4242
  User abcd
  IdentityFile "~/.ssh/id_rsa"
  ForwardX11 yes
  Compression yes
  TCPKeepAlive yes

    User YourUserName
    IdentityFile ~/.ssh/YourGithubSSHKey

After that we can run ssh remotehost.

To enable it for all hosts use:

Host *
  ServerAliveInterval 240

Also make sure to run chmod 600 ~/.ssh/config


We can put some host name /etc/hosts as a shortcut to some IP address. After that we can run something like ssh ShortCutName

Change to a different port

$ sudo nano /etc/ssh/sshd_config  # looking for the line containing port 
$ sudo service ssh restart # tested on Ubuntu 14.04

Remember to change the Router settings.

On the client PC, use ssh USERNAME@HOSTNAME -p NEWPORT for a connection.

For security reason, use the port < 1024 (privileged ports and can only be opened by root)

ProxyJump, DynamicForward

How to Manage an SSH Config File in Windows and Linux

Avahi Daemon/Bonjour/Zeroconf

sudo apt-get install avahi-daemon


  • Check the file /proc/sys/net/ipv6/conf/all/disable_ipv6 to see if it is zero (0 means ipv6 is enabled).
  • To query the ipv6 address on the server, the following command from the post How to get the IPv6 IP address in Linux only return one ipv6. Note the command ip -6 address or /sbin/ip -6 addr | grep inet6 will return too many ipv6 addresses.
    # Ubuntu 22.04 on x64
    ip -6 addr show scope global dynamic mngtmpaddr up|egrep -o '([0-9a-f:]+:+)+[0-9a-f]+'
    # Debian 12 on SBC
    ip -6 addr show scope global dynamic up|egrep -o '([0-9a-f:]+:+)+[0-9a-f]+'
  • My ipv6 address looks like fdeb:2506:de09:4441:6604:3326:db42:d815
  • Consecutive groups of zeros can be represented with a double colon (::). However, the double colon can only be used once in an address. This allows for shorter representations of address with long sequences of zeros. For example, 2001:0db8:0000:0000:0000:0000:0000:abcd can be written as 2001:0db8::abcd.
  • The full ipv6 has a form of
    • 128 bits,
    • 8 groups and each group represents 16 bits,
    • 32 digits where each digit actually represents four bits.

ssh alias

  • Using linux's alias; eg put the following inside ~/.bashrc or ~/.zshrc
alias sshnocheck='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' 
alias scpnocheck='scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
alias openports='sudo netstat -tulpn | grep LISTEN'
alias checkport='sudo lsof -i -P -n | grep LISTEN'

With this trick, ssh and scp (scp alias_name:Downloads/myfile .) work perfectly.

Modify ~/.ssh/config

Host *
  ServerAliveInterval 120
  ServerAliveCountMax 30

Host your-alias_name
  User username
  Port 50001
  IdentifyFile ~/.ssh/id_file
  ServiceAliveInterval 120

Host work
  User abcde
  ServiceAliveCountMax 5
  StrictHostKeyChecking yes

According to the man of ssh_config:

  • ServerAliveCountMax: Sets the number of server alive messages (see below) which may be sent without ssh(1) receiving any messages back from the server. If this threshold is reached while server alive messages are being sent, ssh will disconnect from the server, terminating the session.
  • ServerAliveInterval: Sets a timeout interval in seconds after which if no data has been received from the server, ssh(1) will send a message through the encrypted channel to request a response from the server. The default is 0, indicating that these messages will not be sent to the server.

Running commands on a remote host

ssh user@host 'COMMANDS'

ssh user@host "command1; command2; command3"

COMMANDS="command1; command2; command3"
ssh user@host "$COMMANDS"

A practical example



for IP in $IP_LIST;
  utime=$(ssh ${USER}@${IP} uptime  | awk '{ print $3 }' )
  echo $IP uptime:  $utime

How to Run a Local Shell Script on a Remote SSH Server

How to Run a Local Shell Script on a Remote SSH Server

Disable password log in

If we like to ask all users to use key-based to log in, we can modify the line

PasswordAuthentication no

in /etc/ssh/sshd_config and run sudo systemctl restart sshd.

Disable root log in

Modify /etc/ssh/sshd_config. Change this line:

#PermitRootLogin yes


PermitRootLogin no

and run /etc/init.d/sshd restart or sudo systemctl restart sshd. Also run sudo systemctl status sshd to check the status.

However, that line in my Ubuntu is

PermitRootLogin without-password

According to this post, “without-password” means password authentication is disabled for root.

ssh log files

It is also helpful to check /etc/hosts.allow and /etc/hosts.deny for any possible wrong configuration.

Note that auth.log can show ssh security attacks. Am I compromised?

$ grep sshd /var/log/auth.log
Feb 19 11:04:12 phenom sshd[16922]: Failed password for root from port 49383 ssh2
Feb 19 11:04:12 phenom sshd[16922]: Received disconnect from 11: Bye Bye [preauth]
Feb 19 11:04:14 phenom sshd[16924]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=  user=root

Feb 19 11:04:36 phenom sshd[16998]: Invalid user enea from
Feb 19 11:04:36 phenom sshd[16998]: input_userauth_request: invalid user enea [preauth]
Feb 19 11:04:37 phenom sshd[16998]: pam_unix(sshd:auth): check pass; user unknown
Feb 19 11:04:37 phenom sshd[16998]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost= 
Feb 19 11:04:39 phenom sshd[16998]: Failed password for invalid user enea from port 36090 ssh2
Feb 19 11:04:39 phenom sshd[16998]: Connection closed by [preauth]
Feb 19 11:05:11 phenom sshd[17060]: refused connect from (
Feb 19 11:05:55 phenom sshd[17353]: refused connect from (
Feb 19 11:06:38 phenom sshd[17732]: refused connect from (
Feb 19 11:07:20 phenom sshd[17850]: refused connect from (
Feb 19 11:07:40 phenom sshd[17874]: refused connect from (
Feb 19 11:08:01 phenom sshd[17955]: refused connect from (
Feb 19 11:08:41 phenom sshd[18118]: refused connect from (
Feb 19 11:09:22 phenom sshd[18280]: refused connect from (
Feb 19 11:10:02 phenom sshd[18353]: Invalid user support from
Feb 19 11:10:02 phenom sshd[18353]: input_userauth_request: invalid user support [preauth]
Feb 19 11:10:02 phenom sshd[18353]: pam_unix(sshd:auth): check pass; user unknown
Feb 19 11:10:02 phenom sshd[18353]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost= 
Feb 19 11:10:03 phenom sshd[18424]: refused connect from (
Feb 19 11:10:04 phenom sshd[18353]: Failed password for invalid user support from port 54218 ssh2
Feb 19 11:10:05 phenom sshd[18353]: fatal: Read from socket failed: Connection reset by peer [preauth]
Feb 19 11:10:07 phenom sshd[18425]: Did not receive identification string from
Feb 19 11:10:17 phenom sshd[18443]: Address maps to, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!

How to List Unsuccessful SSH Logins on Linux

How to List Unsuccessful SSH Logins on Linux

grep "Failed password" /var/log/auth.log
# OR
journalctl _SYSTEMD_UNIT=ssh.service | egrep "Failed|Failure"


Note that denyhosts package is no longer available in Ubuntu 14.04, 16.04 now. We can install install from its source DenyHosts-2.6.tar.gz.

Procedures: follow the README.txt file.


# Check the status
$ /etc/init.d/fail2ban status 

$ sudo fail2ban-client status

# show banned IPs
$ sudo fail2ban-client status sshd

Status for the jail: sshd
|- Filter
|  |- Currently failed:	4
|  |- Total failed:	10
|  `- File list:	/var/log/auth.log
`- Actions
   |- Currently banned:	3
   |- Total banned:	3
   `- Banned IP list:

# manually unban an IP:
fail2ban-client set <JAIL-NAME> unbanip <IP-ADDRESS>
fail2ban-client set sshd unbanip <IP-ADDRESS>

# manually ban an IP:
fail2ban-client set <JAIL-NAME> banip <IP-ADDRESS>

# Another way to list banned IPs
sudo iptables -L -n

# Real-time Monitor 
sudo tail -f /var/log/fail2ban.log

Log in history: last command

The following command also shows how long a user has been logged in.

last <username> | less

w/who can show who (and when) are currently logging in.

Generate a strong password

5 Ways To Generate A Random/Strong Password In Linux Terminal: pwgen, openssl, gpg, mkpasswd, makepasswd, ...

Put in your ~/.bashrc. See Top 20 OpenSSH Server Best Security Practices.

$ genpasswd() {
	local l=$1
       	[ "$l" == "" ] && l=20
      	tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs
$ genpasswd 16

login banners/messages

  • How to Disable SSH Welcome Message on Ubuntu
    • /etc/ssh/sshd_config
    • /etc/update-motd.d/
  • There are two types of banners you can configure. Banner message to display before user log in (configure in file of your choice eg. /etc/login.warn) Banner message to display after user successfully logged in (configure in /etc/motd)
  • Where does the System Information information come from on login by SSH?
    sudo run-parts /etc/update-motd.d/
  • Example on my xu4 running armbian. Each binaries under /etc/update-motd.d/ was used.
    $ ssh [email protected]
      ___      _           _     _  __  ___   _ _  _   
     / _ \  __| |_ __ ___ (_) __| | \ \/ / | | | || |  
    | | | |/ _` | '__/ _ \| |/ _` |  \  /| | | | || |_ 
    | |_| | (_| | | | (_) | | (_| |  /  \| |_| |__   _|
     \___/ \__,_|_|  \___/|_|\__,_| /_/\_\\___/   |_|  
    Welcome to Armbian 23.05.0-trunk Bullseye with Linux 5.4.239-odroidxu4
    No end-user support: built from trunk
    System load:   1%           	Up time:       21 days 11:24	
    Memory usage:  10% of 1.94G  	IP:
    CPU temp:      43°C           	Usage of /:    9% of 15G    	
    storage/:      46% of 458G   	storage temp:  26°C           	
    Tip of the day: Armbian is leading investor into software for custom ARM based hardware
    [ 0 security updates available, 48 updates total: apt upgrade ]
    Last check: 2023-10-15 00:00
    $ ls /etc/update-motd.d/
    10-armbian-header   35-armbian-tips     41-armbian-config           quotes.txt
    30-armbian-sysinfo  40-armbian-updates  98-armbian-autoreboot-warn

Double dash

What Does ‐‐ (double dash) Mean In SSH Shell Command?

ssh -A: forwarding of the authentication agent connection

Two-factor authentication

X11 forwarding

  • How to Run Graphical X Apps Over SSH in Linux. You'll have to enable X11 forwarding on the remote server. /etc/ssh/sshd_config file.
  • Mac connect to Linux
    • On Mac Mojave 10.14.6 (client side), I need to use -Y option (Enables trusted X11 forwarding) because "-X" does not work. The answer was found when I use "-v" option in ssh.
    • The 'ForwardX11' option in ~/ssh/config file does not help.
    • When I connect to my Linux machine, I can use display XXXX.png command to show the remote png file locally (display is part of imagemagick pack).
  • Linux connect to Linux does not have a problem.

Bypass SSH password login (convenient for CVS, git etc)

  1. ssh-keygen -t rsa
  2. (make sure the remote server has .ssh directory)
  3. cat ~/.ssh/ | ssh user@hostname 'cat >> .ssh/authorized_keys'
  4. ssh user@hostname

It helps with CVS log in too when the CVS works by using ssh protocol. Note that step 3 allows to run a shell command at a remote machine.

See also for similar instruction when work on github.

The ssh key can be copied to another a machine (pay attention to mode). Or let the new machine to create its own key pair and use ssh-copy-id to append the identity file to remote machine's ~/.ssh/authorized_keys file. See

We can even have multiple ssh key on local machine by using <.ssh/config> file. See

Allow for a user

How to Enable/Disable SSH access for a particular user or user group in Linux


-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory Fix

SSH file server

How to create a personal file server with SSH on Linux

SSHFS: mount a remote file system over ssh

From my testing, files in local and remote machines are automatically synchronized. Convenient and dangerous.

# Remote: only need to make sure openssh-server is installed

# Local
sudo apt install sshfs
mkdir /local/dir
sshfs user@ip:/remote/dir  /local/dir
# Unmount
fusermount -u /local/dir

To make this more practical, make sure /etc/fstab is modified appropriately and the ssh key is copied to the remote server.

sudo nano /etc/fstab
sshfs#[email protected]:/remote/dir /local/dir
sudo nano /etc/fuse.conf # uncomment user_allow_other

sudo mkdir /media/roms
sudo chown -R $USER:$USER /media/roms
sshfs user@ip:/remote/roms /media/roms -o idmap=user,ro,allow_other

SSH server on Windows 10


Enhancing SSH Login With A Tmux Session Selection Menu In Linux

xpipe - remote connection hub

ssh key

SSH key is useful if you want a password-less login to a remote system. Some useful resources:

Also there are different kinds of keys (see for example <~/.ssh/known_hosts file>): RSA, DSA and ECDSA (newer). They're keys generated using different encryption algorithms. See SSH key-type, rsa, dsa, ecdsa, are there easy answers for which to choose when?

The steps are

  • Check if there is an existing key
ls -al ~/.ssh
  • Create a new RSA key pair:
ssh-keygen -t rsa
ssh-keygen -f ~/.ssh/personalid -C "bitbucket"

where the comment 'bitbucket' will appear at the end of <~/.ssh/personalid> file.

  • Copy the public key to a remote host ([email protected]) over ssh. The current user (eg brb) and the remote user (eg git)have not any relationship (they most likely have different user names):
ssh-copy-id -i ~/.ssh/ [email protected] # this will 'append' the key to the remote-host’s .ssh/authorized_key.

Or (may not work:()

cat ~/.ssh/ | ssh [email protected] "mkdir -p ~/.ssh && cat >>  ~/.ssh/authorized_keys"
  • Delete the authorized key. Open the text file '.ssh/authorized_keys' and remove the offending lines.
  • Test if this is working by trying 'ssh [email protected]'.
  • To disable the password for root login. Type sudo nano /etc/ssh/sshd_config
PermitRootLogin without-password

Then run the following to put the changes into effect:

reload ssh
# Or service ssh restart

Default key file

Force SSH Client To Use Given Private Key ( identity file )

The default is ~/.ssh/identity for protocol version 1, and ~/.ssh/id_rsa and ~/.ssh/id_dsa for protocol version 2.

Multiple ssh keys and ssh-add; ssh-agent

<Method 1> If we want to use a specific key in ssh, use

ssh -i ~/.ssh/xxx_id_rsa [email protected]

<Method 2> Another way is to use ssh-add & ssh-agent to manager your keys. ssh-agent keeps your key in its memory and pulls it up whenever it is asked for it.

<Method 3> <~/.ssh/config> file.

Windows OS

Set up SSH public key authentication in WinSCP.

  • Use PuTTYgen to generate an rsa key.
  • We only need to save the private key since PuTTYgen can load a private key (right click the key file and choose Edit with PuTTYgen) and show the public key value.
  • The public key text box shown at the top of the PuTTYgen window is what we should copy to the server's ./ssh/authorized_keys file as instructed by the dialog.
  • NOTE: the "Key comment" part does not affect the authentication. It is located at the end of the public key. It's helpful to change that to more meaningful words.

ssh key management

Copy ssh keys to another computer

# Copy
$ ssh-copy-id -p 22 -i ~/.ssh/ [email protected]

# Test
$ ssh -p 22 -i ~/.ssh/MyKey [email protected]

$ chown brb:brb ~/.ssh/id_rsa*
$ chmod 600 ~/.ssh/id_rsa
$ chmod 644 ~/.ssh/

If we do not change the permission correctly in <id_rsa>, we will get a warning: Unprotected private key file. Permissions 0664 for '/home/USERNAME/.ssh/id_rsa' are too open.

Preserve ssh keys when upgrading computers

ls -l /etc/ssh/*key* > ~/key_list  # optional
mkdir ~/serverkeys && sudo cp -p /etc/ssh/*key* ~/serverkeys/ # back up, -p will preserve mode, ownership and timestamps
sudo cp -p ~/serverkeys/*key* /etc/ssh  # copy back
ls -l /etc/ssh/*key* | diff - ~/key_list # optional

If diff produces no output, you're finished.

Pay attention to the permissions. All the /etc/ssh/* files should be owned by root:root, with 644 permissions except for those that end in *key, which should be 600.

udooer@udoo:~$ ls -l /etc/ssh/*key*
total 32
-rw------- 1 root root  668 Dec  8 14:43 ssh_host_dsa_key
-rw-r--r-- 1 root root  599 Dec  8 14:43
-rw------- 1 root root  227 Dec  8 14:43 ssh_host_ecdsa_key
-rw-r--r-- 1 root root  171 Dec  8 14:43
-rw------- 1 root root  399 Dec  8 14:43 ssh_host_ed25519_key
-rw-r--r-- 1 root root   91 Dec  8 14:43
-rw------- 1 root root 1679 Dec  8 14:43 ssh_host_rsa_key
-rw-r--r-- 1 root root  391 Dec  8 14:43

udooer@udoo:~$ cd /etc/ssh; sudo tar -czvf ~/Downloads/sshkeys.tar.gz *key*
-rw------- root/root       668 2017-12-08 14:43 ssh_host_dsa_key
-rw-r--r-- root/root       599 2017-12-08 14:43
-rw------- root/root       227 2017-12-08 14:43 ssh_host_ecdsa_key
-rw-r--r-- root/root       171 2017-12-08 14:43
-rw------- root/root       399 2017-12-08 14:43 ssh_host_ed25519_key
-rw-r--r-- root/root        91 2017-12-08 14:43
-rw------- root/root      1679 2017-12-08 14:43 ssh_host_rsa_key
-rw-r--r-- root/root       391 2017-12-08 14:43

udooer@udoo:~/$ cd /etc/ssh; sudo tar -xzvf ~/Downloads/sshkeys.tar.gz  

Disable SSH host key checking

ssh -o UserKnownHostsFile=/dev/null \
    -o StrictHostKeyChecking=no \

To disable the checking for all hosts, in your ~/.ssh/config (if this file doesn't exist, just create it):

Host *
    StrictHostKeyChecking no

Or for certain domains

Host * 
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null
  User foo
  LogLevel QUIET

Handling the ssh key change when connecting to a remote machine

An article from

  • Method 1. Remove the key using ssh-keygen -R command.
$ ssh-keygen -R {}
$ ssh-keygen -R {ssh.server.ip.address}
$ ssh-keygen -R
$ ssh-keygen -f "/home/$USERNAME/.ssh/known_hosts" -R ""
  • Method 2. Add correct host key in /home/user/.ssh/known_hosts
  • Method 3. Just delete the known_hosts file If you have only used one ssh server
  • Method 4. Use ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no method. See Alias or Disable SSH host key checking.

What is tunnel A tunnel provides a direct path that avoids some type of complexity you would otherwise have to deal with.

Cloudflare tunnel

See here.


Tested it on Slax

First we install openssh server on slax so we can remote access it and copy/paste commands.

apt install openssh-server
systemctl start sshd.service
passwd # change root password


apt update
apt install curl wireguard

touch newfile
python3 -m http.server # Serving http on port 8000 (

# open a new terminal/tab
curl > tunnel.conf && wg-quick up ./tunnel.conf
# access on https://<unique_slug>

# To stop your tunnel
wg-quick down ./tunnel.conf

tailscale VPN

SSH Port forwarding

Verizon Quantum Gateway Router

User guide p98. Click 'Advanced' button first.

  • Source port: Any (this is the key)
  • Destination Ports: the port you want to use (connect from outside)
  • Forward to Port: Same as incoming port or the port used in the local computer

'L'ocal port forwarding: view a certain port web page on a remote domain locally

This port forwarding involves three computers (local, remote/application server, host/secure shell server). If the remote is the same as the host, it will be reduced to involving 2 computers.

For example, we like to access home's router ( information from an outsider computer. Suppose the host 'hostname' is one computer in the home network and it can be accessed from outside world.

Another example is if we want to use Jupyter running on a remote machine from local browser.

# ssh -L localPort:remoteIP:remotePort username@hostname
ssh -L 8080: username@hostname
ssh -L 8080:localhost:80 username@hostname   # access http://hostname:80 using http://localhost:8080
ssh -i someKey.pem -L 443: username@hostname

The -L option specifies local port forwarding. In this case, port 8080 on the local machine was forwarded to port 80 on the remote machine. For the duration of the SSH session, pointing your browser at http://localhost:8080/ would send you to as if you are in the same local network of 'hostname'. We can try other ports like 1234 instead of 8080; it can be anything above 1024.

The reason it works is because the 'ssh' trick. In addition to being able to make yourself in the home network environment, the traffic on http://localhost:8080 is encrypted too.

Note that this forwarding uses port 8080 on the client rather than port 80. Binding to port 80 would require using root privileges every time we SSH.

To stop the ssh session, use ps -ef to find the process id and kill it.

Remote port forwarding (Reverse port forwarding)

This is most useful in situations where you have a machine which isn't publicly accessible from the internet, but you want others to be able to access a service on this machine. In this case, if you have SSH access to a remote machine which is publicly accessible on the internet, you can set up a reverse port forward on that remote machine to the local machine which is running the service.

ssh -R 8000:localhost:80 user@REMOTE_MACHINE

This will forward port 8000 on the remote machine to port 80 on the local machine. Using this method, if you browse to http://localhost on the remote machine, you will actually connected to a web server running on port 8000 of the local machine.

Example 2: Suppose you have two machine

  • machine A (userA): under firewall. cannot be directly accessed (like corporate machines)
  • machine B (userB): local machine (like home machines)

Our goal is to access machine A directly from machine B.

We can run the following on the machine A

# ssh -R remoteIP:remoteport:localIP:localport hostname
# ssh -R remoteport:localIP:localport hostname
ssh -R 2222:localhost:22 userB@machineB_IP
ssh -i /path/to/priv/key/id_rsa -f -N -R 2222:localhost:22 userB@machineB_IP

Then we can access machine A from machine B by

ssh -p 2222 userA@localhost

If you want remote port forwarding configured every time you connect to a host, use the RemoteForward option in ssh_config .

LocalForward server-IP:server-port client-IP:client-port

'D'ynamic port forwarding, SOCKS proxy, bypass blocked websites from work computer

ssh -D 4096 user@remoteip
ssh -D 4096 -p 23 user@remoteip

ssh -D 4096 -p 23 -f -N -q -C user@remoteip

This will require you to enter the password and leave you in the remote machine. If a nonstandard port is required, we can use -p option. -f is to fork process into background, -N means don't open a shell, -q means quiet and -C means compress data sent through tunnel. In order to close the connection, you need to find the process ID and kill it manually. You can use other port like 1080 (or something like 4321 which is also easy to remember too).

Now in the firefox, we need to go to Edit -> Preferences -> Advanced -> Network tab -> Settings... Check 'Manual proxy configuration' (The default is 'Use system proxy settings') and enter 'localhost' for SOCKS (SOCKS5 by default) Host and '4096' for the Port. Don't enter 'localhost' in the HTTP Proxy. Also check the option Proxy DNS when using SOCKS v5; otherwise someone on the network can see which site you are trying to get to even they are unable to see what you are seeing.

Open and search my ip to check if the change works.

Note that in addition to the Firefox, we can use

  • Chrome or chromium
  • SeaMonkey (seems better than Firefox since the form works better on 1024x600 resolution).
  • Brave browser does not support proxy

On Windows, we can use Putty. In short, in the left-hand panel, navigate through Connection > SSH > Tunnels. Enter 4096 in the Source Port box and select the Dynamic radio button. Click Add and “D4096″ will appear in the Forwarded Ports list. The setting in the firefox end is the same. See also my Windows wiki page.

Linux journal also put a video on youtube. We can use to check the current location. The port number is 1080 in the example. The example actually also use '-N' option which means no interaction; i.e. ssh -N -D 1080 user@remoteip. So we won't see anything after we type our password. Once we want to stop SOCK proxy, we just need to hit Ctr+C on terminal.

Backgrounding OpenSSH Forwarding

Use the -N flag to tell ssh to not run anything, including a terminal, on the remote server, and the -f flag to tell ssh to go into the background on the client.

ssh -fNL 2222:localhost:22 user@remotehost &

By backgrounding this command, you get your original terminal back.

tunnel a ssh connection through an intermediate server

Simple method is (-t means Force tty/pseudo-terminal allocation).

$ ssh -t user1@domain1 ssh user2@domain2

Another method is to use ssh ProxyCommand to tunnel connections.

A third method is to

$ ssh -L 9999:host2:22 user1@host1  # leave this terminal 
# open a new terminal tab
$ ssh -p 9999 user2@localhost


file path with spaces (parentheses)

Use double quotes around the full path and a backslash to escape any space.

scp [email protected]:"web/tmp/Master\ File\ 18\ 10\ 13.xls" .

Use the 'Tab' key to get the full path used by Linux.

$ cd Calibre\ Library/calibre/Calibre-2\ days\ \(582\)/
$ exit
~/Downloads$ scp "taichimd:~/Calibre\ Library/calibre/Calibre-2\ days\ \(582\)/*.mobi" .

# Use the path we understand does not work
~/Downloads$ scp "taichimd:~/Calibre Library/calibre/Calibre-2 days (582)/*.mobi" .
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `scp -f ~/Calibre Library/calibre/Calibre-2 days (582)/*.mobi'


You either need quotes, or a backslash before the star, but not both. And scp is not the one expanding it, the shell is. See How to use wildcards (*) when copying with scp?

scp [email protected]:/abc/def/*.txt .   # no matches found:
scp [email protected]:/abc/def/\*.txt .

# macOS
scp 'helix:/data/xxx/file_*.rda' .

Copy multiple files

scp or sftp copy multiple files with single command

From local to remote: use space character.

scp foo.txt bar.txt your_username@domain:

From remote to local: use escaped parentheses and comma sign.

scp your_username@domain:~/\{foo.txt,bar.txt\} .

Some uses double quotes around the files with the space character to separate files but it does not work when I try to copy files from remote(biowulf) to local(mac).

Recursive copying

Use -r parameter.

Preserve permissions and modes

Use -p parameter.

Disable SSH host key checking

See here. scp is supposed to take the same command line options as ssh. Add the following options to the scp command.

-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null

scp files through one intermediate host

The following command is tested.

scp -o 'ProxyCommand ssh user@remote1 nc %h %p' user@remote2:path/to/file .

A second method which is useful for ssh and scp commands

$ ssh -L 9999:host2:22 user1@host1 # leave the terminal
# Open a new terminal
$ scp -P 9999 fileName user2@localhost:/path/to/dest/fileName   # transfer from local to remote. Note: Upper P.
$ scp -P 9999 user2@localhost:/path/to/source/fileName fileName # transfer from remote to local. Note: Upper P.
# If we only want to use ssh
$ ssh -p 9999 user2@localhost # Note: lower p.

scp with non-standard port: -P (capital)

Use -P argument.

scp -P 23 myfile user@remoteip:

scp without a password

Assume the ssh key has been copied to the remote computer

scp -p -P 22 -i ~/.ssh/MyKey [email protected]:MyFile .


  1. Verify that local-host and remote-host is running openSSH (ssh -V)
  2. Generate key-pair on the local-host using ssh-keygen (Enter a passphrase here, do not leave it empty. A passphrase should be at least several words long, something you can easily remember. It's a bad idea to use a single word as a passphrase.)
  3. Install public key on the remote-host
  4. Give appropriate permission to the .ssh directory on the remote-host (chmod 755 ~/.ssh; chmod 644 ~/.ssh/authorized_keys)
  5. Login from the local-host to remote-host using the SSH key authentication to verify whether it works properly
  6. Start the SSH Agent on local-host to perform ssh and scp without having to enter the passphrase several times (ssh-agent $SHELL)
  7. Load the private key to the SSH agent on the local-host (ssh-add, need to enter the passphrase 1 time only)
  8. Perform SSH or SCP to remote-home from local-host without entering the password. It works for all remote machines containing the key from local-local.

Another option is to use ssh -i IDENTITY_FILE. See

ssh with password on the command line: sshpass

Rsync does use your ssh config

SCP user’s migration guide to rsync.

Some advantages of rsync over scp:

  • In-flight compression
  • Delta transfers
  • Syncing