[Ubuntu] SSH 접속 시 텔레그램 알람보내기 #3 (명령어로 메시지발송 테스트)

[Ubuntu] SSH 접속 시 텔레그램 알람보내기 #3 (명령어로 메시지발송 테스트)
Photo by Dima Solomin / Unsplash

지난 편을 작성하고서 일이 바빠져서... 글 작성이 너무 늦어져서, 다시 하던 것을 마무리하고자 한다. 아마 이번 편과 다음 편까지 총 4편으로 마무리가 될 것 같다. 사실 중간 과정없이 쉘스크립트만 공유해도 무관한데... 내가 공부했던 과정을 기록하면 다른 사람도 혹시 그 과정에서 얻는 것이 있지 않을까 싶었고, 나도 이걸 기록하면서 얻는 것이 있을 것 같아서이다.


연관 포스트

  1. [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #1 (봇생성편)
  2. [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #2 (메시지발송편)
  3. [Ubuntu] SSH 접속 시 텔레그램 알람보내기 #3 (명령어로 메시지발송 테스트)
  4. [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"}}

  1. 참고문서 1을 보면 자세한 내용을 확인 할 수 있다. ↩︎

  2. 참고로 위 url은 API Token을 임으로 변형한 것이므로 정상적으로 실행되지 않는다. ↩︎

처음 curl 명령어를 실행했을 때는 실패했지만, 두번째 get파라미터를 -d 옵션으로 분리하고서는 정상적으로 메시지 발송에 성공했다!

B. 조금 더 복잡하게

프로그래밍으로 치면, 이제 ==Hello World!==만 끝난 것이다. 단순하게 login과 같은 띄어쓰기도 안되어있는 메시지만 보낼꺼라면 저걸로 충분하지만... 난 좀 더 많은 정보를 메시지에 담고 싶었다.

  1. SSH 세션이 열린 서버의 호스트명과 IP주소
  2. 접속한 사용자계정과 IP주소
  3. 접속한 시간

일단 최소 위의 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

위 내용 중에서 주요 라인을 설명하면...

  1. API_TOKEN : 이 부분은 본인이 봇파더에게 받은 봇의 API TOKEN을 넣어준다.
  2. API_CHATID : 이 부분도 이전 문서에서 확인한 나의 Chat ID를 넣어준다.
  3. 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. 참고문서

  1. [Linux] wget, curl 차이, 우노, 운호(Noah), 2021/04/21
  2. curl로 REST API 테스트, 기록만이살길, 기록만이살길, 2021/03/28