Skip to content

Instantly share code, notes, and snippets.

@LM1LC3N7
Last active November 2, 2023 12:54
Show Gist options
  • Save LM1LC3N7/b6f98611a1cd425cd5e328f90ed697f6 to your computer and use it in GitHub Desktop.
Save LM1LC3N7/b6f98611a1cd425cd5e328f90ed697f6 to your computer and use it in GitHub Desktop.
SSH PAM module - Telegram Alert on connect and disconnect, with IP exceptions.

SSH Telegram configuration

telegram

Bot creation

  1. Open your app and search for @BotFather, or open this link: https://telegram.me/botfather.
  2. Type /newbot
  3. Name your new bot (this is the contact name, like "Bot My server")
  4. Give it a unique Telegram name, ending with bot(like "my_server_bot")
  5. Now, you should see a token: keep it safe!

Chat ID

  1. Search for @IDBot
  2. Start a new discussion with it and type /getid
  3. Start a new discussion with your bot to enable it
  4. Update the USERID in the script

Script creation

Create a new file /usr/local/bin/telegram-alert.sh and copy the script.

SSH configuration

Add a new line at the end of the file /etc/pam.d/sshd:

session optional pam_exec.so type=open_session seteuid /usr/local/bin/telegram-alert.sh

Apply the correct rights:

chmod +x /usr/local/bin/telegram-alert.sh
# For SELinux
restorecon /usr/local/bin/telegram-alert.sh
ausearch -c "sshd" --raw | audit2allow -M my-sshd
semodule -X 300 -i my-sshd.pp

Conclusion

Now, on SSH connection and disconnection you will receive a new Telegram notification by your bot!

#!/bin/bash
# FILE /usr/local/bin/telegram-alert.sh
#################
# TELEGRAM CONFIG
#################
# Your USERID or Channel ID to display alert and key, create a new bot with @BotFather on Telegram
# Ask to @IDBot for your id (/getid)
USERID="********"
# Create a new bot with @BotFather and start a new discussion with it
KEY="*********:***********************************"
URL="https://api.telegram.org/bot${KEY}/sendMessage"
##############
# ALERT CONFIG
##############
# IP Exceptions
# Don't send an alert for theses IPs:
KNOWN_IPs="127.0.0.1 123.456.789.10"
###############
# SCRIPT CONFIG
###############
LOG_FILE="/var/log/telegram.log"
DATE="$(date "+%d %b %Y %H:%M:%S")"
touch ${LOG_FILE}
echo "" | tee -a ${LOG_FILE}
echo "Telegram alert script called at: $(date)" | tee -a ${LOG_FILE}
echo "User that runs the script: $(whoami)" | tee -a ${LOG_FILE}
#######################
# Checking dependencies
#######################
# "jq" must be installed
JQ=$(whereis jq)
if [ ${#JQ} -eq 3 ] ; then
echo "Installing jq tool."
yum install -y jq
fi
# "getent" must be installed
GETENT=$(whereis getent)
if [ ${#GETENT} -eq 3 ] ; then
echo "getent tool is missing on the system, stopping the script." | tee -a ${LOG_FILE}
exit 1
fi
######
# Main
######
if [[ ${KNOWN_IPs} == *"${PAM_RHOST}"* ]]; then
echo "This IP is known, no Telegram alert (${PAM_RHOST})." | tee -a ${LOG_FILE}
echo "DEBUG: ${KNOWN_IPs} == *${PAM_RHOST}." | tee -a ${LOG_FILE}
exit 0
else
echo "DEBUG: ${KNOWN_IPs} != *${PAM_RHOST}." | tee -a ${LOG_FILE}
fi
# Regex to determine if PAM_RHOST provide an IP or a FQDN
rx='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
if [[ ${PAM_RHOST} =~ ^$rx\.$rx\.$rx\.$rx$ ]]; then
USERIP=${PAM_RHOST}
USERFQDN=""
else
# Find the user IP (resolved by default by PAM as FQDN)
USERIP="$(getent hosts ${PAM_RHOST} | cut -d' ')"
USERFQDN=${PAM_RHOST}
fi
IPINFO="https://ipinfo.io/${PAM_RHOST}"
SRV_HOSTNAME=$(hostname -f)
SRV_IP="$(hostname -I | awk '{print $1}')"
echo | tee -a ${LOG_FILE}
echo "SRV_IP = $(ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1)" | tee -a ${LOG_FILE}
echo "SRV_IP = ${SRV_IP}" | tee -a ${LOG_FILE}
echo | tee -a ${LOG_FILE}
# Generate the final text
TEXT="*${PAM_USER}* "
# Change string if it's a new connection or a disconnection
if [ "${PAM_TYPE}" = "open_session" ] ; then
TEXT+="has connected to "
else
TEXT+="has disconnected from "
fi
# Generate the final text
TEXT+="*${HOSTNAME}* (${SRV_IP}).
IP: *${USERIP}* ${USERFQDN}
More information: [${IPINFO}](${IPINFO})
Date: ${DATE}
Service: ${PAM_SERVICE}
TTY: ${PAM_TTY}"
echo "${TEXT}" | tee -a ${LOG_FILE}
# Run in background so the script could return immediately without blocking PAM
curl -s --max-time 10 --retry 5 --retry-delay 2 --retry-max-time 10 -d "chat_id=${USERID}&text=${TEXT}&disable_web_page_preview=true&parse_mode=markdown" ${URL} | tee -a ${LOG_FILE} &
exit 0
@drunkly
Copy link

drunkly commented Nov 8, 2019

Maybe a comment like the next could be useful for others:

# check /etc/ssh/sshd_config:85:UsePAM yes
# to verify pam is reporting

@LM1LC3N7
Copy link
Author

LM1LC3N7 commented Nov 8, 2019

Maybe a comment like the next could be useful for others:

# check /etc/ssh/sshd_config:85:UsePAM yes
# to verify pam is reporting

Yes you are right, this line is required in the SSH configuration:

UsePAM yes

@josemdiaza
Copy link

I'm having a problem with the script.

While trying to access to my server, I receive the following message:

/usr/local/bin/telegram-alert.sh failed: exit code 8

And no message is sent. I'm using Ubuntu 18.04 and jq package is installed.

@josemdiaza
Copy link

I'm having a problem with the script.

While trying to access to my server, I receive the following message:

/usr/local/bin/telegram-alert.sh failed: exit code 8

And no message is sent. I'm using Ubuntu 18.04 and jq package is installed.

I solved this putting in the first line bash shebang. "#!/bin/bash"

@LM1LC3N7
Copy link
Author

I solved this putting in the first line bash shebang. "#!/bin/bash"

oh yes, maybe an incorrect copy and paste!
Thanks 😀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment