5 min read

Telegram Notifications on SSH Logins

Monitor successful SSH logins with ad-hoc Telegram notifications.
Telegram Notifications on SSH Logins
Photo by Dima Solomin / Unsplash

The Secure Shell Protocol (SSH) is probably one of the most known and used remote administration tool. It can be configured to allow password authentication as well as public-key authentication, where the latter usually offers more resilience against automated Internet bots trying to gain unauthorized access.

Furthermore, there are various tools to additionally secure the SSH service such as Fail2ban or Crowdsec. These Intrusion Detection System (IDS) solutions actively monitor SSH log data to identify a vast of failed login attempts and ban the IP addresses of threat actors. But what about valid SSH logins?

On today's blog post we will focus on implementing an alerting feature for successful SSH logins. Whether it is an unauthorized threat actor or just yourself gaining SSH access during regular server administration. We will plant a shell script that notifies us via Telegram about successful SSH logins on our server.

💡
For this tutorial to work you will need a Telegram account as well as a Telegram Bot to send actual notifications to yourself. Usually, you can chat with BotFather to create a Telegram bot and chat with GetMyID to find out your Telegram chat ID.

Setup and Installation

There are various options to choose from in order to implement notifications during SSH logins. Various other blog posts will often recommend putting a bash script at /etc/profil.d/. However, this solution is not bullet proof, as an attacker may login via SSH using /bin/bash. If this is the case, scripts located at /etc/profil.d/ are not executed.

If you want a more bullet-proof approach, I recommend following the second or third option outlined in this blog post.

Option 1: /etc/profil.d/

All you need to do is to save the following bash script ssh-telegram.sh at the path /etc/profil.d/ of your Linux server and also install the lightweight JSON processor tool jq, which is used in the script itself. Also adjust the USERID and KEY variable with your Telegram API token and user's chat ID.

sudo apt-get install jq

Installation of jq

#!/bin/bash

USERID="<TELEGRAM-CHAT-ID-TO-RECEIVE-ALERT>"
KEY="<TELEGRAM-API-TOKEN-OF-YOUR-BOT>"

TIMEOUT="10"
URL="https://api.telegram.org/bot$KEY/sendMessage"
DATE_EXEC="$(date "+%d %b %Y %H:%M")"
TMPFILE='/tmp/ipinfo-$DATE_EXEC.txt'
if [ -n "$SSH_CLIENT" ]; then
        IP=$(echo $SSH_CLIENT | awk '{print $1}')
        PORT=$(echo $SSH_CLIENT | awk '{print $3}')
        HOSTNAME=$(hostname -f)
        IPADDR=$(hostname -I | awk '{print $1}')
        curl http://ipinfo.io/$IP -s -o $TMPFILE
        CITY=$(cat $TMPFILE | jq '.city' | sed 's/"//g')
        REGION=$(cat $TMPFILE | jq '.region' | sed 's/"//g')
        COUNTRY=$(cat $TMPFILE | jq '.country' | sed 's/"//g')
        ORG=$(cat $TMPFILE | jq '.org' | sed 's/"//g')
        TEXT="$DATE_EXEC # ${USER} logged into $HOSTNAME ($IPADDR) from $IP - $ORG - $CITY, $REGION, $COUNTRY"
        curl -s --max-time $TIMEOUT -d "chat_id=$USERID&disable_web_page_preview=1&text=$TEXT" $URL > /dev/null fi
        rm $TMPFILE
fi

Bash script to send Telegram notifications

🛑
Do not forget to harden permissions and give execution rights to the script.
sudo chown root:root <sh-file>
sudo chmod -R 755 <sh-file>

Option 2: PAM Module

A more robust way of obtaining notifications is using PAM (Pluggable Authentication Modules). It has a module named pam_exec to execute a script at specific PAM events, such as a successfull SSH login.

It's adviced to adjust the above script slightly. Then just place it at your prefered location, not being /etc/profil.d/, e.g. at /opt/pam-notifications.sh.

#!/bin/bash

if [ "$PAM_TYPE" = "open_session" ]; then
        USERID="<TELEGRAM-CHAT-ID-TO-RECEIVE-ALERT>"
        KEY="<TELEGRAM-API-TOKEN-OF-YOUR-BOT>"
        TIMEOUT="10"
        URL="https://api.telegram.org/bot$KEY/sendMessage"
        DATE_EXEC="$(date "+%d %b %Y %H:%M")"
        TMPFILE='/tmp/ipinfo-$DATE_EXEC.txt'
        IP=$(echo $SSH_CLIENT | awk '{print $1}')
        PORT=$(echo $SSH_CLIENT | awk '{print $3}')
        HOSTNAME=$(hostname -f)
        IPADDR=$(hostname -I | awk '{print $1}')
        curl http://ipinfo.io/$IP -s -o $TMPFILE
        CITY=$(cat $TMPFILE | jq '.city' | sed 's/"//g')
        REGION=$(cat $TMPFILE | jq '.region' | sed 's/"//g')
        COUNTRY=$(cat $TMPFILE | jq '.country' | sed 's/"//g')
        ORG=$(cat $TMPFILE | jq '.org' | sed 's/"//g')
        TEXT="$DATE_EXEC # ${USER} logged into $HOSTNAME ($IPADDR) from $IP - $ORG - $CITY, $REGION, $COUNTRY"
        curl -s --max-time $TIMEOUT -d "chat_id=$USERID&disable_web_page_preview=1&text=$TEXT" $URL > /dev/null
        rm $TMPFILE
else
        :
fi

exit 0

Adjusted bash script for PAM to send Telegram notifications

Afterwards, put the following lines of code inside the file /etc/pam.d/sshd.

# telegram notification on login
session    optional     pam_exec.so /opt/pam-notification.sh

Excerpt of /etc/pam.d/sshd

💡
You can configure various other PAM event triggers too. Feel free to read the following blog post: StalkR's Blog: Login notifications, pam_exec scripting

Option 3: SSHRC

Another option would be putting the script into the file /etc/ssh/sshrc.

I personally went for this choice and found a brilliant GitHub repository handling this option. Bonus points as the repository uses a different bash script without dependencies for the jq binary.

Just put the following content into a file at /etc/ssh/sshrc. Ensure proper file permissions (e.g. with sudo chmod 755 /etc/ssh/sshrc).

🛑
You have to supply your Telegram chat ID as well as bot token.

Here is the script content:

#!/bin/bash

export LANG=C
TELEGRAM_CHAT_ID="<YOUR-CHAT-ID>"
TELEGRAM_BOT_TOKEN="<YOUR-BOT-TOKEN"
LOGGED_USER="$(/usr/bin/whoami)"
LOGGED_HOST="$(/usr/bin/hostname -f)"
SERVER_IP="$(/usr/bin/hostname -I | /usr/bin/cut -d ' ' -f 1)"

LOGGED_IP=${SSH_CONNECTION%% *}
LOGGED_TTY="$(/usr/bin/ps -p "$$" -o tname h)"

NOW="$(/usr/bin/date)"
MESSAGE="$(/usr/bin/echo -e "<strong>⚠️ SSH Login Notification ⚠️</strong>\n\n<u>Host</u>: $LOGGED_HOST ($SERVER_IP)\n<u>User</u>: $LOGGED_USER\n<u>User IP</u>: $LOGGED_IP\n<u>Time</u>: $NOW")"

/usr/bin/curl --silent --output /dev/null \
    --data-urlencode "chat_id=${TELEGRAM_CHAT_ID}" \
    --data-urlencode "text=${MESSAGE}" \
    --data-urlencode "parse_mode=HTML" \
    --data-urlencode "disable_web_page_preview=true" \
    "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage"

Result

As soon as a successful SSH login occurs, the notification script will be executed and sends a Telegram notification to you. It will disclose various helpful information to you, such as the user that logged in, the remote IP address from which the login occurred as well as specific information about the IP address itself (city, region, country, organization), if available.

A notification will look something like this:

Telegram notification about SSH login (option 1 and option 2)
Telegram notification about SSH login (option 3)