random/docs/ssh.md

9.5 KiB

SSH Security

A full write-up on OpenSSH usage with security in mind.


Table of Contents

Note: The port 65150 is used in this write-up as an example of how to use a non-standard ports.


Generating An SSH Key Pair

Linux

Generate a key using the Ed25519 algorithm with 500 KDF rounds:

  • ssh-keygen -t ed25519 -a 500 -C "$(whoami)@$(hostname)-$(date -I)"

This will generate 2 files in your ~/.ssh directory. A public key (.pub) and a private key.

You only need to backup your private key. Public keys can be regenerated from the private key:

  • ssh-keygen -y -f ~/.ssh/acidvegas@pi-2017-01-01

Copy your public key to clipboard:

  • cat ~/.ssh/acidvegas@pi-2017-01-01.pub

Windows

Download & run puttygen.

Once opened, change the key type to ED25519 under the Parameters box, and then click the Generate button.

Click the Save private key button to save your key.

You only need to backup your private key. Public keys can be regenerated by clicking File -> Load private key.

Copy the data in the box labeled Public key for pasting into OpenSSH authorized_keys file.

Getting Your Client To Use Your SSH Key

Linux

  • ssh -p 65150 -i ~/.ssh/acidvegas@pi-2017-01-01 acidvegas@192.168.1.10

or...

  • nano ~/.ssh/config
Host acidbox
	HostName 192.168.1.10
	Port 65150
	User acidvegas
	IdentityFile ~/.ssh/acidvegas@pi-2017-01-01
	IdentitiesOnly yes
  • chmod 600 ~/.ssh/config
  • Usage: ssh acidbox

Windows

Download & run the putty client.

Once opened, select Connection -> SSH -> Auth from the Category box. Click the Browse button and select your private key.

Select Session from the Category box. Change the Host Name (or IP address) and Port to your server.

Name the session in Saved Sessions box and click the Save button.

SSH into your server by clicking your saved session from the Saved Sessions box, and clicking the Open button.


Setup Server

Harden OpenSSH Daemon

  • nano /etc/ssh/sshd_config
AddressFamily any
AllowAgentForwarding no
AllowGroups ssh
AllowTcpForwarding no
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
#Banner /etc/issue
ChallengeResponseAuthentication no
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
ClientAliveInterval 0
#ClientAliveCountMax 0
HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
LoginGraceTime 30
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
MaxAuthTries 2
MaxSessions 1
MaxStartups 3:50:10
PasswordAuthentication no
PermitRootLogin no
Port 65150
PrintLastLog no
PrintMotd no
Protocol 2
  • mkdir /etc/ssh/authorized_keys
  • rm /etc/ssh/ssh_host_*_key
  • ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

Options:

  • The AddressFamily option can be:
    • inet for IPv4 only.
    • inet6 for IPv6 only.
    • any for both.
  • The AuthorizedKeysFile option can be commented out to use the standard ~/.ssh/authorized_keys file instead.
  • The Banner option can be un-commented if the /etc/issue file exists. This is shown before the user authenticates.
  • The ClientAliveCountMax option can be un-commented & the ClientAliveInterval option can be changed to 1800 to enforce a 15 minute idle timeout.
  • The MaxSessions option can be increased if there are additional users on the server.
  • The Port option should be set to a non-standard port (High-value port number recommended).
  • The PrintMotd option can be changed to yes if the file /etc/motd exists. This is shown after the user authenticates.

Create A New User On The Server

Create a new user on the server with a password:

  • useradd -m -s /bin/bash acidvegas
  • passwd acidvegas

Create an ssh group and add your user to the group.

  • groupadd ssh
  • gpasswd -a acidvegas ssh

Copy Your Public Key To Your Shell

  • nano /etc/ssh/authorized_keys/acidvegas (Paste your public key data in this file)

Note: This is only required if you are using the AuthorizedKeysFile /etc/ssh/authorized_keys/%u line in your sshd_config file. For using the standard ~/.ssh/authorized_keys file, do the follow:

  • mkdir ~/.ssh
  • chmod 700 ~/.ssh
  • chown -R $USER ~/.ssh
  • nano ~/.ssh/authorized_keys (Paste the copied public key data into this file)
  • chmod 400 ~/.ssh/authorized_keys
  • Optionally, you can pass the immutable flag to prevent changes:
    • chattr +i ~/.ssh
    • chattr +i ~/.ssh/authorized_keys

Extra Security

Allow Incoming SSH Connections Through IPTables

iptables -A INPUT  -i eth0 -p tcp --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 65150 -m conntrack --ctstate ESTABLISHED     -j ACCEPT

You can also allow only incomming connection from a specific IP address instead by changing the first line above to:

iptables -A INPUT -i eth0 -p tcp -s 192.168.1.99 --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Lock Users In A Chroot Jail Environment

See mkchroot repository for details.

Port Knocking

The following is an example which uses the port knocking sequence 8881 -> 7777 -> 9991 to open port 65150 for 30 seconds.

Server
Using IPTables
  • nano /etc/iptables/iptables.rules
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TRAFFIC - [0:0]
:SSH-INPUT - [0:0]
:SSH-INPUTTWO - [0:0]
# TRAFFIC chain for Port Knocking. The correct port sequence in this example is  8881 -> 7777 -> 9991; any other sequence will drop the traffic 
-A INPUT -j TRAFFIC
-A TRAFFIC -p icmp --icmp-type any -j ACCEPT
-A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 65150 -m recent --rcheck --seconds 30 --name SSH2 -j ACCEPT
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 9991 -m recent --rcheck --name SSH1 -j SSH-INPUTTWO
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 7777 -m recent --rcheck --name SSH0 -j SSH-INPUT
-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP
-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 8881 -m recent --name SSH0 --set -j DROP
-A SSH-INPUT -m recent --name SSH1 --set -j DROP
-A SSH-INPUTTWO -m recent --name SSH2 --set -j DROP 
-A TRAFFIC -j DROP
COMMIT
  • systemctl daemon-reload
  • systemctl restart iptables
Using Knockd

Download & install the knockd package.

  • nano /etc/knockd.conf
[options]
	logfile = /var/log/knockd.log
[opencloseSSH]
	sequence      = 8881:tcp,7777:tcp,9991:tcp
	seq_timeout   = 5
	tcpflags      = syn,ack
	start_command = /usr/bin/iptables -A TCP -s %IP% -p tcp --dport 65150 -j ACCEPT
	cmd_timeout   = 10
	stop_command  = /usr/bin/iptables -D TCP -s %IP% -p tcp --dport 65150 -j ACCEPT

Knocking Your Server

Using Nmap

Download & install the nmap package.

  • nano knock.sh
#!/bin/bash
HOST=$1
shift
for ARG in "$@"
do
	nmap -Pn --host_timeout 100 --max-retries 0 -p $ARG $HOST
done
  • Usage: sh knock.sh example.server.com 8881 7777 9991
Using Knockd

Download & install the knockd package.

  • knock -v example.server.com 8881:tcp 7777:tcp 9991:tcp

Jump Hosts

  • ssh -J <jumphost> <host>

The <jumphost> option can be user@host, user@host:port or an host setup in your ~/.ssh/config.

Multiple jump hosts can be used in a comma (no spaces) separated list.

The same applies for the <host> option, except to change the port, either use the -p <port> option at the end or use a host setup in your ~/.ssh/config.

or...

  • nano ~/.ssh/config:
Host jumpbox
    HostName jump.server.com

Host targetbox
	...
    ProxyJump jumpbox1
	...

Multiple jump hosts can be used in the ProxyJump option in a comma (no spaces) separated list.

Connect to your target host with ssh targetbox


Sources