❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.
Khi quản trị VPS, một trong những điều quan trọng nhất là biết được ai đang truy cập vào server của bạn. Mặc định, Linux có ghi log đăng nhập SSH trong /var/log/auth.log (Ubuntu) hoặc /var/log/secure (AlmaLinux/Rocky), nhưng mấy ai ngồi đọc log cả ngày?
Giải pháp đơn giản và hiệu quả: tạo một Telegram Bot để gửi thông báo ngay lập tức mỗi khi có ai SSH vào VPS. Bạn sẽ nhận được tin nhắn chứa thời gian đăng nhập, tên user, IP nguồn, ISP và cả thành phố của người kết nối. Toàn bộ quá trình setup chỉ mất khoảng 10 phút.
Trong bài này, mình sẽ hướng dẫn bạn từ A đến Z: tạo bot Telegram, lấy Chat ID, viết script cảnh báo và test thực tế. Hướng dẫn áp dụng cho cả Ubuntu/Debian và AlmaLinux/Rocky Linux.
Bước 1: Tạo Telegram Bot qua BotFather
Đầu tiên, bạn cần tạo một bot Telegram để nhận thông báo. Telegram cung cấp @BotFather để làm việc này.
Mở Telegram, tìm kiếm @BotFather và bắt đầu chat. Sau đó gõ lệnh (hoặc sử dụng mini App):
/newbot
BotFather sẽ hỏi bạn 2 thông tin:
- Tên bot (display name): đặt gì cũng được, ví dụ
VPS SSH Alert - Username bot: phải kết thúc bằng
bot, ví dụvps_ssh_alert_bot
Sau khi tạo xong, BotFather sẽ trả về một Bot Token có dạng:
7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxx
Copy token này lại, bạn sẽ cần nó ở các bước sau.
⚠️ Giữ Bot Token bí mật. Ai có token đều có thể điều khiển bot của bạn, bao gồm gửi tin nhắn và đọc thông tin. Không commit token vào git hay chia sẻ công khai.
Bước 2: Lấy Chat ID
Bot cần biết gửi tin nhắn cho ai, và Chat ID chính là định danh của cuộc hội thoại giữa bạn với bot. Có 2 cách lấy:
Cách 1: Dùng getUpdates API
Mở Telegram, tìm bot bạn vừa tạo và gửi một tin nhắn bất kỳ (ví dụ gõ hello). Việc này tạo ra một “update” để API có dữ liệu trả về.
Sau đó mở trình duyệt hoặc dùng curl, truy cập URL sau (thay <TOKEN> bằng token thật):
curl -s "https://api.telegram.org/bot<TOKEN>/getUpdates" | jq .
Trong kết quả JSON trả về, tìm phần:
"chat": {
"id": 123456789,
...
}
Số 123456789 chính là Chat ID của bạn. Ghi lại giá trị này.
Cách 2: Dùng @userinfobot
Nếu bạn muốn nhanh hơn, tìm @userinfobot trên Telegram, gõ /start. Bot sẽ trả về User ID của bạn ngay lập tức. Giá trị này cũng chính là Chat ID khi chat 1-1 với bot.
Test gửi tin nhắn
Để chắc chắn mọi thứ hoạt động, chạy lệnh test sau trên VPS (thay <TOKEN> và <CHAT_ID> bằng giá trị thật):
curl -s "https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAT_ID>&text=Hello%20from%20VPS"
Nếu Telegram nhận được tin nhắn “Hello from VPS” thì token và Chat ID đã đúng. Nếu không, kiểm tra lại 2 giá trị này.
Bước 3: Cài đặt jq trên VPS
Script cảnh báo sẽ dùng jq để parse dữ liệu JSON từ API tra cứu IP. Cài đặt tùy theo distro:
Ubuntu/Debian:
apt install jq -y
AlmaLinux/Rocky Linux:
dnf install jq -y
Kiểm tra cài đặt thành công:
jq --version
Bước 4: Tạo script cảnh báo SSH
Script sẽ được đặt tại /etc/profile.d/ssh-telegram-alert.sh. Thư mục /etc/profile.d/ chứa các script được tự động chạy mỗi khi user đăng nhập qua shell (bao gồm SSH). Đây là cách đơn giản nhất để trigger thông báo mà không cần chỉnh sửa PAM hay systemd.
Tạo file script:
nano /etc/profile.d/ssh-telegram-alert.sh
Dán nội dung sau vào:
#!/bin/bash
# SSH Login Alert via Telegram
# Gửi thông báo qua Telegram mỗi khi có đăng nhập SSH
# === CẤU HÌNH ===
TELEGRAM_TOKEN="7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxx"
CHAT_ID="123456789"
# === KẾT THÚC CẤU HÌNH ===
# Chỉ chạy khi có kết nối SSH (biến SSH_CONNECTION tồn tại)
if [ -n "$SSH_CONNECTION" ]; then
# Lấy thông tin cơ bản
LOGIN_USER=$(whoami)
LOGIN_DATE=$(date '+%Y-%m-%d %H:%M:%S %Z')
SERVER_HOSTNAME=$(hostname)
SSH_SOURCE_IP=$(echo "$SSH_CONNECTION" | awk '{print $1}')
SSH_SOURCE_PORT=$(echo "$SSH_CONNECTION" | awk '{print $2}')
SSH_DEST_PORT=$(echo "$SSH_CONNECTION" | awk '{print $4}')
# Tra cứu thông tin IP từ ipinfo.io (có fallback)
TMPFILE=$(mktemp /tmp/ssh-alert-XXXXXX)
HTTP_CODE=$(curl -s -o "$TMPFILE" -w '%{http_code}' \
--connect-timeout 5 --max-time 10 \
"https://ipinfo.io/${SSH_SOURCE_IP}/json" 2>/dev/null)
if [ "$HTTP_CODE" = "200" ] && [ -s "$TMPFILE" ]; then
IP_ISP=$(jq -r '.org // "N/A"' "$TMPFILE")
IP_CITY=$(jq -r '.city // "N/A"' "$TMPFILE")
IP_COUNTRY=$(jq -r '.country // "N/A"' "$TMPFILE")
else
IP_ISP="Không tra cứu được"
IP_CITY="N/A"
IP_COUNTRY="N/A"
fi
rm -f "$TMPFILE"
# Tạo nội dung tin nhắn
MESSAGE="🔐 *SSH Login Alert*%0A"
MESSAGE+="━━━━━━━━━━━━━━━%0A"
MESSAGE+="🕐 Thời gian: ${LOGIN_DATE}%0A"
MESSAGE+="👤 User: ${LOGIN_USER}%0A"
MESSAGE+="🖥 Hostname: ${SERVER_HOSTNAME}%0A"
MESSAGE+="🌐 IP nguồn: ${SSH_SOURCE_IP}%0A"
MESSAGE+="🏢 ISP: ${IP_ISP}%0A"
MESSAGE+="📍 Vị trí: ${IP_CITY}, ${IP_COUNTRY}%0A"
MESSAGE+="🔌 Port: ${SSH_SOURCE_PORT} → ${SSH_DEST_PORT}"
# Gửi tin nhắn qua Telegram API
RESPONSE=$(curl -s --connect-timeout 10 --max-time 15 \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${MESSAGE}" \
-d "parse_mode=Markdown" 2>/dev/null)
# Log lỗi nếu gửi thất bại (không hiển thị cho user)
if ! echo "$RESPONSE" | grep -q '"ok":true'; then
logger -t ssh-telegram-alert "Failed to send Telegram notification for ${LOGIN_USER} from ${SSH_SOURCE_IP}"
fi
fi
Thay 2 giá trị TELEGRAM_TOKEN và CHAT_ID bằng token và Chat ID thật mà bạn đã lấy ở bước 1 và 2.
Phân quyền cho script:
chmod +x /etc/profile.d/ssh-telegram-alert.sh
Giải thích script
Script hoạt động theo luồng sau:
- Kiểm tra SSH_CONNECTION: biến môi trường này chỉ tồn tại khi user đăng nhập qua SSH. Nếu đăng nhập local (console), script sẽ không chạy.
- Lấy thông tin đăng nhập: user, thời gian, hostname, IP nguồn và port từ biến
SSH_CONNECTION. - Tra cứu IP qua ipinfo.io: dùng
curlvới timeout 5 giây để tránh treo session. Kết quả lưu vào file tạm rồi parse bằngjq. Nếu API không phản hồi, script dùng giá trị fallback thay vì crash. - Gửi Telegram: gọi API
sendMessagevới nội dung format Markdown. Nếu gửi thất bại, ghi log vào syslog thay vì hiển thị lỗi ra terminal.
💡 Script dùng mktemp tạo file tạm với tên ngẫu nhiên và xóa ngay sau khi dùng. Dấu nháy kép quanh "$TMPFILE" là bắt buộc để xử lý đúng path có khoảng trắng.
Bước 5: Test thông báo
Mọi thứ đã sẵn sàng. Bây giờ bạn mở một terminal khác và SSH vào VPS:
ssh root@your-vps-ip
Ngay sau khi đăng nhập thành công, kiểm tra Telegram. Bạn sẽ nhận được tin nhắn từ bot với đầy đủ thông tin: thời gian, user, hostname, IP nguồn kèm ISP và vị trí, cùng port kết nối.
Nếu bạn không nhận được tin nhắn, hãy xem phần Troubleshooting bên dưới.
Mở rộng: Cảnh báo đăng nhập thất bại
Script ở trên chỉ gửi thông báo khi đăng nhập thành công (vì /etc/profile.d/ chỉ chạy sau khi shell được tạo). Nếu bạn muốn nhận cảnh báo cả khi có ai đó đăng nhập thất bại (brute-force, sai mật khẩu), bạn cần dùng PAM (Pluggable Authentication Modules).
Dùng PAM để bắt sự kiện đăng nhập thất bại
Tạo script xử lý PAM:
nano /usr/local/bin/ssh-pam-alert.sh
Nội dung:
#!/bin/bash
TELEGRAM_TOKEN="7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxx"
CHAT_ID="123456789"
if [ "$PAM_TYPE" = "auth" ] && [ -n "$PAM_RHOST" ]; then
if [ "$PAM_SM_FUNC" = "pam_sm_authenticate" ] || [ -z "$PAM_SM_FUNC" ]; then
MESSAGE="⚠️ *SSH Auth Event*%0A"
MESSAGE+="👤 User: ${PAM_USER}%0A"
MESSAGE+="🌐 IP: ${PAM_RHOST}%0A"
MESSAGE+="📌 Service: ${PAM_SERVICE}%0A"
MESSAGE+="🕐 Thời gian: $(date '+%Y-%m-%d %H:%M:%S')"
curl -s --connect-timeout 10 --max-time 15 \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${MESSAGE}" \
-d "parse_mode=Markdown" &>/dev/null &
fi
fi
Phân quyền:
chmod +x /usr/local/bin/ssh-pam-alert.sh
Thêm dòng sau vào cuối file /etc/pam.d/sshd:
session optional pam_exec.so /usr/local/bin/ssh-pam-alert.sh
💡 Nếu bạn muốn giải pháp chống brute-force toàn diện hơn, hãy kết hợp với CrowdSec hoặc Fail2ban. Các tool này không chỉ cảnh báo mà còn tự động block IP tấn công.
Troubleshooting
Nếu bạn gặp vấn đề, kiểm tra theo thứ tự sau:
Không nhận được tin nhắn Telegram
- Sai token hoặc Chat ID: chạy lại lệnh test ở Bước 2. Nếu không nhận được “Hello from VPS” thì token hoặc Chat ID chưa đúng.
- Firewall chặn outbound HTTPS: VPS cần kết nối được tới
api.telegram.org(port 443). Kiểm tra bằng:curl -I https://api.telegram.org - Chưa gửi tin nhắn cho bot: bạn phải gửi ít nhất 1 tin nhắn cho bot trước khi bot có thể gửi lại cho bạn. Đây là giới hạn của Telegram API.
Script không chạy khi SSH vào
- Thiếu quyền execute: chạy
ls -la /etc/profile.d/ssh-telegram-alert.shvà kiểm tra có flagxkhông. Nếu chưa có, chạy lạichmod +x. - Shell không load profile.d: thư mục
/etc/profile.d/chỉ được load với login shell. Nếu bạn dùngssh user@host command(non-interactive), script sẽ không chạy. - Lỗi cú pháp trong script: chạy
bash -n /etc/profile.d/ssh-telegram-alert.shđể kiểm tra syntax. - jq chưa cài: chạy
which jq. Nếu không có kết quả, quay lại Bước 3 cài đặt.
Nếu muốn debug chi tiết hơn, thêm dòng sau vào đầu script (sau dòng #!/bin/bash):
exec 2>/tmp/ssh-alert-debug.log
set -x
Sau đó SSH vào và kiểm tra file /tmp/ssh-alert-debug.log để xem script chạy đến đâu và lỗi ở đâu.
Tổng kết
Chỉ với một script nhỏ trong /etc/profile.d/, bạn đã có hệ thống cảnh báo SSH real-time qua Telegram. Tóm tắt những gì mình đã làm:
- Tạo Telegram Bot qua @BotFather để nhận thông báo
- Lấy Chat ID bằng getUpdates API hoặc @userinfobot
- Viết script tra cứu IP và gửi thông báo qua Telegram API
- Mở rộng với PAM để bắt cả đăng nhập thất bại
Script hoạt động trên cả Ubuntu/Debian và AlmaLinux/Rocky Linux, chỉ khác nhau ở lệnh cài jq (apt vs dnf). Ngoài ra mọi thứ đều giống nhau.
Bạn có thể tuỳ biến thêm: gửi thông báo vào group Telegram thay vì chat riêng, thêm thông tin CPU/RAM vào tin nhắn, hoặc kết hợp với CrowdSec/Fail2ban để tự động block IP đáng ngờ. Chúc bạn bảo mật VPS hiệu quả!
Có thể bạn cần xem thêm
- Tạo script Monitor tài nguyên VPS và thông báo qua Telegram
- Logging, Monitoring và IDS trên Linux VPS - auditd, AIDE và Wazuh
- Hướng dẫn thiết lập Zabbix cảnh báo qua Telegram
- Thông báo đơn hàng Woocommerce qua Telegram
- Monitoring Docker với Portainer, Uptime Kuma và cAdvisor
- Shell Scripting cơ bản trên Linux - Tự động hóa tác vụ VPS
Về tác giả
Quân Đỗ Trung
Mình là Quân, hiện đang công tác tại AZDIGI với vai trò SysAdmin. Mình có niềm đam mê với việc viết blog, vì thông qua việc viết lách, mình có thể trau dồi thêm nhiều kỹ năng, học hỏi được nhiều kiến thức mới. Từ đó, mình mong muốn chia sẻ lại cho mọi người những bài viết và tài liệu hữu ích, mang tính thực tiễn cao.