Let us consider a first SSH connection to a server that I know the correct public key. Can I setup something such that even if the SSH server public key changes, I am able to figure out if there is not a man-in-the-middle attack?
Jun 2, 3:49pm

Yes, you can protect yourself against man-in-the-middle (MITM) attacks during an SSH connection, even if the server's public key changes, by using SSH key verification best practices. Here’s how you can achieve this:


1. Use SSH Known Hosts with Strict Host Key Checking

By default, SSH clients store the server's public key in the ~/.ssh/known_hosts file. If the key changes, SSH will warn you and refuse to connect (unless you explicitly disable this check).

How it works:

  • On your first connection, SSH saves the server's public key in ~/.ssh/known_hosts.
  • On subsequent connections, SSH compares the server's key with the stored one.
  • If the key does not match, SSH will display a warning like:
    text
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
  • This is your first line of defense against MITM attacks.

How to enforce it:

  • Ensure StrictHostKeyChecking=yes is set in your SSH client config (~/.ssh/config or /etc/ssh/ssh_config).
  • Example:
    text
    Host *
        StrictHostKeyChecking yes
        UserKnownHostsFile ~/.ssh/known_hosts

2. Use SSH Certificates (for Servers)

If you control the server, you can use SSH certificates (signed by a trusted Certificate Authority, or CA) instead of raw public keys.

How it works:

  • The server presents a certificate (signed by a trusted CA) instead of a raw public key.
  • The SSH client checks the certificate against a trusted CA public key (stored in ~/.ssh/known_hosts or a separate file).
  • Even if the server's key changes, as long as the new key is signed by the same CA, the connection is trusted.

How to set it up:

  1. Generate a CA key pair (on a secure machine):
    bash
    ssh-keygen -s /path/to/ca_key -I "cert_id" -n "host" -V +52w server_host_key.pub
  2. Sign the server's host key with the CA.
  3. Configure the SSH client to trust the CA:
    • Add the CA's public key to ~/.ssh/known_hosts with a @cert-authority marker:
      text
      @cert-authority mydomain.com ssh-rsa AAAAB3NzaC1yc2E...
  4. On the server, configure /etc/ssh/sshd_config:
    text
    HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

Advantage:

  • If the server's key changes but is re-signed by the same CA, the client will still trust it.
  • If an attacker tries to intercept, they cannot present a valid certificate signed by your CA.

3. Use SSHFP DNS Records (for Public Servers)

If the server is publicly accessible, you can publish its SSH public key fingerprint in DNS as an SSHFP record.

How it works:

  • The server admin publishes the SSH key fingerprint in DNS:
    text
    example.com. IN SSHFP 1 1 a1b2c3d4e5f6...
  • The SSH client can verify the key against DNS (if DNSSEC is enabled and trusted).

How to enable it:

  • On the client, add to ~/.ssh/config:
    text
    Host example.com
        VerifyHostKeyDNS yes
  • The client will automatically check DNS for the SSHFP record and compare it with the server's key.

Advantage:

  • If the key changes, the client will detect a mismatch (unless the attacker also controls DNS).

Limitation:

  • Requires DNSSEC for full security (otherwise, DNS spoofing is possible).

4. Use a Custom Script to Verify Keys

If you want manual control, you can:

  1. Store the expected public key in a secure location (e.g., encrypted file, password manager).
  2. Before connecting, run a script to fetch the server's current key and compare it:
    bash
    ssh-keyscan example.com | grep "ssh-rsa" | cut -d' ' -f3 > current_key.pub
    diff current_key.pub trusted_key.pub
  3. Only proceed if the keys match.

5. Use Tools Like ssh-ca or ssh-audit

  • ssh-ca: For managing SSH certificates.
  • ssh-audit: To check server configurations and key algorithms.

Summary Table

known_hosts
❌ No
✅ Yes
❌ No
Default SSH behavior.
SSH Certificates (CA)
✅ Yes
✅ Yes
✅ Yes
Best for managed servers.
SSHFP + DNSSEC
❌ No
✅ Yes
✅ Yes
Needs DNSSEC.
Manual Key Verification
✅ Yes
✅ Yes
❌ No
Good for one-off checks.

Recommendation

  • For personal use: Rely on StrictHostKeyChecking and manually verify changes.
  • For managed servers: Use SSH certificates (most secure and flexible).
  • For public servers: Use SSHFP + DNSSEC if available.

Would you like help setting up any of these methods?

Jun 2, 3:49pm

This is a shared conversation and may include unverified content that doesn't reflect Mistral AI's views. Login to resume chatting.

Vibe can make mistakes. Check answers. Learn more