We create a Telegram Bot and a Bash script that sends a message to a Telegram chat when a user logs in via SSH on your linux server. The script is designed to help administrators monitor SSH login activity on their server and receive notifications in real-time.
CREATE A TELEGRAM BOT
We look for the user @BotFather
in our Telegram application, and we start to "talk to him".
We ask to launch the creation of a bot: /newbot
Now, follow the steps and if everything went well, it will return the Token that we will use to configure our alert sistem. Save this Token.
Now we need to create a new Group in Telegram which is where the alert messages will arrive. And we add the bot that we have created before as if it were a normal user. We need the ChatID of this group. To know this ChatID there are many options, I used this one that is well explained in stackoverflow:
https://stackoverflow.com/questions/32423837/telegram-bot-how-to-get-a-group-chat-id
In conclusion, we need the token that has been generated when creating our bot and the ChatID of the group that we have created. This is very important so that we can later use it in our bash script.
CREATE A BASH SCRIPT
It's time to have fun. We will create a bash script that will send a message to our Telegram bot.
We simply generate a file in the path /etc/ssh
as follows:
xabikip@debian11:~$ sudo nano /etc/ssh/xabikip-login-ssh.sh
And we put this content:
#!/usr/bin/env bash
TELEGRAM_TOKEN="90273023019:tHeTokENyougetwhENcreatETeleGRamBoT"
CHAT_ID="-xxxxxxxxxxx"
if [ ${PAM_TYPE} = "open_session" ]; then
MESSAGE="$PAM_USER@$PAM_RHOST: New login $PAM_SERVICE"
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" -d chat_id="$CHAT_ID" -d text="$MESSAGE" > /dev/null 2>&1
fi
We give the right execution permissions:
xabikip@debian11:~$ sudo chmod +x /etc/ssh/xabikip-login-ssh.sh
We set the following variable:
xabikip@debian11:~$ PAM_TYPE="open_session" /etc/ssh/xabikip-login-ssh.sh
Now we modify the PAM configuration. The script then uses the PAM (Pluggable Authentication Modules) system to trigger when a user successfully logs in. PAM is a system used by Linux and other Unix-like operating systems to handle user authentication. By using PAM, the script can be sure that it will only trigger when a user has successfully authenticated and logged in.
First, we make a backup:
xabikip@debian11:~$ sudo cp /etc/pam.d/sshd /etc/pam.d/sshd.old
And we add at the end of the file:
xabikip@debian11:~$ sudo nano /etc/pam.d/sshd
-----------
# Login Telegram Notifications
session optional pam_exec.so /etc/ssh/xabikip-login-ssh.sh
That’s all, we can try to see if we done well by login on our server and seen if we got an alert message.
Now, I will to explain the script.
The script begins by setting the Telegram bot token and chat ID as environment variables. The Telegram bot token is a unique identifier that allows the script to interact with the Telegram API, while the chat ID specifies the target chat where the message will be sent.
When a user logs in, the script uses the PAM_TYPE variable to determine whether the action was an "open_session" (i.e., a successful login). If the login was successful, the script constructs a message that includes the user's name, the remote host they logged in from, and the service they are logging into (e.g., SSH)
The curl command is then used to send the message to the Telegram API. The command includes the Telegram bot token, chat ID, and message text as parameters. Any output from the curl command is redirected to /dev/null, which means that the script will not produce any visible output when it runs.
Overall, this script provides a simple and effective way for administrators to monitor SSH login activity on their server and receive notifications in real-time. By using the Telegram API, the notifications can be sent to a group chat or individual user, making it easy to keep track of login activity across multiple servers and users.
Any improvement or any doubt you have will be welcome in the comments ;)
Top comments (2)
There is a typo in the shell script, fixed version
Thank @greenroach ! Now it's fixed ;)