When troubleshooting SSH access or implementing security automation, identifying which public key was used for authentication becomes crucial. The SSH daemon logs this information in different ways depending on your configuration.
The most straightforward approach is checking the authentication logs. On Debian-based systems:
grep "Accepted publickey" /var/log/auth.log
Sample output shows the key fingerprint:
May 15 10:23:45 server sshd[1234]: Accepted publickey for user from 192.168.1.100 port 54322 ssh2: RSA SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789
If fingerprints aren't logged by default, modify sshd_config:
sudo nano /etc/ssh/sshd_config
Add or modify these lines:
LogLevel VERBOSE PubkeyAuthOptions fingerprint
Then restart SSH:
sudo systemctl restart ssh
For currently connected sessions:
sudo lsof -c sshd | grep 'authorized_keys'
This shows which authorized_keys file is being accessed by each SSH process.
Here's a Python script to check logs and send notifications:
import re
import smtplib
from email.message import EmailMessage
def parse_ssh_log():
with open('/var/log/auth.log') as f:
for line in f:
if "Accepted publickey" in line:
match = re.search(r'RSA SHA256:([0-9A-Za-z+/]+)', line)
if match:
fingerprint = match.group(1)
user = re.search(r'for (\w+)', line).group(1)
ip = re.search(r'from ([0-9.]+)', line).group(1)
verify_key(fingerprint, user, ip)
def verify_key(fingerprint, user, ip):
# Your database lookup here
key_db = {
"AbCdEfGhIjKlMnOpQrStUvWxYz0123456789": "admin@example.com"
}
if fingerprint in key_db:
send_notification(key_db[fingerprint], user, ip)
def send_notification(email, user, ip):
msg = EmailMessage()
msg['Subject'] = f"SSH login alert for {user}"
msg['From'] = "noreply@yourserver.com"
msg['To'] = email
msg.set_content(f"User {user} logged in from {ip}")
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
if __name__ == "__main__":
parse_ssh_log()
For more robust tracking, configure auditd:
sudo auditctl -w /home/*/.ssh/authorized_keys -p r -k ssh_key_access
Then query with:
ausearch -k ssh_key_access | grep -E "name=|key serial"
Remember to:
- Restrict log file permissions
- Encrypt email notifications containing sensitive info
- Rate-limit notification emails
- Consider using SSH certificates instead of raw keys for better traceability
For enterprise environments, consider forwarding these logs to your SIEM solution and creating alerting rules there for better scalability and correlation with other security events.
When troubleshooting SSH access or implementing security monitoring, identifying which public key was used for authentication becomes crucial. The SSH server logs contain this information, but extracting it requires proper configuration and parsing.
First, ensure your SSH daemon logs authentication details at the appropriate level. Modify your /etc/ssh/sshd_config:
# Increase logging verbosity
LogLevel VERBOSE
# Alternatively for more details
# LogLevel DEBUG3
Restart the SSH service after changes:
sudo systemctl restart sshd
The system logs will now contain key fingerprints. Here's a sample log entry:
Accepted publickey for user from 192.168.1.100 port 54232 ssh2:
RSA SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789+/==
To extract this information automatically, create a parsing script:
#!/bin/bash
# Parse auth.log for SSH key authentications
grep "Accepted publickey" /var/log/auth.log | \
awk '{print $9, $11, $NF}' | \
sort | uniq -c
Store your authorized keys with email associations in a database table:
CREATE TABLE ssh_keys (
id SERIAL PRIMARY KEY,
fingerprint VARCHAR(128) UNIQUE,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Here's a Python script to match fingerprints and send notifications:
import psycopg2
import smtplib
import re
from email.mime.text import MIMEText
def parse_logs():
conn = psycopg2.connect("dbname=ssh_keys user=postgres")
cur = conn.cursor()
with open('/var/log/auth.log') as f:
for line in f:
if "Accepted publickey" in line:
parts = line.split()
ip = parts[10]
fingerprint = parts[-1]
cur.execute("""
SELECT email FROM ssh_keys
WHERE fingerprint = %s
""", (fingerprint,))
result = cur.fetchone()
if result:
send_notification(result[0], ip)
def send_notification(email, ip):
msg = MIMEText(f"SSH login detected from {ip}")
msg['Subject'] = 'SSH Access Notification'
msg['From'] = 'security@example.com'
msg['To'] = email
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
if __name__ == '__main__':
parse_logs()
For more robust tracking, configure auditd to monitor SSH events:
# Add to /etc/audit/rules.d/ssh.rules
-a always,exit -F arch=b64 -S execve -F path=/usr/sbin/sshd -F key=ssh_session
When implementing this solution:
- Store only key fingerprints, not private key material
- Use TLS for email notifications
- Limit database access to the monitoring script
- Consider rate limiting notifications