Using AuthorizedKeysCommand in sshd

Posted by : on

Category : ssh   security   network


Using AuthorizedKeysCommand allows you to customize how SSH retrieves the public keys used for authentication. Typically, SSH retrieves public keys from the ~/.ssh/authorized_keys file, but with AuthorizedKeysCommand, you can specify a script or command that SSH will call to fetch the keys from an external source (like a remote server, a database, or another file system).

Example: Fetching Authorized Keys from a Remote File

Here’s a setup example where AuthorizedKeysCommand is used to fetch keys from a remote server over SSH or HTTP. We will write a simple script that fetches the keys and returns them to the SSH server.

Step 1: Write the Command Script

Create a script (e.g., /usr/local/bin/fetch-keys.sh) that retrieves the public keys from a remote file or service. This script will be called by the SSH server.

Example Script to Fetch Keys from a Remote SSH Server:

#!/bin/bash

# Ensure the username is passed in
if [ -z "$1" ]; then
  exit 1
fi

# Define the remote location of the authorized keys (adjust the server and path)
REMOTE_SERVER="keys.example.com"
REMOTE_KEYFILE="/home/$1/.ssh/authorized_keys"

# Fetch the keys using SCP or SSH
ssh $REMOTE_SERVER "cat $REMOTE_KEYFILE"
  • Explanation: This script uses ssh to log in to the remote server (keys.example.com) and retrieve the authorized_keys file for the specified user. The $1 variable represents the username passed to the script by the SSH server.

  • Permissions: Make sure the script is executable:

    sudo chmod +x /usr/local/bin/fetch-keys.sh
    

Example Script to Fetch Keys via HTTP API:

This script adds a 5-second connection timeout and a 10-second total maximum time to prevent long delays if the remote server is slow or down.

#!/bin/bash

# Ensure the username is passed as an argument
if [ -z "$1" ]; then
  exit 1
fi

# Set the URL of the remote server
REMOTE_URL="https://keys.example.com/keys/$1"

# Use curl to fetch the public keys
curl -s --connect-timeout 5 --max-time 10 "$REMOTE_URL"

# Exit with the appropriate status
if [ $? -ne 0 ]; then
  exit 1
fi

return $?
  • Explanation:
    • $1: This is the username passed to the script by the SSH server.
    • curl -s: Fetches the public key from https://keys.example.com/keys/$1. The -s flag makes curl silent (suppress progress output).
    • Replace https://keys.example.com/keys/$1 with the actual URL where the public key is hosted. For example, if the user is gp, the URL would be https://keys.example.com/keys/gp.
  • Permissions: Make sure the script is executable:
    sudo chmod +x /usr/local/bin/fetch-keys.sh
    

Security Considerations

  • HTTPS: Make sure to use HTTPS for secure transmission of the public keys.
  • Access Control: Ensure that only authorized requests can fetch public keys. Consider setting up authentication mechanisms if needed.
  • Timeouts and Error Handling: Make sure your curl command has sensible timeout settings (--connect-timeout, --max-time) and error handling. This ensures that your SSH server won’t hang if the remote key server is unreachable.

Why Use a Script Instead?

  • Complex Logic: If you need to handle errors, logging, or more complex conditions (like checking multiple sources for keys), using a script would give you more flexibility.
  • Scalability: While you can use curl directly, a script can more easily accommodate changes to your key-fetching logic in the future without modifying the SSH configuration.

This is the simplest way to use curl directly, but consider switching to a script if you need more advanced functionality. Let me know if you have more questions!

Step 2: Configure sshd_config

Modify your sshd_config to use the AuthorizedKeysCommand directive to call your script. Edit the /etc/ssh/sshd_config file and add the following lines:

AuthorizedKeysCommand /usr/local/bin/fetch-keys.sh
AuthorizedKeysCommandUser nobody
  • AuthorizedKeysCommand: Specifies the path to your script (/usr/local/bin/fetch-keys.sh).
  • AuthorizedKeysCommandUser: Specifies the user under which the command will be run. It’s recommended to use a low-privilege user like nobody for security reasons.

Step 3: Reload the SSH Configuration

After making the changes, restart the SSH service to apply the new configuration:

sudo systemctl restart ssh

Step 4: Test the Configuration

To test the configuration:

  1. Ensure the authorized_keys file exists on the remote server (keys.example.com) for the user you want to SSH into.
  2. Try logging in to the server as the user whose key is fetched remotely:

    ssh user@your-ssh-server
    

The fetch-keys.sh script will be called to retrieve the public key from the remote server and allow the login.

Notes:

  • Security: Ensure that your remote server where the public keys are stored is secure. Access to the remote server should be restricted to avoid unauthorized key retrieval.
  • Performance: Depending on the method of fetching keys (e.g., using ssh, scp, or curl), there might be a performance impact. Consider caching public keys locally if necessary.
  • Error Handling: Ensure that your script handles errors, such as if the remote server is unreachable or if the user does not have an authorized keys file.

This method provides flexibility for environments where public keys are centrally managed or stored remotely.

To view a small project to manage remote keys, checkout the ssh keys manager


About Guillaume Plante
Guillaume Plante

A developper with a passion for technology, music, astronomy and art. Coding range: hardware/drivers, security, ai,. c/c++, powershell

Email : guillaumeplante.qc@gmail.com

Website : https://arsscriptum.ddns.net

Useful Links