온프레미스에 방화벽(침입차단시스템)이 있다면, AWS 에는 NETWORK FIREWALL 이 있다.
이름은 FIREWALL 이지만 suricata rule 사용 시 IDS/IPS 기능도 쓸 수 있다.
일단 결론부터 설명드리자면, 실제 비즈니스/업무 용도로 쓰기에는 부적합하다. 왜냐면,
- 설정 및 정책 구성 방법이 까다롭다(+번거롭다).
- 로그가 실시간으로 쌓인다고 보기 어렵다.
(약간의 시간차를 두고 로그가 쌓일때가 있다.)
- 직관적이지 못하고 suricata rule 을 써야만 제대로 사용 가능하다.
- 로그 구성을 위해 별도의 룰을 따로 구성해야 한다.
- 상기 사항과 같이 온프레미스의 방화벽과 동작 방식이 달라서 사용, 관리가 어렵다.
그래서인지 실제로 클라우드 환경에서의 방화벽은 안랩, 시큐아이 등과 같은 서드파티 방화벽을
주로 사용한다고 한다. 그래도 개인 프로젝트와 같은 소규모 프로젝트에는 사용할만하다.
(개인 프로젝트인데 보안 회사 클라우드 방화벽을 쓸 수 없으니까)
그리고 NETWORK FIREWALL 은 사용료가 붙는다. 트래픽 사용량에 따라 요금이 매겨지며
자세한 요율은 AWS 홈페이지를 참조한다.
(NETWORK FIREWALL 에 연결된 EC2 에 (D)DoS 공격이 안오길 바래야한다.)
그래서 NETWORK FIREWALL 구성 후 사용하지 않는다면 바로 삭제해야 한다.

온프레미스 방화벽과는 동작 방식이 다르므로 우선 AWS 방화벽의 동작 원리부터 봐야 한다.
이미지만 봐도 어느정도는 이해를 할 수 있다. 자세한 설명은 아래의 사이트를 참고한다.
https://aws.amazon.com/ko/blogs/tech/understanding-anf-rule-evaluation-order/
AWS 방화벽에는 stateless 룰 탐지 엔진과 stateful 룰 탐지 엔진이 있는데, 들어온 패킷은 먼저 stateless 엔진을 거쳐 stateful 엔진으로 온다. 그렇기 때문에 stateless 탐지 룰을 먼저 신경써야 한다. AWS 에서는 되도록 stateless 정책 사용을 금지하고 statefule 정책 사용을 권장한다. (관련 설정은 구성 과정에서 설명)
stateful, stateless 에 대한 개념은 아래의 글 참고
[NW] Stateful, Stateless 차이점
stateful 엔진에 들어가면 온프레미스 방화벽과 비슷하게 동작하는것 처럼 보이지만, 실제 구성해보면 어느정도 차이가 있음을 알 수 있다.
AWS 방화벽은 퍼블릭 서브넷에 방화벽 엔드포인트를 생성하고,
이 방화벽 엔드포인트를 통해서만 외부와 통신할 수 있도록 구성한다.

위 구성도는 표준 구성방식(AWS 홈페이지 제공)이다. 여기에 CLOUDWATCH 를 연동하여 로그를 수집, 분석 할 수 있다.
AWS 방화벽 구성을 위해 사전작업이 필요한데, 최소
- VPC 1개
- 퍼블릭 서브넷 2개
- IGW (인터넷게이트웨이) - 테스트용 VPC 에 연결된 IGW
- 라우팅 테이블 3개
- EC2 1개
가 필요하다. 예전 실습에서 구성한 TEST VPC, 퍼블릭, 프라이빗 서브넷 두개, IGW 를 그대로 활용한다. 이 블로그에 VPC, 서브넷, IGW 를 구성하는 글들이 있으므로 참고하면 된다.
[AWS] VPC, SUBNET 네트워크 망 구성
[AWS] IGW로 외부 인터넷 연결
방화벽 생성 순서는
- 방화벽 rule group(룰 그룹) 생성
- 방화벽 policy(정책) 생성
- 방화벽 생성
- 라우팅 테이블 수정
- 테스트 및 cloudwatch 연동
로 진행한다.
룰 그룹은 말 그대로 룰의 그룹을 의미하고 실제로 어떤 패킷을 통과, 차단할지에 대한 규칙 그룹을 의미한다.
방화벽 RULE GROUP은 생성하여 POLICY(정책) 에 적용하고, 이 정책을 방화벽에 적용하는 방식이다. 즉 방화벽에 룰 그룹, 정책이 귀속되지 않아서, 방화벽을 삭제해도 정책과 룰 그룹은 그대로 남는다.
룰 그룹은 정책에 포함시키고, 정책은 방화벽에 포함시키는 구조로 되어 있다.
(룰 그룹 -> 정책 -> 방화벽), 그래서 룰 그룹과 정책은 여러개의 방화벽에 각각 적용가능하다.
생성 자체는 어렵지 않다. VPC 메뉴에서 NETWORK FIREWALL 메뉴에 NETWORK FIREWALL GROUP 이 있다. 그런데 왜 룰 그룹부터 만드냐면.. 방화벽을 생성할 때 룰 그룹과 방화벽 정책을 구성하게 되어 있는데, 미리 만들어 두면 방화벽 생성할 때 편하기 때문이다.

메뉴에 가면 우측에 CREATE RULE GROUP 으로 생성할 수 있다.
(많은 시행착오로 여러 룰 그룹이 생성되어 있다 ㅋㅋ)

stateful 방화벽으로 운용할 것이니, stateful rule group 으로 생성한다.
rule group format 에는 suricata compatible rule string 을 선택한다.
rule evaluation order 는 strict order 로 설정한다. (AWS 권장사항)
domain list, standard stateful rule 도 선택 가능하지만 일반 통신을 테스트하므로 두가지는 제외한다. domain list 는 도메인 기반, standard stateful rule 은 ip, port, 프포토콜 기반이다. standard stateful rule 설정이 일반 통신에 해당될 것 같지만 해당 기능은 방화벽의 디폴트 차단 정책을 사용할 수가 없다. (디폴트 차단 정책 사용 시 상단에 허용 정책이 있어도 전체 통신이 차단된다. 이유는 알 수 없지만;;)
suricata compatible rule string 은 말그대로 suricata 구문으로 허용, 차단을 구현하겠다는 것이다. suricata 로 구성했을 때 제일 깔끔하게 운영되므로 이 옵션을 선택했다.
suricata 구문은 snort 과 비슷하며, 관련 자료들이 많으니 참고하면 된다.

name(이름) , description (설명) 입력하고, Capacity 는 20 으로 설정한다.
Capacity 는 룰의 최대 갯수이다. 20으로 설정하면 룰을 최대 20개까지 추가할 수 있다.
아래에 있지만 최대 설정값은 30,000 이다. (만 단위로 설정할 일이 없을 듯 하다..)

Configure Rules 부분인데 여기서 실질적인 탐지 룰을 구성한다.
optional 로 되어 있는 부분은 말 그대로 선택사항이므로 따로 건드릴 필요는 없다.
(Rule variables, IP set references 설정)

하단의 suricata compatible rule string 에 rule 구문만 입력해도 사용가능하다.
사진의 구문은 간단한 형식으로 입력한 것이고 TCP 22번, 80번 포트의 통신을 모두 허용하는 구문이다. sid 가 겹치면 에러가 발생하니, 겹치지 않게 주의한다. 물론 더 복잡하게 잘 구성할 수 있다면 그렇게 해도 된다.
pass tcp any any -> any 22 (msg:"allow TCP 22"; sid:10;)
pass tcp any any -> any 80 (msg:"allow TCP 80"; sid:11;)

NEXT

NEXT

마지막 단계인데 설정한 것들을 확인한 후 하단의

CRAETE RULE GROUP을 선택하면 RULE GROUP 구성이 완료된다.
RULE GROUP을 생성했으니 , POLICY (정책)를 생성한다. 정책은 여러개 생성할 수 있으나
방화벽에 적용할 수 있는 정책은 단 한개이다. 그래도 정책 하나에 여러개의 룰 그룹을 포함시킬 수 있으니, 방화벽 운영에는 전혀 문제되지 않는다.

FIREWALL POLICIES 에서 CRAETE FIREWALL POLICY 를 선택한다.

정책 이름, 설명을 입력하고 Stream exception policy 를 Drop 으로 설정한다.
해당 설정은 정책으로 패킷을 차단할 때 어떤방식으로 차단할지 설정하는 것이다.
Drop 방식이 심플하고, 활용하기 쉽다.

AWS 방화벽은 stateless 정책도 구성할 수 있다. 그러나 요즘 보안상 stateless 정책은 거의 쓸 일 없으므로, stateful 정책으로 구성한다.
use the same actions for all packets 에 체크 (모든 패킷에 정책을 동일하게 적용)
Rule action(기본 동작)을 Forwarded to stateful rule group 로 설정한다. Forwarded to stateful rule group 설정은 stateless 정책을 사용하지 않고 stateful 정책으로만 구성한다는 뜻이다.

stateless rule group 은 생성하지 않았으므로 따로 설정할 필요가 없다.
(이미 생성한 rule group 은 stateful rule group 이다.)

그 다음은 stateful rule 에 대한 설정인데 Rule evaluation order 에 strict order 로 체크한다. strict order 은 방화벽의 일반 설정이라보면 된다. (action order 는 pass, block, reject, alert 등의 상세 action 에 대한 고급 설정이므로 권장하지 않는다.)
drop action 은 stateful 정책의 디폴트 동작이다. drop all 로 설정하는데, 어떠한 룰의 조건도 만족하지 않는다면, 디폴트 동작이 적용되고 drop all로 설정했으니, 룰의 조건을 만족하지 못하는 패킷은 모두 차단된다.
alert action 은 alert 를 발생시키기 위한 설정이며 이 또한 디폴트 동작이므로, 어떠한 룰의 조건에도 만족하지 못하는 패킷에 대해서는 alert 를 발생시킨다.
아래 state rule group 의 오른쪽, Add stateful rule groups 을 선택해서 생성해둔 룰 그룹을 추가한다. (이럴려고 먼저 생성했다)

Add stateful rule groups 을 선택하면 생성한 rule group 을 볼 수 있고, 원하는 rule group을 선택하고 add rule group 으로 추가한다.

추가한 rule group을 볼 수 있고, 우측의 next 로 넘어간다.

별로 중요한 건 없으니 별다른 설정없이 비어있는 상태로 next 선택

해당 설정은 SSL/TLS (HTTPS) 트래픽 탐지, 차단을 위한 설정이다. 지금은 HTTP, SSH 테스트만 하므로 따로 설정하지 않고 그대로 NEXT 넘긴다.

TAG 안해도 그만이니 NEXT


POLICY 생성하면서 설정한 것들을 보여주는데 확인 후 CREATE FIREWALL POLICY 선택해서 정책 생성을 완료한다.

생성한 정책을 확인할 수 있다.

NETWORK FIREWALL 서비스, FIREWALLS 메뉴에서 CREATE FIREWALL 선택

이름, 설명 입력

방화벽 엔드포인트를 구성할 VPC, AZ, 서브넷을 선택하고 IP 타입은 IPv4 를 선택한다.
IPv6를 쓸일은 없고, 서브넷은 퍼블릭 서브넷을 선택한다. ADD NEW SUBNET으로 AZ 와 서브넷은 여러개 선택할 수 있으나 테스트를 간단하게 하기위해 하나만 한다.

방화벽 삭제 및 서브넷 변경 차단 설정

생성한 방화벽 정책을 선택한다.

NEXT


방화벽 생성 시 설정한 부분들 확인

생성한 방화벽은 활성화 될 때까지 시간이 몇분 걸린다. (5분 정도 걸리는 듯?)
사진에서 프로비저닝이라고 되어 있는데, 활성화 중 이라는 것이다.
생성한 방화벽은 라우팅의 게이트웨이로 사용할 수 있다.
라우팅 테이블은 총 3개를 구성하는데, 글 상단 AWS 방화벽 표준 구성도의 라우팅 테이블을
보면 더 쉽게 이해할 수 있다.
- IGW 의 라우팅테이블
| 목적지 | 타겟 |
|---|---|
| 10.0.0.0/16 | local |
| 10.0.2.0/24 | vpce- (방화벽 id) |
프라이빗 서브넷으로 들어오는 패킷은 모두 방화벽으로만 통신하게 하기 위해서,
프라이빗 서브넷 대역인 10.0.2.0/24 를 목적지로 설정했다.
- 퍼블릭 서브넷의 라우팅 테이블
| 목적지 | 타겟 |
|---|---|
| 10.0.0.0/16 | local |
| 0.0.0.0/0 | igw-(igw id) |
- 프라이빗 서브넷의 라우팅 테이블
| 목적지 | 타겟 |
|---|---|
| 10.0.0.0/16 | local |
| 0.0.0.0/0 | vpce- (방화벽 id) |
이렇게 구성할 것이다.
그리고 라우팅 테이블 구성 전에 방화벽이 활성화 되어 있어야 한다.

라우팅 테이블의 타겟으로 방화벽을 선택할 때, 활성화 되어 있지 않으면 선택할 수가 없기 때문이다. status (상태)를 보면 ready(활성화) 되어 있다.
IGW 라우팅 테이블 구성을 위해, 라우팅 테이블을 하나 생성한 뒤


edge associations 의 edit edge associations 으로 생성해둔 IGW 를 선택한다.
save changes 를 선택하면 edge associations 가 IGW 로 변경된다.

타겟 타입을 gateway load balancer Endpoint 로 선택하고, 생성한 방화벽을 선택한다.
[ vpce-(방화벽 id) ] 를 선택한다.
나머지 퍼블릭, 프라이빗 서브넷 라우팅 테이블도 라우팅 테이블표와 같이 설정한다.

퍼블릭 서브넷 라우팅 테이블 구성

프라이빗 서브넷 라우팅 테이블 구성
이제 라우팅 테이블 구성은 완료했다.
프라이빗 서브넷에 EC2 를 생성하고, 구성한 방화벽을 통해 HTTP,SSH 에 접속이 되는지 확인한다.
EC2 생성 시
- EC2의 보안그룹을 SSH, HTTP 를 ANY 로 허용,
- Auto-assign public IP를 ENABLE로 설정한다.
(외부에서 접속해야 하므로 enable로 설정 필요하다.)
- key pair 도 저번에 만들어둔 것으로 선택한다. (없으면 만들면 된다.)
- advanced options 의 USER DATA 에 아래의 스크립트를 작성하여 EC2 생성 시 자동으로 아파치 웹 서버가 구성되도록 한다.
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello Test $(hostname -f)</h1>" > /var/www/html/index.html
EC2 생성 후 EC2 connect 로 접속해보면

접속은 잘 되지만, 구글 dns 로 ping 은 나가지 않는다. 방화벽 룰 그룹에 ICMP 허용 룰이 없어서이다. ping 을 쓰려면, ICMP를 허용하는 suricata 구문을 추가해야 한다.
http 통신을 모두 허용했으니 curl 의 응답값도 받을 수 있다. (https 응답은 안될 것이다. 443 이 룰에 없으니까)

브라우저의 http://[ec2 공인 ip] 접속도 잘 된다.
방화벽을 구성했다면 로그를 분석하고 이를 바탕으로 정책을 구성, 운영해야한다.
그럼 AWS 방화벽의 로그 설정을 해야하는데, AWS 방화벽 자체로는 로그를 볼 수 없다.
Cloudwatch, S3, 데이터 서비스 등에 연동해야만 로그를 볼 수 있다. 이 중에서 CloudWatch 연동이 제일 간단하고 직관적이므로, CloudWatch를 연동할 것이다.
연동전에 알아야할 것은 AWS 방화벽은 alert action 만 로그를 남긴다. 그 외 나머지는 flow 로 로그를 남기는데 flow 로 로그를 남기면 block 인지 allow 인지 알 수가 없다.
즉 alert 가 적용된 패킷에만 block, allow 로그를 확인할 수 있다. 이외 나머지 action 에는 block , allow 를 확인할 수 없다.
그래서 방화벽 policy를 구성할 때 디폴트 alert 를 모든 트래픽에 대해 적용했다
그래야만 룰 그룹 조건에 만족하지 않는 패킷들에 alert 가 적용되어 block 인지, allow 인지 확인 할 수 있을 것이기 때문이다.
그런데 pass로 룰을 구성하면 alert 가 아니기 때문에 allow 로그가 생성되지 않는다. 그저 통과만 할 뿐 allow 로그가 남지 않는 것이다. 그래서 allow 로그를 확인하기 위해 pass 룰 바로 위에 alert 룰을 따로 생성해야 한다.
그래서 로그 연동을 하기 앞서 룰 그룹을 추가로 하나 더 만들어야 한다.
그래서 pass 룰 그룹 상단에 alert 룰 그룹을 추가로 만들어 두면, alert 룰 그룹이 우선 적용된 뒤 pass 그룹에 적용되므로, alert 로그도 발생되고, pass 룰도 같이 적용된다.
(순서를 반대로 적용하면 pass 룰 먼저 적용 후 alert 가 적용되지 않을 수 있으니 유의한다.)

alert 로그를 위한 룰 그룹을 만들때
실제 적용되는 룰 그룹의 suricata 구문과 동일하게 만들되 action 부분의 pass를 alert 로만 바꿔서 생성하면 된다. (이미 만들어둔 룰 그룹은 바꿀 필요가 없고, 새로 만드는 것이다.)


방화벽 policy 설정에서 add unmanaged stateful rule groups 를 선택하면 룰 그룹을 추가할 수 있다. (unmanaged 는 개인이 만든 룰 그룹, managed 는 AWS 에서 제공하는 룰 그룹이다. AWS 에서 제공하는 룰 그룹은 지금 테스트에서 쓰지 않는다.)
alert 용도로 만들어둔 정책을 선택하고 add stateful rule group 을 선택해서 저장한다.

그리고 추가 후에 stateful 그룹 목록의 edit priority 를 선택해서, alert 룰 그룹의 우선순위를 실제 패킷을 허용, 차단 하는 룰 그룹보다 상단에 위치시킨다.
별로 어려울 것은 없다. CloudWatch 서비스, Logs 의 log groups 에 가서
create log group 으로 log group 을 만든다.

이름, 만료기간, log class 를 입력하는데 테스트 용도이므로 만료기간은 1day, log class 는 standard 로 설정한다. CREATE 로 설정을 저장,생성한다.

생성한 방화벽을 선택하면 로깅 부분이 있는데 여기서 로그 연동을 설정한다.

어차피 alert 로그를 연동할 것이므로 alert 에만 체크하고 log destination 에는
CloudWatch log group을 선택한다. CloudWatch log group 에는 생성해둔 log group 을 선택하고 save 선택해서 저장한다.
CloudWatch 로그 그룹으로 가기 전에 로그 발생을 먼저 시켜야 한다.
EC2 connect 로 접속하여 ping 도 날리고, 브라우저 http ec2 ip 로 접속을 여러차례 시도한다.
그리고 CloudWatch의 로그 그룹으로 가서 방화벽과 연동한 로그 그룹을 클릭한다.

log stream 을 보면 log_stream_created_by_aws_to_validate_log_delivery_subscriptions 이 보이는데 이것은 로그 스트림이 생성되었다고 알림을 해준 것이고 ,
실제 로그는 /aws/network-firewall/alert/FW-TEST2_2025-01-26-01 이다.
만약 log_stream_created_by_aws_to_validate_log_delivery_subscriptions 만 있고
실제 alert 로그가 보이지 않으면 search all log streams 로 로그 스트림을 전체 검색 했다가 다시 목록으로 돌아오면 된다.
생성된 alert 로그 /aws/network-firewall/alert/FW-TEST2_2025-01-26-01 를 선택하면
로그를 볼 수 있다.

allow 로그를 볼 수 있고,(signature 를 보면 msg 로 설정한 값을 볼 수 있다.)

block 로그도 볼 수 있다. (외부 8.8.8.8 로 보낸 ping 이 차단됨을 확인할 수 있다.)
CloudWatch, AWS 방화벽은 요금이 발생하므로 추후 사용할 일이 없으면 삭제하는게 좋다.
CloudWatch 는 트래픽량에 따라 요금이 발생하므로 테스트가 끝났으면 바로 연동을 중지한다.

방화벽 로그 연동 설정에서 모두 체크해제 하면 된다.
AWS 방화벽 또한 트래픽 사용량에 맞춰 요금이 발생하므로, 테스트가 끝나거나 앞으로 사용할 일이 없다면 삭제한다.
방화벽 제거를 위해선, 우선 라우팅 테이블의 타겟이 방화벽으로 설정된 레코드를 삭제해야 한다. vpce-(방화벽 id)로 설정된 라우팅 레코드를 삭제하면 된다. 그 후

방화벽 목록에 가서 삭제할 방화벽을 선택하고, 우측의 delete 를 통해 삭제하면 된다.

disable delete protection 을 클릭한 후 아래의 입력란에 delete 를 입력해서 삭제한다.
(삭제 방지에 체크 되어 있어서 버튼을 클릭해야 한다.)


AWS 방화벽 삭제 완료 !!
EC2 에가서 stop 을 통해 사용할 필요가 없는 인스턴스를 중지한다.
구성도는 글 상단에 있는 AWS 방화벽 표준 구성도와 동일하니, 참고하면 된다.