commit e85e85158a61c21aba0810830b127e7136e0764c
parent 0c22bfede59ae0a5080a55287627303a960c42be
Author: pyratebeard <root@pyratebeard.net>
Date: Fri, 15 Dec 2023 00:49:39 +0000
respect_my_authoritah
Diffstat:
1 file changed, 88 insertions(+), 29 deletions(-)
diff --git a/entry/respect_my_authoritah.md b/entry/respect_my_authoritah.md
@@ -1,25 +1,84 @@
-* hostca server
- * multiple, some offline
-* sign all existing system pub keys
-* new servers get pub key signed during commisson
- * "commisson" ssh key with force-command on hostca
-* userca server
-* add cert to pgp key
+I enjoy trying to improve security in the environments I manage as a sysadmin. One of the hardest parts of improving security is not making it a hindrance to users. (There is a fine line between good security and hindrance, but that's a rant for another time).
-* create host ca keys
+Recently I had been asked to improve the SSH security in an environment. SSH keys weren't really being used, so that was my first suggestion, but I needed to make key management as simple as possible without forgoing any security benefits; so I decided to take a proper look at [SSH Certificate Authorities](TK){target="_blank" rel="noreferrer"} (CA).
+
+I've known about SSH CA for a while, though never played around with it. Before taking it to into a production environment I decided to become familiar on my own turf.
+
+There are two types of SSH CA, Host and User.
+
+### gracious host
+Lets look at the Host side first. When you install OpenSSH on a system a number of host keys are generated
+```
+/etc/ssh/ssh_host_dsa_key
+/etc/ssh/ssh_host_dsa_key.pub
+/etc/ssh/ssh_host_ecdsa_key
+/etc/ssh/ssh_host_ecdsa_key.pub
+/etc/ssh/ssh_host_ed25519_key
+/etc/ssh/ssh_host_ed25519_key.pub
+/etc/ssh/ssh_host_rsa_key
+/etc/ssh/ssh_host_rsa_key.pub
+```
+
+When you first SSH to a server you are presented with a message that looks something like this
+```
+The authenticity of host '10.1.2.3 (10.1.2.3)' can't be established.
+ECDSA key fingerprint is SHA256:CwrcHjdd9349u38rj392fr9j389rj3298rj23.
+Are you sure you want to continue connecting (yes/no/[fingerprint])?
+```
+
+Now what should happen, if it isn't your server, is the sysadmin would provide you with the fingerprint of the host key(s) so you can confirm it is in fact the correct server you are connecting to.
+
+But we all know that doesn't happen. Everyone types `yes` and moves on with their life.
+
+When you accept the fingerprint SSH adds the host public key to your _known_hosts_ file, usually located under ~/.ssh.
+
+If the host key ever changed you would want to know. It could be the sysadmin has rotated the keys (unlikely), the server has been rebuilt or another has taken that IP (likely), or someone is attempted a Man in the Middle attack (scary!).
+
+Thankfully SSH does warn you, have you ever seen this?
+```
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
+Someone could be eavesdropping on you right now (man-in-the-middle attack)!
+It is also possible that a host key has just been changed.
+The fingerprint for the ECDSA key sent by the remote host is
+SHA256:CwrcHjdd9347u38fj392fr9f389rj289snjd.
+Please contact your system administrator.
+Add correct host key in /home/pyratebeard/.ssh/known_hosts to get rid of this message.
+Offending ECDSA key in /home/pyratebeard/.ssh/known_hosts:1
+ECDSA host key for 10.1.2.3 has changed and you have requested strict checking.
+Host key verification failed.
+```
+
+Phew, now we can contact our sysadmin and make sure we're not being intercepted.
+
+Or, as is more likely, we remove the "offending" line and reconnect
+```
+ssh-keygen -f ~/.ssh/known_hosts -R 10.1.2.3
+```
+
+An SSH CA can help improve security by removing this need to confirm the key fingerprints, because as we know nobody does it anyway.
+
+By signing all your server's host keys with a CA key your users only need to trust one entity, the CA.
+
+For SSH, a CA is actually just another SSH key pair. You then sign a hosts public key using the CA private key to produce a certificate. To generate a CA it's as easy as creating a new key pair
```
ssh-keygen -t ed25519 -C hostca@pyratebeard.net -f hostca-key
-cat hostca-key.pub
```
-* on local system, add ca pub key to _~/.ssh/known_hosts_
+Now I have _hostca-key_ and _hostca-key.pub_. I am using ED25519 instead of RSA or ECDSA.
+
+The public key is the entity we want to trust, so we add that to our _known_hosts_ file, prefixed with `@cert-authority` and the domain your servers are in
```
cat >> ~/.ssh/known_hosts << EOF
> @cert-authority *.pyratebeard.net [hostca public key]
> EOF
```
-* copy server public key
+In my example I am using the domain `pyratebeard.net` and a wildcard for the subdomain. This means if I `ssh` to `server.pyratebeard.net` then this CA will be used. You could use a wildcard (`*`) with no domain if you use the same CA for every system you need to access.
+
+Next we want to take a copy of the host public key
```
# method 1
cat >> server-ssh_host_ed25519_key.pub << EOF
@@ -27,21 +86,21 @@ cat >> server-ssh_host_ed25519_key.pub << EOF
> EOF
# method 2
-rsync server:/etc/ssh/ssh_host_ed25519_key.pub server-ssh_host_ed25519_key.pub
+rsync server.pyratebeard.net:/etc/ssh/ssh_host_ed25519_key.pub server-ssh_host_ed25519_key.pub
# method 3
-ssh-keyscan server | grep ed25519
+ssh-keyscan server.pyratebeard.net | grep ed25519
```
-* sign server public key with ca private key
+Now we can sign the host public key using our CA private key
```
ssh-keygen -s hostca-key -h -I server@pyratebeard.net -n server.pyratebeard.net,server -V +52w server-ssh_host_ed25519_key.pub
```
- * -s sign
- * -h host cert
- * -I unique identifier
- * -n principals
- * -V validity
+* `-s` sign - tells `ssh-keygen` which key to sign with
+* `-h` host cert - indicates we're creating a host cert (not a user cert)
+* `-I` unique identifier - an identifier used for logging
+* `-n` principals - hostname(s) certificate is valid for, good practice to user short hostname and FQDN
+* `-V` validity - length of time the certificate is valid for, in this example it is 52 weeks
* confirm new server key cert
```
@@ -66,11 +125,11 @@ HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
* reload ssh daemon
-## client
-* create client ca key
+## user
+* create user ca key
```
-ssh-keygen -t ed25519 -C clientca@pyratebeard.net -f clientca-key
-cat clientca-key.pub
+ssh-keygen -t ed25519 -C userca@pyratebeard.net -f userca-key
+cat userca-key.pub
```
* copy user key
@@ -86,7 +145,7 @@ rsync pyratebeard-ssh_ed25519_key.pub server:pyratebeard-ssh_ed25519_key.pub
* sign user public key with ca private key
```
-ssh-keygen -s clientca-key -I pyratebeard@pyratebeard.net -n pyratebeard -V +52w pyratebeard-ssh_ed25519_key.pub
+ssh-keygen -s userca-key -I pyratebeard@pyratebeard.net -n pyratebeard -V +52w pyratebeard-ssh_ed25519_key.pub
```
* -s sign
* -I unique identifier
@@ -109,20 +168,20 @@ cat >> pyratebeard-ssh_ed25519_key-cert.pub << EOF
rsync server:pyratebeard-ssh_ed25519_key-cert.pub pyratebeard-ssh_host_ed25519_key-cert.pub
```
-* copy client ca public key to all servers
+* copy user ca public key to all servers
```
# method 1 (on server)
-cat >> /etc/ssh/clientca.pub << EOF
-> [clientca public key]
+cat >> /etc/ssh/userca.pub << EOF
+> [userca public key]
> EOF
# method 2
-rsync clientca.pub server:/etc/ssh/clientca.pub
+rsync userca.pub server:/etc/ssh/userca.pub
```
* on servers add following to _/etc/ssh/sshd_config_
```
-TrustedUserCAKeys /etc/ssh/clientca.pub
+TrustedUserCAKeys /etc/ssh/userca.pub
```
* reload ssh daemon