[Ubuntu] SSH 접속 시 텔레그램 알람보내기 #3 (명령어로 메시지발송 테스트)
지난 편을 작성하고서 일이 바빠져서... 글 작성이 너무 늦어져서, 다시 하던 것을 마무리하고자 한다. 아마 이번 편과 다음 편까지 총 4편으로 마무리가 될 것 같다. 사실 중간 과정없이 쉘스크립트만 공유해도 무관한데... 내가 공부했던 과정을 기록하면 다른 사람도 혹시 그 과정에서 얻는 것이 있지 않을까 싶었고, 나도 이걸 기록하면서 얻는 것이 있을 것 같아서이다.
연관 포스트
- [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #1 (봇생성편)
- [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #2 (메시지발송편)
- [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #3 (명령어로 메시지발송 테스트)
- [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #4 (최종편)
A. 명령어로 url 호출
리눅스 명령어로 url을 호출 할 수 있는 명령어는 대표적으로(=내가 알고 있는) curl과 wget이 있다. 내 경우에는 URL을 통해서 무언가를 다운받을 경우에는 wget을 주로 사용하고, Restful API와 같은 특정 URL을 호출하는 경우에는 curl을 사용하는 편이다.[1]
지난 문서와 동일한 메시지를 curl 명령어로 전송해보면...
$ curl https://api.telegram.org/bot57412121:AAEF-Zjsdlsd-----YPk/sendMessage?chat_id=5545034869&text=test
[1] 1859
$ {"ok":false,"error_code":400,"description":"Bad Request: message text is empty"}
[1]+ Done curl https://api.telegram.org/bot57412121:AAEF-Zjsdlsd-----YPk/sendMessage?chat_id=5545034869
$
curl에 단순히 URL 전체[2]를 붙여넣으니 전송이 안된다. 참고문서 2를 보면서 명령어를 손봐야한다.
일단, 위 에러내용을 보니 정상적으로 get 방식으로 전달한 파라미터가 잘 전달되지 않은 것으로 보아서 분리해본다.
$ curl -d 'chat_id=55450--869&text=test' https://api.telegram.org/bot57412121:AAEF-Zjsdlsd-----YPk/sendMessage
위 명령어를 실행하니 아래와 같은 json 형태의 반환값(웹브라우저에서 보였던 값)이 보이고, 메시지도 정상적으로 발송되었다.
{"ok":true,"result":{"message_id":5,"from":{"id":6215--8963,"is_bot":true,"first_name":"simplism-ssh-alarm","username":"simplism_ssh_alarm_bot"},"chat":{"id":55450--869,"first_name":"SIMPLISM","type":"private"},"date":1690266482,"text":"test"}}
처음 curl 명령어를 실행했을 때는 실패했지만, 두번째 get파라미터를 -d 옵션으로 분리하고서는 정상적으로 메시지 발송에 성공했다!
B. 조금 더 복잡하게
프로그래밍으로 치면, 이제 ==Hello World!==만 끝난 것이다. 단순하게 login과 같은 띄어쓰기도 안되어있는 메시지만 보낼꺼라면 저걸로 충분하지만... 난 좀 더 많은 정보를 메시지에 담고 싶었다.
- SSH 세션이 열린 서버의 호스트명과 IP주소
- 접속한 사용자계정과 IP주소
- 접속한 시간
일단 최소 위의 3가지 정보는 메시지에 담고 싶었다.
예를 들어 아래처럼...
simplism-beebox(192.168.0.11) ssh session open! (user=simplism, ip=192.168.0.3, datetime=2023-07-25 (Tue) 15:07:22)
위와 같은 메시지를 받으면, 어떤 리눅스 서버(hostname, server ip)에 누가(user), 언제(datetime), 어디서(client ip) 접속했는지 바로 알 수 있으니까!
C. 메시지를 위한 정보수집
이제 메시지 발송에 포함되는 정보들을 수집할 방법을 찾아보자
01) 서버의 호스트명과 IP주소
$ echo $(hostname)
simplism-beebox
$ echo $SSH_CONNECTION
192.168.0.3 14693 192.168.0.11 22
$ echo $SSH_CONNECTION | awk '{print $3}'
192.168.0.11
$
호스트명은 hostname이라는 명령어의 결과로 출력이 가능하니 간단하고... SSH 서버의 IP주소는 가장 간단하게 SSH 세션이 열리면 SSH_CONNECTION이라는 환경변수에 클라이언트 IP, 클라이언트 Port, 서버 IP, 서버 Port 정보가 저장된다. 그 중에서 3번째의 값이 서버 IP주소이므로 awk 명령어를 이용해서 추출해준다.
$ netstat -an | grep ESTA | grep :22
tcp 0 0 192.168.0.11:22 192.168.0.3:14693 ESTABLISHED
$
netstat명령어로 확인해보면 IP와 Port정보가 나와서 비교해보니 일치한다.
02) 클라이언트 IP주소 및 사용자명
$ echo $SSH_CONNECTION | awk '{print $1}'
192.168.0.3
$ echo $USER
simplism
$
클라이언트 IP주소는 서버 IP주소와 동일하게 SSH_CONNECTION 환경변수에서 추출하고, 사용자명은 USER 환경변수에 저장되니 해당 값에서 추출한다.
03) 접속시간
접속시간은 date 명령을 원하는 포맷(읽기 편한 형태)으로 바꿔서 출력한다.
$ echo $(date +"%Y-%m-%d (%a) %H:%M:%S")
2023-07-25 (Tue) 15:49:35
$
D. 스크립트 파일을 만들자!
이제 단일 명령어로 끝낼 수 있는 수준은 넘었으니.. 쉘스크립트 파일을 만들어보자.
$ vi LoginAlarm.sh
이제 간단한 형태로 스크립트를 만들어보면...
#/bin/sh
NOW=$(date +"%Y-%m-%d (%a) %H:%M:%S")
SERVER_IP=$(echo $SSH_CONNECTION | awk '{print $3}')
CLIENT_IP=$(echo $SSH_CONNECTION | awk '{print $1}')
SERVER_INFO=$(hostname)'('$SERVER_IP')'
API_URL=https://api.telegram.org/bot
API_TOKEN=57412121:AAEF-Zjsdlsd-----YPk
API_METHOD=sendMessage
API_FULLURL="$API_URL$API_TOKEN"/"$API_METHOD"
API_CHATID=55450--869
MSG="<b>$SERVER_INFO</b> ssh session open! (user=$USER, ip=$CLIENT_IP, datetime=$NOW)"
DAT="{\"chat_id\":\"$API_CHATID\",\"text\":\"$MSG\",\"parse_mode\":\"html\"}"
curl -X POST -H "Content-Type: application/json" -d "$DAT" $API_FULLURL
위 내용 중에서 주요 라인을 설명하면...
- API_TOKEN : 이 부분은 본인이 봇파더에게 받은 봇의 API TOKEN을 넣어준다.
- API_CHATID : 이 부분도 이전 문서에서 확인한 나의 Chat ID를 넣어준다.
- DAT : Telegram API를 호출할 때, 보다 다양한 값을 입력하기 위해서 JSON 형태의 데이터를 만들었다. JSON 데이터의 키(Key)를 표현하기 위해서 "(쌍따옴표)를 넣어야하는데, 키(Key)의 쌍따옴표는 앞 부분에 (backslash, 역슬래시)를 넣어서 Escape Character 처리를 해줘야 정상적으로 인식된다. 추가적으로 Bold와 같은 텍스트 강조를 위해서 parse_mode 값에 html이라는 값을 넣어줬다.
사실 위 스크립트를 만들기까지 Telegram 공식 API 문서를 열심히 읽었다.. 그 내용을 다 옮길 수가 없더라.. 더 많은 텔레그램 API와 관련된 내용은 텔레그램 API 문서를 확인해보는 것이 좋을 것 같다.
이제 스크립트 파일을 저장하고...
$ chmod u+x LoginAlarm.sh
실행이 가능하도록 퍼미션을 조정한 다음에...
$ ./LoginAlarm.sh
{"ok":true,"result":{"message_id":6,"from":{"id":6215--8963,"is_bot":true,"first_name":"simplism-ssh-alarm","username":"simplism_ssh_alarm_bot"},"chat":{"id":55450--869,"first_name":"SIMPLISM","type":"private"},"date":1690269331,"text":"simplism-beebox(192.168.0.11) ssh session open! (user=simplism, ip=192.168.0.3, datetime=2023-07-25 (Tue) 16:15:30)","entities":[{"offset":0,"length":16,"type":"bold"},{"offset":16,"length":12,"type":"url"},{"offset":16,"length":12,"type":"bold"},{"offset":28,"length":1,"type":"bold"},{"offset":67,"length":12,"type":"url"}]}}
실행했을 때 ok 값이 true로 나온다면 성공이다!
E. 마치면서..
이제 만든 쉘스크립트에 몇 가지 기능을 손을 보고... SSH 세션이 열릴 때 실행되도록 설정만 하면 된다. 여기까지 따라왔다면 아마 뒷 부분은 어렵지 않을 것 같다.
일단, 포스트가 너무 길어지니까 여기서 마무리하고 다음 편에서 마무리 해보겠다!
F. 참고문서
- [Linux] wget, curl 차이, 우노, 운호(Noah), 2021/04/21
- curl로 REST API 테스트, 기록만이살길, 기록만이살길, 2021/03/28