AWS 기술 블로그

AWS Network Firewall Suricata 규칙에서 Flow 키워드 사용하기

AWS Network Firewall(이하 “ANF”)은 AWS 에서 제공하는 관리형 방화벽 및 침입 탐지 차단 서비스로서 Amazon VPC(Virtual Private Network) 네트워크 환경에서 다양한 보안 기능을 제공하고 있습니다. 특히, Security GroupNetwork Access Control List를 통해 구현하기 어려운 도메인 기반 접근 제어나 사용자 요청에 포함된 다양한 페이로드 정보를 기반으로 트래픽을 제한해야하는 고객 환경에서는 꼭 필요한 서비스이기도 합니다. ANF는 최초 서비스 출시 이후 국내와 해외 고객들의 사용이 꾸준히 증가하고 있으며 다양한 신규 기능 역시 지속적으로 추가되고 있는 상태입니다. 따라서 네트워크 보안에 중요한 서비스인 ANF를 서비스 운영환경에서 보다 효율적으로 운영하는데 도움이 될 수 있도록 여러 모범 사례에 대한 글을 게시하고자 합니다. 앞으로 게시하게 될 ”AWS Network Firewall 모범 사례 시리즈“ 게시물에서는 ANF를 구축하고 운영하는데 있어 반드시 숙지해야하는 기술 항목에 대한 설명과 동시에 권장하는 설정을 소개하고 왜 그 설정을 권장하고 있는지 설명하도록 하겠습니다.

AWS Network Firewall 모범 사례 시리즈의 첫번째 게시물인 본 게시물에서는 ANF의 Suricata 규칙을 생성할 때 왜 “flow: established” 키워드를 사용해야 하는지 그 이유와 사용 사례에 대해 살펴보도록 하겠습니다.

1. ANF Suricata Compatible Rule String

ANF는 Stateless 엔진과 Stateful 엔진을 이용하여 트래픽을 제어하는 기능을 제공하고 있습니다. Stateless 엔진은 IP+Port 기반 혹은 TCP Flag 기반의 차단 기능과 함께 Packet 별 검사가 반드시 필요한 경우에 사용되며, Stateful 엔진은 IP+Port 기반 뿐만 아니라 패킷의 페이로드에 포함되어 있는 다양한 정보를 기반으로 트래픽을 제어하고자 하는 경우에 사용됩니다. AWS 에서는 Stateful 엔진의 사용을 권장하며 Stateful 엔진은 아래와 같은 여러가지 규칙 그룹 옵션을 제공하고 있습니다.

여러가지 프로토콜과 함께 IP+Port 의 조합으로 트래픽을 제어하고자 하는 사용 사례에 대해서는 Standard 규칙 그룹을 제공하고 있으며, Domain 기반의 트래픽 제어 사용 사례에 대해서는 Domain List 규칙 그룹을 제공하고 있습니다. 그리고 이 두가지 규칙 그룹을 이용하여 구성할 수 없는 사용 사례에 대해서는 Suricata Compatible Rule String 규칙 그룹을 제공하고 있습니다.

Suricata Compatible Rule String 규칙 그룹은 고객 관리형 Suricata 규칙을 관리자가 직접 생성할 수 있도록 하는 기능을 제공하고 있으며, 관리자는 이 기능을 통하여 Suricata Compatible Rule String 규칙 그룹에서 제공하는 다양한 Suricata 규칙을 생성할 수 있습니다. ANF에서 사용하는 Suricata 엔진은 오픈소스로 제공하는 Suricata 엔진을 사용하고 있습니다. 따라서 Suricata 엔진에서 제공하는 대부분의 기능을 Suricata Compatible Rule String 규칙 그룹에서도 사용할 수 있지만, 아래와 같은 몇 가지 기능은 ANF에서는 지원하지 않고 있습니다:

  • 데이터셋. “dataset” 과 “datarep” 키워드는 허용되지 않습니다.
  • ENIP/CIP 키워드는 허용되지 않습니다.
  • 파일 확장자. “File” 키워드는 허용되지 않습니다.
  • FTP-data 프로토콜 탐지 기능은 지원되지 않습니다.
  • IP 평판. “iprep” 키워드는 허용되지 않습니다.
  • Lua 스크립트는 지원되지 않습니다.
  • pass, drop, reject, alert 이외의 액션은 지원되지 않습니다.
  • SCTP 프로토콜은 지원되지 않습니다.
  • Thresholding 기능은 지원되지 않습니다.
  • IKEv2 프로토콜은 지원되지 않습니다.

ANF의 제한사항에 대한 보다 자세한 설명은 링크를 참조하시기 바랍니다.

그렇다면 Stateful 엔진의 규칙 그룹 옵션 중, Suricata Compatible Rule String 규칙 그룹을 사용하면 어떠한 이점이 있을까요? Suricata Compatible Rule String 규칙 그룹은 관리자가 다양한 키워드를 조합하여 규칙을 만드는 것을 가능하게 함으로써 조직이 원하는 다양한 트래픽 처리를 가능하도록 합니다. 예를 들어, 회사의 데이터 센터와 AWS VPC 간의 통신이 이뤄지는 환경에서 특정한 출발지 IP 및 프로토콜을 허용/차단하고, 도메인 기반의 트래픽 제어를 동시에 적용해야하는 환경이라면 여러 가지 규칙 그룹(Standard 규칙 그룹 + Domain List 규칙 그룹)을 혼용하는 것보다 Suricata Compatible Rule String 규칙 그룹을 단독으로 사용하는 것이 효율적일 수 있습니다.

또한, Suricata Compatible Rule String 규칙 그룹은 관리자가 설정 가능한 “sid” 키워드에 할당된 Signature ID 값을 이용하여 규칙에 매칭되어 허용/차단 처리된 트래픽에 대한 정보를 쉽고 편리하게 검색할 수 있는 기능을 제공한다는 점에서 관리적인 측면의 장점도 제공하고 있습니다.

(참고. Standard 규칙 그룹의 경우 “옵션” 으로 “sid” 의 값을 수정할 수 있으나 Domain List 규칙 그룹은 “sid” 값을 수정할 수 없습니다.)

2. Suricata 키워드 알아보기

그럼 이제 본격적으로 Suricata Compatible Rule String 규칙 그룹에 사용되는 Suricata 규칙 작성에 필요한 키워드에 대해 살펴보도록 하겠습니다.

Suricata 규칙은 여러 키워드를 조합하여 다양한 프로토콜에 대해 관리자가 원하는 조건을 만족하는 패턴을 작성하는 것을 가능하게 합니다. 예를 들어,

  1. IP 프로토콜에서 특정 IP 와 Port 를 기준으로 매칭되는 규칙을 작성한다거나
  2. TCP 프로토콜에서 특정 TCP Flag 를 기준으로 매칭되는 규칙을 작성한다거나
  3. HTTP 프로토콜에서 요청 Header 나 요청 Body 의 값을 기준으로 매칭되는 규칙 등을 작성할 수 있습니다.

이와 같은 Suricata 규칙을 작성하기 위해서는 Suricata 규칙에 사용되는 각 키워드의 목적과 사용방법을 숙지해야 합니다. 이 게시물은 Suricata 규칙 작성 방법에 대한 설명을 다루는 것이 주목적은 아니므로 각 키워드에 대한 상세한 설명은 생략하도록 하겠습니다. Suricata 규칙에서 사용할 수 있는 각종 키워드에 대한 자세한 사항은 이 링크를 참고하시기 바랍니다.

Suricata의 여러 키워드 중 이 게시물에서 다루게 되는 Suricata의 flow 키워드는 클라이언트/서버 간의 통신 방향과 연결 상태 등을 매칭하는데 사용되며 flow 키워드에서는 다음과 같은 옵션을 사용하여 매칭 조건을 명시할 수 있습니다:

  • to_client: 서버에서 클라이언트로 향하는 패킷을 매칭
  • to_server: 클라이언트에서 서버로 향하는 패킷을 매칭
  • from_client: 클라이언트에서 서버로 향하는 패킷을 매칭 (to_server와 동일)
  • from_server: 서버에서 클라이언트로 향하는 패킷을 매칭 (to_client와 동일)
  • established: 연결이 수립된 상태의 통신을 매칭
  • not_established: 연결이 수립되지 않은 상태의 패킷을 매칭

그 외 언급되지 않은 다른 flow 키워드는 이 링크를 참고하시기 바랍니다.

이 게시물에서 다루고자하는 Flow 키워드에서 사용하는 연결 수립(established) 상태의 판단 기준은 프로토콜에 따라 다릅니다:

  • TCP 프로토콜의 경우 3-way 핸드셰이크 완료 후 연결이 수립된 것으로 간주됩니다.
  • 다른 프로토콜(예: UDP)의 경우 양방향에서 트래픽이 관찰된 후 연결이 수립된 것으로 간주됩니다.
  • ‘flow:to_client, established’와 같이 여러 개의 flow 키워드 옵션을 조합하여 사용할 수 있습니다.

AWS에서는 ANF에서 Suricata 규칙을 사용하는 경우 ‘flow:to_server, established’ 옵션을 사용하는 것을 권장합니다.

(참고. Suricata 규칙 사용 시 ‘flow:to_server, established’ 옵션을 사용하는 것을 권장한다는 것이 Suricata 규칙 사용 시 반드시 이 옵션을 사용해야 한다는 것을 의미하지는 않습니다. 사용하는 프로토콜과 고객의 규칙 사용 목적에 따라 다른 flow 옵션을 사용해야 경우도 있으며 ‘flow:to_server, established’ 사용을 권장하는 것은 범용적인 사용 사례에 대한 것임을 참고하시기 바랍니다.)

3. flow:to_server, established 동작 방식 알아보기

아래의 Suricata 규칙을 통해 ‘flow:to_server, established’ 옵션의 동작방식을 살펴보도록 하겠습니다. 아래의 규칙이 적용된 ANF은 Strict Order 를 사용하는 정책이 적용되어 있는 상태입니다. Suricata 규칙에 사용되는 Flow 키워드에 대한 여러분의 이해를 돕기 위해 간단한 질문을 하나 드려보도록 하겠습니다.

Q: 아래의 규칙 이외에 별도의 추가로 생성되어 있는 규칙이 전혀 없다고 가정한 상태에서, VPC 외부에서 ANF을 통과하는 HTTP(Port 80)트래픽이 유입된다면 이 트래픽은 ANF에 의해 허용될까요? 차단될까요?

pass tcp any any <> any 80 (flow:to_server, established; sid:2; rev:1;)
drop tcp any any <> any 80 (sid:1; rev:1;)

위 질문에 대한 정답을 말하기 전에 각 규칙에 사용된 키워드와 옵션을 통해 각 규칙들이 어떻게 트래픽을 처리하는지 살펴보도록 하겠습니다.

참고로 현재 질문에 사용된 규칙은 “Strict Order”를 사용하는 정책에 포함되어 있는 규칙이므로 “pass” “drop”과 같은 액션의 종류는 규칙 검사의 순서에 영향을 주지 않습니다. 즉, “pass” 액션을 사용하는 첫번째 규칙, 그리고 “drop” 액션을 사용하는 두번째 규칙이 순서대로 적용되게 됩니다.

첫번째 규칙은 이미 연결이 수립된(established) 상태에서 클라이언트가 서버의 80포트로 보내는(to_server) 트래픽을 허용하라는 의미입니다. 즉, 첫번째 규칙의 경우 아래에서 보이는 것과 같이 TCP 3-way handshake가 완료된 후에 유입되는 GET이나 POST와 같은 HTTP 요청이 매칭 조건에 해당합니다.:

Client ----SYN----> Server (매칭 안됨)
Client <-SYN/ACK--- Server (매칭 안됨)
Client ----ACK----> Server (매칭 안됨)
Client ----GET----> Server (매칭 됨 - established 상태)

  • to_server: 클라이언트에서 서버로 가는 방향의 트래픽을 매칭
  • established: 이미 TCP 연결이 수립된(established) 상태의 트래픽만 매칭. 즉, TCP 3-way handshake가 완료된 후의 트래픽만 해당. SYN 패킷 같은 연결 수립 단계의 패킷은 매칭되지 않음.

두번째 규칙의 경우 명시된 flow 키워드가 따로 없기에, 아래에서 보이는 것과 같이 TCP 연결 수립 여부와 상관없이 첫 패킷(SYN)이 유입되는 순간 매칭 조건에 해당합니다:

Client ----SYN----> Server (매칭됨)
Client <-SYN/ACK--- Server
Client ----ACK----> Server
Client ----GET---> Server

위 질문에 사용된 두 가지 규칙의 매칭 흐름을 하나의 그림으로 나타내면 아래와 같습니다.

정리해보면, 위의 두 규칙이 적용되어 있는 상태에서 클라이언트가 HTTP(Port 80)요청을 전송하면, 첫 번째 규칙이 “pass” 액션이지만 “pass” 액션이 적용되기 위해서는 TCP 연결 수립 상태까지 대기되어야 하고 두번째 규칙인 “drop” 규칙은 “SYN” 패킷이 유입되는 순간 바로 적용된다는 것을 알 수 있습니다.

따라서, 질문에 사용된 두 규칙이 적용된 상태에서는 HTTP(Port 80)의 요청은 차단되게 됩니다.

4. “flow:to_server, established” 키워드의 사용 예시

앞서 “flow:to_server, established” 키워드 유무에 따른 트래픽 처리 방식 차이를 살펴보았습니다. 이번에는 이러한 flow 키워드의 트래픽 처리 방식을 활용한 문제 해결 사례를 소개해드리고자 합니다. Suricata 규칙 처리 과정에서 프로토콜에 의한 우선 순위 관련 문제가 발생할 수 있습니다. 이에 대한 해결 방법으로 “flow:to_server, established” 키워드가 사용된 예시를 살펴보도록 하겠습니다.

아래 규칙 집합(rule set)은 TLS 트래픽만을 허용하고, 다른 모든 TCP 트래픽을 차단하기 위한 의도로 작성되었습니다.

pass tls $HOME_NET any → any 443 (tls.sni; content:”.amazonaws.com”; sid:1;)
reject tcp $HOME_NET any → any 443 (sid:2;)

그러나 위 규칙을 적용하면 의도한대로 동작하지 않는 현상이 발생합니다. 과연 왜 그럴까요?

문제 해결을 위해, TLS 연결에 대해 먼저 살펴보겠습니다.

TLS는 TCP 프로토콜보다 상위 레이어에서 동작합니다. 즉, TLS 연결을 사용하기 위한 준비 작업이 하위 계층인 TCP 레벨에서 시작됩니다. TLS 사용을 위한 트래픽의 흐름을 순서대로 나타내면 다음과 같습니다:

  1. 먼저 TCP 연결이 성립됩니다 (TCP 3-way handshake)
  2. TCP 연결이 된 후에 TLS handshake가 시작됩니다.
  3. TLS handshake가 완료되면 암호화된 데이터를 주고받을 수 있습니다.

이처럼 TCP 연결로 시작하는 TLS 연결의 동작 특성을 고려했을때, 위와 같은 규칙 집합의 트래픽 처리 방식은 다음과 같습니다:

  1. TCP 패킷이 처음 들어올 때, 두번째 규칙(reject tcp)에 의해 즉시 차단됩니다.
    • Reject 규칙이 낮은 우선 순위를 가진 것처럼 보이지만 프로토콜의 우선 순위에 의해 먼저 처리되게 됩니다.
  2. 이로 인해 첫번째 규칙(pass tls)은 해당 트래픽이 TLS인지 여부를 확인할 기회조차 얻지 못하게 됩니다.

이러한 이유로, 위의 규칙 집합은 의도한대로 동작하지 않습니다.

해결 방안

기존 의도대로 TLS 트래픽만을 허용하고 다른 모든 TCP 트래픽을 차단하도록 규칙을 구성하기 위해서는, 다음과 같이 “flow: to_server, established” 키워드를 추가해야합니다.

pass tls $HOME_NET any → any 443 (tls.sni; content:”.amazonaws.com”; flow: to_server, established; sid:1;)
reject tcp $HOME_NET any → any 443 (flow: to_server, established; sid:2;)

이렇게 flow 키워드를 추가하면 TCP 연결이 완전히 수립된 상태에서만 규칙이 적용되도록 할 수 있습니다. 따라서, 상위 프로토콜(TLS) 규칙과 하위 프로토콜(TCP) 규칙이 서로 충돌하지 않고 올바르게 의도된 순서로 동작할 수 있게 됩니다.

5. 맺음말

서두에 언급한 것처럼 ANF에서는 Suricata 엔진에서 제공되는 여러가지 키워드와 옵션들을 사용하여 다양한 매칭 조건을 만족하는 규칙을 생성할 수 있습니다. 다만, Suricata 엔진은 관리자가 작성한 여러가지 규칙들을 검사하는데 과정에서 프로토콜의 우선 순위나 흐름 연결 여부와 같은 몇 가지 트래픽 원칙들을 기반으로 규칙들을 매칭합니다. 따라서 Suricata 규칙을 작성할 때에는 이와 같은 규칙 검사 조건들을 고려하여 규칙을 작성하는 것이 필요합니다. 특히, ANF에 “Strict Order” 정책을 사용하는 경우에는 규칙의 검사 순서를 모든 규칙에 대해 프로토콜의 우선 순위 없이 Top-Down 방식으로 오해하는 경우가 발생할 수 있는데 “flow: to_server, established” 키워드 옵션의 사용은 이와 같은 오해로 인한 트래픽의 잘못된 처리를 최소화하는데 도움을 줄 수 있습니다.

또한 앞서 살펴본 예시와 유사하게, ANF를 사용할때 서로 다른 규칙 그룹(Standard 규칙 그룹, Doamin List 규칙 그룹 등)을 혼용하는 경우에도 프로토콜 우선 순위에 의한 문제가 발생할 수 있습니다. 이와 같은 경우에도 Suricata Compatible Rule String 규칙 그룹에서 Flow 키워드가 포함된 규칙을 구성함으로써 의도하지 않은 트래픽 처리가 발생되는 것을 미연에 방지할 수 있습니다.

Eunsu Shin

Eunsu Shin

신은수 Security Specialist Solutions Architect 는 보안 담당 SA로서 다양한 산업군의 고객들이 AWS 환경에서 수행해야하는 규정 준수 및 인증획득(개인정보보호법, 전자금융감독규정, ISMS-P 인증 등)을 위한 기술적인 도움을 제공해드리고 있습니다. 또한, 고객이 보다 안전하게 AWS 클라우드를 구성하고 운영할 수 있도록 다양한 모범 사례 공유, AWS 보안 서비스 교육 및 기술자문 등의 업무를 수행하고 있습니다.

Minji Kim

Minji Kim

김민지 Cloud Support Associate는 Amazon VPC와 ELB 등 AWS 네트워크 서비스에 대한 이슈를 분석하고, 기술 문의를 지원하는 업무를 수행하고 있습니다.