SSH Login Push Notifications with IFTTT
I recently set out to find a solution for receiving push notifications on my mobile device for important events on my servers. There are tons of fantastic solutions out there, from hosted platforms, such as PushBullet and Pushover, to custom scripts like ntfy. While all options would work well, the streamlined IFTTT ecosystem offers a wealth of seamless integration possibilities, and so I decided to start there.
My first use case was to receive a notification whenever a remote user logs into my servers, ideally with an IP address to help me determine where the session came from. This is by no means a valid SSH security measure, and so ensure that you have already ticked off the never-ending list of important server-hardening tasks like enabling SSH key-authentication, configuring 2fa, changing default port, enabling fail2ban, and much more.
Even then, a mobile notification still sounded cool to me, so onto IFTTT...
IFTTT
IFTTT (If This then That) is general purpose automation service aimed at tying together popular services and devices in the simplest possible way. If you don't already have an account, go ahead and get set up. To start, you will need to enable the Webhooks Service:
With the Service configured, create a new Applet to receive data from Webhooks and pass through to the Notifications service, like this:
You will have a unique API key associated with your Webhooks service. We will need this for our HTTP POST request later on...
Back to the task at hand, because I am looking to have my system perform a custom operation immediately after a successful login authentication I need to understand where in the stack this operation will sit. It would be easy to add an entry into my `.bashrc` to trigger whenever a new bash shell start, but that is a very indirect way of proving a user has logged in, and would quickly become a nuisance when multiplexing multiple shells in TMUX. Instead, let's dig into how the SSH service handles authentication...
PAM
PAM, or "pluggable authentication modules", are a suite of modules for authentication, which can be taken advantage of by all PAM-aware applications. If you take a look in /etc/pam.d/ you will find configuration files for all PAM-aware applications on your system, such as PPP, sudo and SSH. We can amend these configuration files to add in our custom operation.
I created a dedicated PAM script directory under /etc/pam.custom/ as follows, and made sure to restrict privileges accordingly. Inside the directory, I created an empty shell script, where our API call will soon live:
mkdir /etc/pam.custom
chmod 0755 /etc/pam.custom
touch notify.sh
mv notify.sh /etc/pam.custom/
chmod 0700 /etc/pam.custom/notify.sh
chown root:root /etc/pam.custom/notify.sh
chmod +x /etc/pam.custom/notify.sh
Now I can call the script to be executed upon a successful SSH authentication by adding the path at the end of the SSH PAM configuration file.
Append to end of /etc/pam.d/sshd:
#IFTTT Alert
session required pam_exec.so /etc/pam.custom/notify.sh
Notification Script
Now we can proceed to begin testing our API call in our terminal, and add to our shell script once we are happy with it. The below curl
request will POST our defined values to IFTTT:
curl -X POST -H "Accept: application/json" -H "Content-type: application/json" \
-d "{\"value1\": \"HELLO WORLD\"}" \
'https://maker.ifttt.com/trigger/*ALERT*/with/key/*KEY*' \
>/dev/null 2>&1
Now, the above request is quite straightforward. value1
is my notification message ("HELLO WORLD"), and that is all. This message will appear as a notification on my mobile device, and so I gave some thought to what information I would be interested in:
- Hostname - If I pushed this out to all my servers, having the unique hostname would be neccessary to distinguish between them.
- Username - Knowing which user has logged in is good information to have
- Connecting IP Address - Possibly the most important peice of information, the source IP can help me quickly determine whether the SSH session was my own, or a malicious intruder.
- Timestamp - Always nice to have
Starting with the server hostname, this can be easily accomplished with command substitution and the hostname binary, such as $(hostname). The username and connecting IP are not as straightforward.
While the $SSH_CONNECTION
global variable is set whenever a new session is created, PAM will take precedence over the SSH service here and our script will actually be run before this variable is defined. Fortunately we can defer to PAM variables for the connecting IP ($PAM_RHOST) and user ($PAM_USER).
Finally, the timestamp can easily be added with the `date` command, but IFTTT already has the ability to tack on a nicely formatted timestamp, which seems good enough:
Now my finished POST request looks like this:
#!/usr/bin/env sh
curl -X POST -H "Accept: application/json" -H "Content-type: application/json" \
-d "{\"value1\": \"SSH Login 🔒: $PAM_USER logged into $(hostname) from $PAM_RHOST on\"}" \
'https://maker.ifttt.com/trigger/*ALERT*/with/key/*KEY*' \
>/dev/null 2>&1
At this point I have already done a fair amount of testing with the `curl` request and am confident it works fine.
Finally
When establishing a successful SSH session with my server, a push notification now notifies me through IFTTT:
The method here can be reused for all sorts of system checks (resource monitoring, security, event notifications, etc) via IFTTT, and there is a near infinite amount of supporting integrations on the platform to allow you process and receive such alerts wherever you wish:
Whatever your use case, IFTTT has you covered.
Thanks for reading!