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 & theClientAliveInterval
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