random/docs/ssh.md

275 lines
9.5 KiB
Markdown

# SSH Security
> A full write-up on OpenSSH usage with security in mind.
---
## Table of Contents
* [Generating An SSH Key Pair](#generating-an-ssh-key-pair)
- [Linux](#linux)
- [Windows](#windows)
* [Getting Your Client To Use Your SSH Key](#getting-your-client-to-use-your-ssh-key)
- [Linux](#linux)
- [Windows](#windows)
* [Setup Server](#setup-server)
- [Harden OpenSSH Daemon](#harden-openssh-daemon)
- [Create A New User On The Server](#create-a-new-user-on-the-server)
- [Copy Your Public Key To Your Shell](#copy-your-public-key-to-your-shell)
* [Extra Security](#extra-security)
- [Allow Incoming SSH Connections Through IPTables](#allow-incoming-ssh-connections-through-iptables)
- [Lock Users In A Chroot Jail Environment](#lock-users-in-a-chroot-jail-environment)
- [Port Knocking](#port-knocking)
- [Setup Server](#setup-server-1)
- [Using IPTables](#using-iptables)
- [Using Knockd](#using-knockd)
- [Knocking Your Server](#knocking-your-server)
- [Using Nmap](#using-nmap)
- [Using knockd](#using-knockd-1)
- [Jump Hosts](#jump-hosts)
**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](https://the.earth.li/~sgtatham/putty/latest/w32/puttygen.exe).
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](https://the.earth.li/~sgtatham/putty/latest/w32/putty.exe) 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](https://github.com/acidvegas/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](http://www.zeroflux.org/projects/knock) 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](https://nmap.org/) package.
* `nano knock.sh`
```bash
#!/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](http://www.zeroflux.org/projects/knock) 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
* https://wiki.archlinux.org/index.php/Port_knocking
* https://wiki.archlinux.org/index.php/SSH_keys
* https://wiki.mozilla.org/Security/Guidelines/OpenSSH
* https://www.openssh.com/manual.html
* https://stribika.github.io/2015/01/04/secure-secure-shell.html