All notes



Use man sshd_config for help. sshd config is a very good article on this topic.

Logging: LogLevel, SyslogFacility

LogLevel. The possible values are: QUIET, FATAL, ERROR, INFO (default), VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. Logging with a DEBUG level violates the privacy of users and is not recommended.

SyslogFacility. Gives the facility code that is used when logging messages from sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default isAUTH.

DenyUsers, AllowUsers

DenyUsers user1 user2 user3
DenyGroups group1 group2

AllowUsers user1 user2
AllowGroups group1 group2

Reload conf

After editing your sshd_config file, you will need to reload your SSH server's configuration - restarting the SSH daemon is not necessary:

sudo service sshd reload

Don't lock yourself out of your SSH server

When experimenting with these access controls, it's a good idea to always have two SSH sessions into the server, and to always make backup of the relevant configuration files. If you log out of one session and get denied access, you still have one active session to fix things.


Host hawkhost
	User     me
	IdentityFile /Users/me/.ssh/me.private


ServerAliveInterval 是SSH层的,数据加密状态传输,不会被简单规则过滤。更多参数说明可以参考 man ssh_config.

ssh_config 里还有个参数 TCPKeepAlive,默认false,可以改为yes。TCPKeepAlive是靠发送空的ACK包来保持连接,由可能在特定情况下无效(被防火墙过滤)。

The following exampl. ServerAliveCountMax 5 (默认是3),解释是:10秒钟发送一次心跳,如果连续5次都没有响应,客户端就断开连接。

Host * 
  SendEnv LANG LC_*
  ServerAliveCountMax 5
  ServerAliveInterval 10


Anchor. The concept is very simple — rather than each new SSH connection to a particular server opening up a new TCP connection, you instead multiplex all of your SSH connections down one TCP connection. The authentication only happens once, when the TCP connection is opened, and thereafter all your extra SSH sessions are sent down that connection.

Host *
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%[email protected]%h:%p
# Then mkdir ~/.ssh/cm_socket, and you're away.

# Setting up a dedicated master connection
ssh -MNn [email protected]

# If you need to disable control master for a given connection
ssh -S none [email protected]



For security concern, we usually set ChallengeResponseAuthentication to "no". If you want to fully disable password-based authentication, set BOTH PasswordAuthentication and ChallengeResponseAuthentication to "no".

Usual Commands


-v	Verbose mode. Causes ssh to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple -v options increase the verbosity. The maximum is 3.
 -M	Places the ssh client into ``master'' mode for connection sharing. Multiple -M options places ssh into ``master'' mode with confirmation required before slave connections are accepted.
 -N	Do not execute a remote command.  This is useful for just
forwarding ports (protocol version 2 only).
 -n	Redirects stdin from /dev/null (actually, prevents reading from stdin).  This must be used when ssh is run in the background.  A common trick is to use this to run X11 programs on a remote machine.  For example, ssh -n emacs & will start an emacs on, and the X11 connection will be automatically forwarded over an encrypted channel.  The ssh program will be put in the background.  (This does not work if ssh needs to ask for a password or passphrase; see also the -f option.)
 -S ctl_path:	 Specifies the location of a control socket for connection sharing, or the string ``none'' to disable connection sharing. Refer to the description of ControlPath and ControlMaster in ssh_config(5) for details.
-T      Disable pseudo-tty allocation.
-t      Force pseudo-tty allocation.

The Amazon AWS allows only the key-pair authentication, so if I log in with ssh -l [email protected], I got the error "permission denied (pulickey)" instead of the password prompt.

ssh -v [email protected] # Output debug info so you could know why you cannot login.
man ssh_config # Check this manual for config options.

# ssh onto remote and execute command.
ssh [email protected] "ls"

The authorized_keys must be 644.

Proxy ssh proxy.

ssh -L 8080:localhost:80 [email protected] -p 443 

ssh -ND 8080 [email protected] -p 443

ssh-copy-id ssh-copy-id.

ssh-copy-id [-i [identity_file]] [[email protected]]machine


What contents are added to remote?


# -C: Compression enabled.
# -p: Preserves modification times, access times, and modes from the original file.
# -q: Quiet.
scp -Cpqr srcFile destPath

# Copy multiple files from remote to current local directory.
scp [email protected]:~/\{abc.log,cde.txt\} .


# -p: requests changing the passphrase.
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]

# -b bits: Specifies the number of bits in the key to create.
ssh-keygen -t rsa -b 2048

# Export pub key from private.
# -y: This option will read a private OpenSSH format file and print an OpenSSH public key to stdout.
# -e: Read a private or public OpenSSH key file and print the key in RFC 4716 SSH Public Key File Format to stdout.
ssh-keygen -y [-f input_keyfile]

Bits. For RSA keys, the minimum size is 768 bits and the default is 2048 bits. Generally, 2048 bits is considered sufficient. DSA keys must be exactly 1024 bits as specified by FIPS 186-2.


ssh-keyscan is a utility for gathering the public ssh host keys of a number of hosts. It was designed to aid in building and verifying ssh_known_hosts files.

ssh-keyscan -t rsa > ~/.ssh/known_hosts

ssh-agent, ssh-add

Instead of removing passphrase, consider using ssh-agent, which can cache the passphrase for a time.


ssh-agent [-c | -s] [-d] [-a bind_address] [-t life] [command [arg ...]]
ssh-agent [-c | -s] -k


ssh-agent bash
ssh-add ~/.ssh/myPrivateKey
# Enter passphrase, then bingo!

# Set timeout to 4 hours. Default is forever/no expire.
ssh-agent -t 4h
# The timeout of ssh-add overrides that of ssh-agent, per key.
ssh-add -t 4h

# Displays the identities currently held by the agent.
ssh-add -l
# List all identities
ssh-add -L


A unix-domain socket is created and the name of this socket is stored in the SSH_AUTH_SOCK environment variable.
The socket is made accessible only to the current user. This method is easily abused by root or another instance of the same user.
See pitfalls of ssh-agents for details and good practices, e.g. never ever copy your private keys or run an ssh-agent on a computer somebody else has root on.


Reverse Tunneling How to access a Linux server behind NAT via reverse SSH tunnel.

For this, you will need another host (relayServer) outside with a public IP address (e.g. IP Then set up a persistent SSH tunnel from the server (homeServer) in your home network to the public relay host. With that, you can connect back to the home server from the relay host (which is why it’s called a “reverse” tunnel).

# On homeServer, open an SSH connection to relayServer:
# It forwards traffic on port 10022 of relayServer to port 22 of homeServer.
# -f: Requests ssh to go to background just before command execution.
# -N: Do not execute a remote command.
# -T: disables pseudo-tty allocation, which is appropriate because you're not trying to create an interactive shell.
# -vvv: for debugging.
ssh -fNT -R 10022:localhost:22 relayserver_user @

# On relayServer, is bound to sshd.
sudo netstat -nap | grep 10022
# tcp      0    0*               LISTEN      8493/sshd

# Log in to relayserver. Then access homeServer as follows.
ssh -p 10022 homeserver_user @ localhost

# The end point of an SSH tunnel on relayserver is binding to loopback address ( To make it to

vi /etc/ssh/sshd_conf
# Add: GatewayPorts clientspecified
# Restart sshd.

# initiate a reverse SSH tunnel from homeserver:
ssh -fN -R :localhost: 22 relayserver_user @
# Log in to relayServer and confirm with netstat command:
sudo netstat -nap | grep 10022
# tcp      0      0*           LISTEN      1538/sshd: dev
# Gain access to NATed homeserver from anywhere.
ssh -p 10022 homeserver_user @

# Use autossh to make persistent connection:
# On homeServer:
# -M: a monitoring port.
autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 10022 :localhost: 22 relayserver_user @

# Kill autossh
pkill -9 autossh


debug1: key_load_public: No such file or directory

The line above is not error, but just simple debug log saying that ssh client is not able to find separate public key (named ~/.ssh/ This file is not needed to connect to the remote server, but it can be useful.

Error: no kex algo

SO: ssh prompts no kex alg.

wcfNote: the ssh client is too old. Use bitvise ssh client on Windows instead.

People recommends to edit the sshd_config and add:

KexAlgorithms diffie-hellman-group1-sha1

ssh login by identity file fails

Log in to server and see /var/log/secure. I found:

sshd[25561]: Authentication refused: bad ownership or modes for directory /home/me

chmod 755 /home/me solved the problem.

ssh slow

ssh -vv shows

debug1: Authentications that can continue: publickey,gssapi-with-mic,password
debug1: Next authentication method: gssapi-with-mic
(wcfNote: This is where ssh -vv holds for long)
debug1: Unspecified GSS failure.  Minor code may provide more information
Cannot determine realm for numeric host address

Solution: in your client host, edit /etc/ssh/ssh_config, and comment out lines begin with "GSSAPIAuthentication yes".

SSH can input username and password, but can't login even with no error info in server log

If the client IP is, and the server IP is, it is usually network route problem. Try to modify the netmask from 24 to 23:

sudo route add -net netmask dev eth0
sudo route del -net netmask dev eth0

Resume / continue download file with scp


rsync --partial --progress --rsh=ssh [email protected]:~/ .