DNS company

Ditch SSSD before getting it

Februari 2024 I've attended the AIM track at FOSDEM. And -once again- I decided I really should try SSSD.
A great solution to fix authentication to many servers at a central point (but additionally with failover).
Plus, it can also manage authorisation in sudo.
My biggest petpeeve in Linux security is that sudo is working against you when unconfigured or too loosely.
In reality almost always. And so this would be a nice solution to tackle that.

However, after 3 days of battle: configuration of several cocktails of SSSD i.c.w. GSAPI and OpenLDAP and FreeIPA...
...I made the conclusion there are no simple recipies available on the internet to accomplish even something simple.
And so decided to give up, as time is valuable, and so doing it the hard way remains much easier.

I couldn't imagine OpenSSH never jumped in providing a solution to this need.
So I started re-reading man sshd_config and noticed AuthorizedKeysCommand.

TL;DR

Below method will:

  • eliminate unnecessary maintenance of countless ~/.ssh/authorized_keys files
  • centralize, but still enjoy failover when using multiple nameservers as DNS is redundant by design
  • eliminate fragile dependencies, creating fatal problems, making your server unreachable
  • instead allows redundancy in dependencies
  • reliable automize verification of hostkey fingerprints - especially when using DNSSEC signed zones

Theo's Agent

Doing a Google search on 'AuthorizedKeysCommand' returned me example usage on OpenBSD by Theo's Tool, so likely Theo de Raadt.
Delving deeper in OpenSSH documentation it shows the chosen command only would need to supply the same content as a authorized_keys file.
...which we can also generate using TXT records, especially when having DNSSEC signed DNS zones.

Let's try it

Server side

So let's give it a spin. Starting at the OpenSSH deamon I placed this configuration:


AuthorizedKeysCommand		/etc/ssh/dns2authkeys.sh
AuthorizedKeysCommandUser	root

Initially I attempted using dnspython to extract public SSH keys from TXT records. However OpenSSL 3+ is causing trouble in Python.
Made me decide to eliminate additional software which is causing trouble instead of convience. Already causing failure before we began.

Instead let's use Bind's dig or Knot's kdig command, i.c.w. POSIX compliant shell scripting.
Since the whole thing developed organicly, it's hard to break down it's explanation chronologicly.
However, as you can see, below script:

  • searches for a TXT record starting with 'v=sss'
  • then looks for TXT records containing the public keys
  • returns data identical to what you can put in authorized_keys

#!/bin/sh
PATH=/bin:/usr/bin:/usr/local/bin

[ -x "$(command -v  dig)" ] && dig='env  dig';
[ -x "$(command -v kdig)" ] && dig='env kdig';
[ -z "${dig}" ] && exit 1	# exit when dig or kdig is absent.

myself=hostname			# hostname should be set correctly, corresponding to DNS records
myself='srv99.vandewoestyne.nl'	# manual intervience

ans=`${dig} +short ${myself} -t TXT | grep '"v=sss ' | tail -n 1`
[ -z "${ans}" ] && exit 0	# exit when no SSS record found in DNS
ans="${ans#?}";			# strip opening "
ans="${ans%?}";			# strip closing "

for usr in ${ans}; do		# assemble 'authorized_keys' content from TXT record(s)
  if [ ! -z "${usr}" ] && [ "${usr}" != "v=sss" ]; then
    
    ${dig} +short ${usr} -t TXT | while read key; do
      key="${key#?}";		# strip opening "
      key="${key%?}";		# strip closing "
      echo ${key}		# return entry
    done

  fi
done

# any suggestions/advice to improve are welcome.
# One todo bullet point would be filtering TXT records on supported and accepted key algorithms.

The DNS part of it

We would need to place above mentioned TXT records. Since there is no standard I can make my own.
And so initially I just use one records that can point to groups at different domains (in this example i037.com).

srv99.vandewoestyne.nl  A      172.232.157.80
srv99.vandewoestyne.nl  TXT    v=sss cto.i037.com leo.i037.com tim.i037.com

Then the actually public keys of users I placed in TXT records:

cto.i037.com  TXT  ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABB ... B5AXLHTbRiBzNtdEWI1J8y2P= harry@laptop
leo.i037.com  TXT  sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAdyNTZA ... Blb5jb20AAmtleTE= key1 verify-required
leo.i037.com  TXT  ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMHuZJJjjgOKl+4z4j3tR7N/rgQO0WwuN2Cc/FAAA/TI key2
leo.i037.com  TXT  ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABB ... ebTdM= root@blackbox.ams1.unicycle.net
tim.i037.com  TXT  ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABB ... n5rSS1wdaaagmulQ+Qo= tim@MacBook.local

And while we're at it... also place fingerprints of the public hostkeys in SSHFP records, conform RFC 4255
To do so, there is a usefull command, which -at the server- reads the hostkeys and generates the SSHFP records.


ssh-keygen -r srv99.vandewoestyne.com
srv99.vandewoestyne.nl  SSHFP  1 1 84466bc1d5591bb4208ab9f2258b709b267a56a7
srv99.vandewoestyne.nl  SSHFP  1 2 2f4ff75830aff217db5fe4c47ef750fee74a921481e208d7386d002aacfe7a9d
srv99.vandewoestyne.nl  SSHFP  3 1 3fdbb4e13c67f9b7da2e596342326a736c62faa7
srv99.vandewoestyne.nl  SSHFP  3 2 8a02bc9ccd0368caa5f7660250fe3eb2bb2cf9493a6587388383886caa55598b
srv99.vandewoestyne.nl  SSHFP  4 1 718f33624621ba9cc3c13ddcbe20e17f7f952566
srv99.vandewoestyne.nl  SSHFP  4 2 0f899ca49b91188a81a12fa869bf7dd98edb9ed69c484957efecbe306cbc2a2a

Local SSH client

Proof of concept / proof of pudding

Actually the local client doesn't need any modification, except for VerifyHostKeyDNS.
Still you may wish to place something like below in your local ~/.ssh/config


Host srv96, srv97, srv98, srv99
	Hostname		%h.vandewoestyne.nl
	User			root
	VerifyHostKeyDNS	yes
	VisualHostKey		yes

Ensure that sshd loaded it's new config. Then on your console typing ssh srv99 should be sufficient.
And when you have a current ssh client, this host would not be automatically added to your ~/.ssh/known_hosts file.

Conclusions (so far)

  • So far it was pretty simple to accomplish, but can be improved.
  • Right now it does only authentication but no user-distinctive authorisation (yet).
  • it would great if an SSHPK RR type would exist: "SSH Public Key", aside of the SSHFP RR type - such that public keys could be placed in DNS better
  • Proper DNS is making this service redundant by design
  • DNSSEC is optional, but highly recommended
  • ideally you should delegate a zone to NS records in private IP space (kind of "split horizon")

Todo

  • Adjust the script to generate user-specific content, such that bob cannot login as alice - which should be simple using %u
  • Test adding per-user restrictions in authorized_keys

AuthorizedKeysCommand		/etc/ssh/dns2authkeys.sh %u
AuthorizedKeysCommandUser	root

Example of preceding restrictions in "~/.ssh/authorized_keys - which could / should also be in DNS:


no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="~/pipe.sh $SSH_ORIGINAL_COMMAND" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNo...WPY= nagios@dom.tld

Links

https://theoapp.readthedocs.io/en/latest/theo-agent/verify_signed_keys.html
https://jpmens.net/2019/03/02/sshd-and-authorizedkeyscommand/
© 2014-2025: unicycle / 0 loss B.V.