How do I set up an email alert when a ssh login is successful?
Solution 1:
Warning: As always when you change the login configuration, leave a backup ssh session open in the background and test the login from a new terminal.
Since the sshrc
method doesn't work if the user has their own ~/.ssh/rc
file, I'll explain how to do this with pam_exec
as @adosaiguas suggested. The good thing is that this can also be easily adapted to login types other than ssh
(such as local logins or even all logins) by hooking into a different file in /etc/pam.d/
.
First you need to be able to send mail from the command line. There are other questions about this. On a mail server it's probably easiest to install mailx
(which is probably already installed anyway). You need to configure mailx
so that the user root
can send mails.
Then you need an executable script file login-notify.sh
with the following content. You can change the variables to change the subject and content of the e-mail notification. You can put the file in /usr/local/bin
or in /etc/ssh/
for example. Don't forget to run chmod +x login-notify.sh
to make it executable. And give ownership to root with sudo chown root:root login-notify.sh
, so that nobody can mess with the script.
#!/bin/sh
# Change these two lines:
sender="[email protected]"
recepient="[email protected]"
if [ "$PAM_TYPE" != "close_session" ]; then
host="`hostname`"
subject="SSH Login: $PAM_USER from $PAM_RHOST on $host"
# Message to send, e.g. the current environment variables.
message="`env`"
echo "$message" | mailx -r "$sender" -s "$subject" "$recepient"
fi
Once you have that, you can add the following line to /etc/pam.d/sshd
(with the correct /path/to/login-notify.sh
of course):
session optional pam_exec.so seteuid /path/to/login-notify.sh
For testing purposes, the module is included as optional
, so that you can still log in if the execution fails. You could change optional
to required
. However, this will prevent any SSH login unless the script is run successfully. Not sure if this is a good idea...
For those of you in need of an explanation of what PAM is and how it works, here is a very good one.
Solution 2:
Warning: according to the comments, this does not work if the user creates a file called
~/.ssh/rc
.*
Modify or create /etc/ssh/sshrc
with the following contents:
ip=`echo $SSH_CONNECTION | cut -d " " -f 1`
logger -t ssh-wrapper $USER login from $ip
echo "User $USER just logged in from $ip" | sendemail -q -u "SSH Login" -f "Originator <[email protected]>" -t "Your Name <[email protected]>" -s smtp.server.com &
This will effectively notify you by email anytime someone logs in through SSH, and the login will be logged in the syslog.
Note: You'll need the sendemail
package (sudo apt-get install sendemail
) for the email notification to work.
Note: works with port forwarding, but with -N option not.
Solution 3:
Put the following in /etc/profile
:
if [ -n "$SSH_CLIENT" ]; then
TEXT="$(date): ssh login to ${USER}@$(hostname -f)"
TEXT="$TEXT from $(echo $SSH_CLIENT|awk '{print $1}')"
echo $TEXT|mail -s "ssh login" [email protected]
fi
How the script works
/etc/profile
is executed at every login (for bash shell users). The if statement will only return true if the user has logged in via ssh, which in turn will cause the indented code block to be run.
Next, we then build the text of the message:
-
$(date)
will be replaced by the output of thedate
command -
${USER}
will be replaced by the user’s login name -
$(hostname -f)
will be replaced by the full hostname of the system being logged into
The second TEXT
line adds to the first, giving the IP address of the system this user is logging in from. Finally, the generated text is sent in an email to your address.
Summary Linux will, by default, record every system login, whether by ssh or not, in the system log files, but sometimes – particularly for a system that is seldom accessed via ssh – a quick and dirty notification can be useful.
Solution 4:
We have been using monit to monitor processes on our linux boxes. monit can also alert by emails on successful logins over ssh. Our monit config looks like this
check file ssh_logins with path /var/log/auth.log
# Ignore login's from whitelist ip addresses
ignore match "100.100.100.1"
# Else, alert
if match "Accepted publickey" then alert
Note: The mailserver configuration, email format etc. should be set in monitrc
file
Update: Wrote a more detailed blog post on this
Solution 5:
Mailgun adaptation of @Fritz answer
After posting I noticed @pacharanero also writes about mailgun, but I don't understand what they are doing with dig, so I'll post my solution as well.
If you are on a VM that doesn't have SMTP, you might need to use something like mailgun, sendgrid, or the like. This worked for me on Google Cloud.
One risk of this approach is that an attacker may get your outgoing email sending credentials if they can sudo su
and find the script or you leave the script for sending email readable. mailgun has an ip whitelist you should set up, but that's imperfect for this particular use case, obviously.
This script should work with mailgun after you change mydomain.com
to your actual domain. You could save the script in /root/login-alert.sh
or some more obscure location.
#!/bin/bash
if [ "$PAM_TYPE" != "close_session" ]; then
APK='api:your-mailgun-api-key-goes-here'
FROM='Login Alert <[email protected]>'
TO='[email protected]'
SUBJECT="Login: $PAM_USER @ mydomain.com from $PAM_RHOST"
DATE=$(date)
TEXT="At $DATE a login occurred for $PAM_USER on mydomain.com from $PAM_RHOST"
curl -s --user $APK \
https://api.mailgun.net/v3/mg.mydomain.com/messages \
-F from="$FROM" \
-F to="$TO" \
-F subject="$SUBJECT" \
-F text="$TEXT"
fi
After that you can follow @Fritz answer to change /etc/pam.d/sshd
to include:
session optional pam_exec.so seteuid /root/login-alert.sh
I note this works with no read permissions for arriving users (chmod 700 /root/login-alert.sh
) so arriving users do not need to have read access to the script.