본문 바로가기

Cloud/AWS

[AWS] CloudWatch로 EC2 로그 모니터링하기

목표

EC2에 ssh 접속 이벤트가 발생할 때마다 CloudWatch에서 이를 모니터링하여 SNS 알림을 보내고자 한다.

Ubuntu에서는 /var/log/auth.log 파일을 모니터링하여 SSH 로그인 이벤트를 감지할 수 있다. 이를 기반으로 로그 감지 데몬 + CloudWatch Agent를 설정하여 CloudWatch Logs + SNS 알림까지 연결할 계획이다.

 

CloudWatch Logs 그룹 생성

다음, CloudWatch Logs 그룹을 생성하고, CloudWatch Agent를 설정한다.

나는 public key를 사용해 SSH 로그인을 하도록 설정했으므로, "Accepted publickey for"로 필터 패턴을 설정했다.

 

  • 로그 그룹: EC2-SSH-Logs
  • 필터 패턴: "Accepted publickey for"
  • 지표 네임스페이스: EC2/SSHMonitor
  • 지표 이름: SSHLoginEvents
  • 지표 값: 1 (SSH 로그인 감지 시 1 증가)

 

 

IAM 권한 생성 및 EC2에 할당

IAM 권한 생성

우선, EC2 리소스에 IAM 권한을 할당해주어야한다.

'CloudWatchAgentServerPolicy' 권한이 기존에 생성되어있다면 그대로 할당하고, 없다면 새로 생성한다.

 

 

EC2에 할당

EC2에 생성한 IAM 권한을 추가한다.

EC2 인스턴스 선택 > 작업 > 보안 > IAM 역할 수정에서 수정해준다.

 

CloudWatch Agent 설치 및 구성

EC2에 접속해 CloudWatchAgent를 설치한다.

운영체제 이미지마다 설치 경로가 다르며 이 경로는 아래 공식문서에 있다.

 

 

서버에 CloudWatch 에이전트 설치 및 실행 - Amazon CloudWatch

서버에 CloudWatch 에이전트 설치 및 실행 IAM 역할 또는 IAM 사용자에 대한 에이전트 구성 파일을 생성한 후에는 다음 단계에 따라 해당 구성으로 서버에 CloudWatch 에이전트를 설치하고 실행합니다.

docs.aws.amazon.com

나는 우분투라서 아래와 같이 설치했다.

$ sudo wget https://amazoncloudwatch-agent.s3.amazonaws.com/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
$ sudo dpkg -i amazon-cloudwatch-agent.deb

 

오래걸렸음;

 

설치 후 CloudWatch Agent 환경설정 목록을 수정한다. 해당 파일은 /opt/aws/amazon-cloudwatch-agent/bin/config.json 위치에 저장된다.

 

JSON 파일 생성

log_group_name을 앞서 생성했던 로그 그룹 이름으로 적어준다.

log_stream_name에 로그 대상이 되는 인스턴스 아이디를 적어준다.

{
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/var/log/auth.log",
            "log_group_name": "EC2-SSH-Logs",
            "log_stream_name": "{instance_id}"
          }
        ]
      }
    }
  }
}
$ sudo systemctl restart amazon-cloudwatch-agent

 

ssh 로그인 감지 데몬코드

import time
import re
import subprocess

LOG_FILE = "/var/log/auth.log"  # Ubuntu에서 SSH 로그인 로그 위치
PATTERN = re.compile(r"Accepted (password|publickey) for (\S+) from (\S+) port")

def monitor_ssh_log():
    with open(LOG_FILE, "r") as f:
        f.seek(0, 2)  # 파일 끝으로 이동 (기존 로그 무시)

        while True:
            line = f.readline()
            if not line:
                time.sleep(1)  # 새로운 로그가 없으면 대기
                continue

            match = PATTERN.search(line)
            if match:
                auth_method, user, ip = match.groups()
                alert_msg = f"[ALERT] SSH Login Detected: {user} ({auth_method}) from {ip}"
                print(alert_msg)
                
                # CloudWatch Logs로 전송 (선택 사항)
                subprocess.run(["logger", "-t", "ssh-monitor", alert_msg])

if __name__ == "__main__":
    monitor_ssh_log()

 

데몬으로 실행

$ sudo vi /etc/systemd/system/ssh-monitor.service
[Unit]
Description=SSH Login Monitor
After=network.target

[Service]
ExecStart=/usr/bin/python3 /usr/local/bin/ssh_monitor.py
Restart=always
User=root

[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable ssh-monitor
$ sudo systemctl start ssh-monitor
$ sudo systemctl status ssh-monitor

 

CloudWatch Metric Filter 설정

CloudWatch에서 SSH 접속 감지를 위한 지표 필터(Metric Filter)를 설정한다.

 

CloudWatch 경보 설정

  1. SSHLoginEvents 지표 선택
  2. 임계값(Threshold) 설정
    • 조건: >= 1
    • 통계: Sum 또는 Minimum
    • 기간: 1분 (로그 발생 즉시 감지되도록 설정)

알림(Notifications) 설정

  1. SNS 주제를 선택하거나 새로 생성
    • 이메일, SMS, Slack 등 원하는 알림 방식 선택
  2. 경보 이름 설정 후 저장



결과화면

SSH 접근할 때마다 로그를 필터링하여 지표를 계산하고, threshold를 초과하면 알림을 보낸다.

나는 threshold를 1로 설정했기 때문에 특정 기간 내 1번 이상 접근이 확인되면 무조건 알림이 오도록 하였고,

아래와 같이 SNS 서비스를 통해 메일이 날아왔다.