EC2 인스턴스가 SSH Brute-force 공격을 받을 때 관리자들은 빠르게 대처해야 합니다. 오늘은 SSH 활동 로그를 CloudWatch Logs에 기록한 뒤, CloudWatch Alarm으로 공격을 감지하여 SNS로 이메일에 알리는 서비스를 구축해 봅시다.
1. 인스턴스 준비
Amazon Linux AMI를 사용하며 SSH 액세스가 가능한 EC2 인스턴스를 생성합니다.
EC2 인스턴스가 CloudWatch에 접근할 수 있도록 IAM Role 하나를 생성합니다. CloudWatchAgentServerPolicy를 가져야 합니다.
IAM Role을 EC2 Instance와 연결합니다.
Amazon Linux 2023은 SSH 활동 로그를 생성하는 Rsyslog가 없기 때문에 설치해줘야 합니다. Amazon Linux 2는 이미 설치되어 있을 겁니다.
yum install -y rsyslog
systemctl start rsyslog
systemctl enable rsyslog
이제 /var/log/secure라는 SSH 활동 로그가 생성되었습니다. 로그를 살펴보면 로그인, 루트 전환 등 많은 기록이 있는 것을 볼 수 있습니다.
[root@ip-172-31-40-143 ~]# tail /var/log/secure
Nov 28 05:25:29 ip-172-31-40-143 useradd[2143]: add 'ec2-user' to shadow group 'systemd-journal'
Nov 28 05:25:30 ip-172-31-40-143 sshd[2158]: Server listening on 0.0.0.0 port 22.
Nov 28 05:25:30 ip-172-31-40-143 sshd[2158]: Server listening on :: port 22.
Nov 28 05:30:51 ip-172-31-40-143 sshd[2389]: Accepted publickey for ec2-user from 211.212.73.171 port 52717 ssh2: RSA SHA256:Ij224Qy0We4ca0481H6J8VVPtt68AYQoUnpi28WfKck
Nov 28 05:30:51 ip-172-31-40-143 (systemd)[2397]: pam_unix(systemd-user:session): session opened for user ec2-user(uid=1000) by (uid=0)
Nov 28 05:30:51 ip-172-31-40-143 sshd[2389]: pam_unix(sshd:session): session opened for user ec2-user(uid=1000) by (uid=0)
Nov 28 05:35:27 ip-172-31-40-143 sudo[2573]: ec2-user : TTY=pts/0 ; PWD=/home/ec2-user ; USER=root ; COMMAND=/usr/bin/su
Nov 28 05:35:27 ip-172-31-40-143 sudo[2573]: pam_unix(sudo:session): session opened for user root(uid=0) by ec2-user(uid=1000)
Nov 28 05:35:27 ip-172-31-40-143 su[2575]: pam_unix(su:session): session opened for user root(uid=0) by ec2-user(uid=0)
Nov 28 05:37:45 ip-172-31-40-143 sshd[25597]: Unable to negotiate with 211.109.181.11 port 56161: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]
CloudWatch Logs에 로그를 보낼 수 있도록 CloudWatch Agent를 설치합니다.
yum install -y amazon-cloudwatch-agent
CloudWatch Agent 마법사로 Config 파일을 생성할 수 있습니다.
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
다음과 같이 질문에 답하면 로그 파일만 전달하게 설정하는 Config 파일을 생성할 수 있습니다.
[root@ip-172-31-40-143 ~]# /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
================================================================
= Welcome to the Amazon CloudWatch Agent Configuration Manager =
= =
= CloudWatch Agent allows you to collect metrics and logs from =
= your host and send them to CloudWatch. Additional CloudWatch =
= charges may apply. =
================================================================
On which OS are you planning to use the agent?
1. linux
2. windows
3. darwin
default choice: [1]:
Trying to fetch the default region based on ec2 metadata...
2023/11/28 06:20:12 I! imds retry client will retry 1 times
Are you using EC2 or On-Premises hosts?
1. EC2
2. On-Premises
default choice: [1]:
Which user are you planning to run the agent?
1. root
2. cwagent
3. others
default choice: [1]:
Do you want to turn on StatsD daemon?
1. yes
2. no
default choice: [1]:
2
Do you want to monitor metrics from CollectD? WARNING: CollectD must be installed or the Agent will fail to start
1. yes
2. no
default choice: [1]:
2
Do you want to monitor any host metrics? e.g. CPU, memory, etc.
1. yes
2. no
default choice: [1]:
2
Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
1. yes
2. no
default choice: [2]:
2
Do you want to monitor any log files?
1. yes
2. no
default choice: [1]:
Log file path:
/var/log/secure
Log group name:
default choice: [secure]
/ec2/ssh
Log stream name:
default choice: [{instance_id}]
Log Group Retention in days
1. -1
2. 1
3. 3
4. 5
5. 7
6. 14
7. 30
8. 60
9. 90
10. 120
11. 150
12. 180
13. 365
14. 400
15. 545
16. 731
17. 1096
18. 1827
19. 2192
20. 2557
21. 2922
22. 3288
23. 3653
default choice: [1]:
Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:
2
Do you want the CloudWatch agent to also retrieve X-ray traces?
1. yes
2. no
default choice: [1]:
2
Existing config JSON identified and copied to: /opt/aws/amazon-cloudwatch-agent/etc/backup-configs
Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
Current config as follows:
{
"agent": {
"run_as_user": "root"
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/secure",
"log_group_name": "/ec2/ssh",
"log_stream_name": "{instance_id}",
"retention_in_days": -1
}
]
}
}
}
}
Please check the above content of the config.
The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
Edit it manually if needed.
Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
2
Program exits now.
이제 Config 파일을 적용하여 CloudWatch Agent를 시작하게 합니다.
amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
CloudWatch Logs에 가면 지정해 준 이름으로 Log group이 생성됐을 것입니다.
EC2 Instance ID의 이름을 가진 Log stream을 클릭하면 /var/log/secure의 내용이 그대로 전달된 것을 볼 수 있습니다.
2. CloudWatch Alarm 생성
SSH 접속 실패 메시지를 보기 위해 SSH 액세스를 없는 유저로 2번, 키 페어 없이 2번 해보겠습니다.
C:\Users\User>ssh bad-user@3.35.49.204
bad-user@3.35.49.204: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
C:\Users\User>ssh bad-user@3.35.49.204
bad-user@3.35.49.204: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
C:\Users\User>ssh ec2-user@3.35.49.204
ec2-user@3.35.49.204: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
C:\Users\User>ssh ec2-user@3.35.49.204
ec2-user@3.35.49.204: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
공통적으로 Connection reset by 라는 로그가 남겨지는 것을 볼 수 있습니다. 이러한 사실을 토대로 필터를 생성하면 됩니다. (나중에 보니 연결한 이력이 있어 해당 메시지가 나오는 것이었습니다. Connection closed by 같이 다른 필터 패턴을 사용하는 것을 추천드립니다.)
Log group에서 Metric filters를 누른 뒤, Create metric filters를 누릅니다.
Filter pattern을 Connection reset by (or Connection closed by)로 설정한 후, Next를 누릅니다.
Filter와 Metric에 관한 설정을 한 후, Next를 누릅니다.
계속해서 Create metric filter를 누릅니다.
이제 metric filter를 토대로 alarm을 생성해 봅시다. metric filter를 선택한 후, Create alarm을 누릅니다.
5분에 5번 이상 SSH 연결 실패 시, alarm이 울리도록 설정합니다. Next를 누릅니다.
alarm이 울리면 이메일에 알리도록 SNS topic을 생성해 줍니다. Create topic을 누른 뒤, Next를 누릅니다.
alarm 이름까지 설정해 주고, Next를 누릅니다.
Create alarm을 누르면 alarm이 생성된 것을 볼 수 있습니다.
이메일 인증을 한 후, SNS Subscriptions에서 Status가 Confirmed로 나오는 것까지 확인해야 합니다.
3. 실행 확인
모든 준비가 끝났습니다. 이제 SSH로 6번 정도 잘못 접근하여 Alarm이 울리고, 이메일이 오는지 확인해 봅시다.
C:\Users\User>ssh bad-user@3.35.49.204
bad-user@3.35.49.204: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
In alarm 상태가 되는 것을 확인할 수 있습니다.
이메일도 즉시 보내졌습니다.
오늘의 글은 여기까지입니다. 감사합니다!
'AWS' 카테고리의 다른 글
[AWS] Github Actions로 ECS 서비스에 배포 (Rolling Update) (0) | 2023.12.29 |
---|---|
[AWS] Github Actions로 CodeDeploy 실행 (EC2) (0) | 2023.12.29 |
[AWS] Golang Gin 이미지를 만들어서 ECR에 Push (0) | 2023.10.14 |
[AWS] Managed Service for Apache Flink로 스트리밍 데이터 분석 - Studio notebooks (1) (0) | 2023.10.13 |
[AWS] Athena에서 Table 생성부터 데이터 조회까지 (0) | 2023.10.12 |