방화벽
고친 사람 github-actions[bot]
방화벽은 네트워크 경계를 지나는 통신을 검사해 통과시킬지 버릴지 정합니다. 미리 적어 둔 규칙에 맞는 것만 들여보내고 나머지는 막습니다. 웹 프레임워크에서 인증이 필요한 구간을 가르는 설정을 방화벽이라 부르기도 합니다. 이 문서는 네트워크의 방화벽을 다룹니다.
쉽고 빠른 이해
방화벽은 네트워크의 문지기입니다. 안쪽 서버로 들어오는 통신 가운데 웹 요청만 들이고 데이터베이스가 쓰는 통로로 오는 것은 막는 식으로 씁니다.
컴퓨터는 열어 둔 통로로 오는 것을 가리지 않고 받습니다. 프로그램마다 누구를 들일지 알아서 챙기게 두면 한 군데만 빠뜨려도 뚫립니다. 그래서 가리는 일을 경계 한 곳에 모읍니다.
어떻게 도는가:
- 지나가는 패킷에서 출발지와 목적지 주소, 포트 번호, 프로토콜 종류를 읽습니다
- 규칙 목록을 위에서부터 맞춰 보고 처음 걸린 규칙대로 통과시키거나 버립니다
- 어느 규칙에도 안 걸리면 미리 정해 둔 기본 정책을 따릅니다
대가도 있습니다. 허용한 통로로 들어오는 공격은 못 가립니다. 규칙이 쌓이면 무엇이 왜 열려 있는지 아무도 모르게 됩니다. 막힌 줄 모른 채 배포하면 원인을 찾는 데 시간이 걸립니다.
상세
건물 현관의 경비실을 떠올려 봅니다. 드나드는 사람마다 어디서 왔고 어디로 가는지 묻습니다. 출입 명부에 없으면 돌려보냅니다.
방화벽은 네트워크 경계에서 오가는 통신을 규칙과 맞춰 보고 통과시키거나 버리는 기능입니다. 전용 장비로 놓이기도 하고 운영체제 안에서 도는 소프트웨어이기도 합니다. 어느 쪽이든 하는 일은 같습니다. 지나가도 되는 것을 미리 정해 두고 그 밖은 안 들입니다.
방화벽이 보는 값
패킷 앞머리에는 이 패킷이 어디서 와서 어디로 가는지가 적혀 있습니다. 이 부분이 헤더입니다. 방화벽은 헤더에 적힌 값을 규칙과 맞춥니다.
가장 흔히 쓰는 값은 넷입니다. 출발지와 목적지의 IP 주소(Internet Protocol address, 인터넷 프로토콜 주소), 포트 번호, 그리고 TCP(Transmission Control Protocol, 전송 제어 프로토콜)나 UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜) 같은 프로토콜 종류입니다.
주소는 누가 보냈고 어디로 가는지를 가릅니다. 포트 번호는 그 컴퓨터의 어느 프로그램에게 가는 것인지를 가릅니다.
프로토콜은 주고받는 방법을 미리 맞춰 둔 약속입니다. 종류까지 보는 까닭은 번호가 같아도 TCP 의 통로와 UDP 의 통로가 서로 다르기 때문입니다.
방향도 값입니다. 바깥에서 안으로 들어오는 것과 안에서 바깥으로 나가는 것에 서로 다른 규칙을 겁니다. 들어오는 것만 막고 나가는 것은 다 열어 두는 구성이 흔합니다. 그러면 안쪽이 한 번 뚫렸을 때 바깥으로 나가는 통로가 남습니다.
규칙을 맞춰 보는 순서
규칙은 목록입니다. 방화벽은 패킷 하나마다 목록을 위에서부터 훑습니다. 처음 걸린 규칙의 처분을 따릅니다. 뒤에 어떤 규칙이 남아 있어도 더 보지 않습니다.
그래서 순서가 뜻을 집니다. 넓게 허용하는 규칙을 위에 두면 그 아래의 좁은 차단 규칙은 영영 안 걸립니다.
어느 규칙에도 안 걸린 패킷은 기본 정책이 받습니다. 기본 정책은 둘 중 하나입니다. 안 걸린 것을 버리는 쪽과 들여보내는 쪽입니다.
flowchart TD
P["패킷이 도착한다"] --> R1{"첫 규칙에 걸리나"}
R1 -->|걸린다| A["그 규칙대로 통과 또는 버림"]
R1 -->|아니다| R2{"다음 규칙에 걸리나"}
R2 -->|걸린다| A
R2 -->|끝까지 안 걸린다| D["기본 정책대로 처분"]
버리는 쪽을 기본으로 두면 열어 준 것만 지나갑니다. 서비스를 띄울 때마다 규칙을 더해야 해서 손이 가지만, 깜빡 잊은 통로가 열린 채 남는 일은 없습니다. 꼭 필요한 만큼만 열어 두는 이 방식이 최소 권한 원칙을 네트워크에 옮긴 모습입니다.
버리는 것과 거절하는 것
막는 방법은 둘로 갈립니다. 둘 다 통신을 끊지만 보낸 쪽이 겪는 것이 다릅니다.
버림은 패킷을 조용히 지웁니다. 보낸 쪽에는 아무 답도 안 갑니다. 보낸 쪽은 답을 기다리다가 정해 둔 시간이 지나서야 포기합니다. 이렇게 기다리다 끝나는 것이 타임아웃입니다.
거절은 여기로는 못 간다는 답을 돌려줍니다. 보낸 쪽은 기다리지 않고 바로 실패합니다.
flowchart TD
X["막기로 정했다"] --> Y{"어떻게 막나"}
Y -->|버림| Z["답이 없다 · 보낸 쪽은 타임아웃까지 기다린다"]
Y -->|거절| W["못 간다는 답이 간다 · 보낸 쪽은 바로 실패한다"]
이 차이는 증상을 읽는 단서가 됩니다. 붙는 데 한참 걸리다 끊기면 어딘가에서 패킷이 버려지고 있는 것입니다. 곧바로 거부되면 상대까지는 닿은 것입니다. 받는 프로그램이 없거나 방화벽이 거절로 답했습니다.
바깥을 향한 통로는 버림으로 막는 구성이 흔합니다. 답을 주지 않으면 바깥에서 훑어보는 쪽이 통로가 막힌 것인지 컴퓨터가 없는 것인지 가리기 어렵습니다.
패킷 하나만 보는 방화벽과 연결을 기억하는 방화벽
앞뒤 사정을 안 보고 패킷 하나의 헤더만 규칙에 맞추는 방식이 있습니다. 이것이 패킷 필터링입니다. 규칙이 단순하고 표만 훑으면 되지만, 돌아오는 답에서 걸립니다.
안쪽 서버가 바깥 서비스를 부르면 그 답은 바깥에서 안으로 들어옵니다. 패킷 하나만 보는 방화벽에게 이 답은 바깥에서 먼저 걸어온 통신과 똑같이 보입니다. 답을 들이려면 답이 돌아올 만한 포트 범위를 통째로 열어 둬야 합니다.
그래서 오늘날의 방화벽은 지나간 연결을 기억합니다. 나가는 연결이 생기면 표에 한 줄을 적어 두고, 돌아온 패킷이 그 줄에 맞으면 들여보냅니다. 이 표가 연결 추적입니다.
sequenceDiagram
participant 서버 as 안쪽 서버
participant 방화벽
participant 밖 as 바깥 서비스
서버->>방화벽: 바깥으로 연결을 연다
Note over 방화벽: 표에 이 연결을 적는다
방화벽->>밖: 내보낸다
밖-->>방화벽: 답이 돌아온다
Note over 방화벽: 표에 적힌 연결의 답이다
방화벽-->>서버: 들여보낸다
표의 줄은 남아 있기만 하지 않습니다. 오래 아무것도 안 오간 연결은 지워집니다. 지워진 뒤에 늦게 온 패킷은 맞는 줄이 없어 버려집니다. 커넥션 풀이 붙들고 있던 연결이 오래 쉬고 나서 다음 요청에서야 끊긴 것으로 드러나는 까닭이 이것입니다.
포트 번호만으로는 못 가리는 것
포트 번호는 그 통로로 무엇이 오갈지 정해 둔 약속일 뿐입니다. 웹이 쓰기로 한 443번에 SSH(Secure Shell, 보안 셸)를 실어 내보낼 수 있습니다. 포트 번호만 보는 규칙으로는 443번에 실린 것이 웹 요청인지 SSH 인지 가르지 못합니다.
패킷 안의 내용까지 읽는 방화벽이 여기서 나옵니다. 무슨 프로토콜인지, 어떤 요청인지까지 보고 가릅니다. 이 방식이 심층 패킷 검사입니다. 웹 요청의 내용을 보고 공격으로 보이는 것을 막는 웹 애플리케이션 방화벽도 같은 갈래입니다.
대가는 둘입니다. 하나는 품입니다. 패킷마다 안을 읽으므로 헤더만 볼 때보다 손이 많이 갑니다.
다른 하나는 암호화입니다. TLS(Transport Layer Security, 전송 계층 보안)로 감싼 통신은 내용이 잠겨 있어 그대로는 못 읽습니다. 읽으려면 방화벽이 중간에서 암호를 풀고 다시 감싸야 합니다. 그러면 양 끝만 알아야 할 내용을 중간 장비가 봅니다.
방화벽이 놓이는 경계
경계가 여럿이면 방화벽도 여럿입니다. 바깥 인터넷과 안쪽 망 사이에 서는 것이 경계 방화벽입니다. 망으로 드나드는 통신을 한 군데에서 가립니다.
컴퓨터 한 대 안에서 도는 것은 호스트 방화벽입니다. 운영체제가 자기에게 오는 통신을 스스로 가립니다. 경계 방화벽을 지나 안쪽까지 들어온 통신도 여기서 한 번 더 걸립니다.
클라우드에서는 보안 그룹이라는 이름으로 만납니다. 서버마다 붙는 규칙 목록입니다. 하는 일은 호스트 방화벽과 같습니다.
flowchart TD
I["인터넷"] --> B["경계 방화벽"]
subgraph 안쪽망
W["웹 서버 · 호스트 방화벽"] --> D["데이터베이스 · 호스트 방화벽"]
end
B --> W
한 겹만 두면 그 겹이 뚫렸을 때 안쪽이 그대로 드러납니다. 겹을 나눠 두고 각 겹에서 다시 가리는 구성을 심층 방어라고 합니다.
방화벽이 막지 못하는 것
열어 준 통로로 들어오는 공격은 방화벽이 막지 못합니다. 웹 서버가 쓰는 통로는 열려 있어야 합니다. 그리로 들어온 요청이 애플리케이션의 허점을 찌르는 것이어도 규칙에는 맞습니다.
안에서 시작한 연결도 대개 나갑니다. 안쪽 컴퓨터가 한 번 장악되면 바깥으로 나가는 통신은 허용된 통로를 그대로 탑니다.
NAT(Network Address Translation, 네트워크 주소 변환)와 헷갈리기도 합니다. 주소를 바꿔 적는 장비 뒤에 있으면 바깥에서 먼저 들어오지 못합니다. 이는 안쪽 주소를 못 찾아서 생기는 결과지 무엇을 막을지 정해서 얻은 것이 아닙니다. 무엇을 들이고 무엇을 막을지 정하는 일은 방화벽이 맡습니다.
백엔드 개발자가 방화벽을 만나는 때
서비스를 띄웠는데 밖에서 안 붙으면 방화벽을 의심합니다. 서버 안에서는 붙는데 다른 컴퓨터에서 안 붙는다면 프로그램이 아니라 통로가 막힌 쪽입니다.
나가는 연결도 막힙니다. 바깥 서비스를 부르거나 패키지를 받아 오는 것이 안 되면 나가는 규칙을 봅니다. 들어오는 규칙만 손보다가 한참 헤매는 일이 잦습니다.
세 번째는 앞에서 본 유휴 연결입니다. 커넥션 풀이 오래 붙들고만 있던 연결이 연결 추적 표에서 지워지면 다음 요청이 갑자기 실패합니다. 주기적으로 작은 패킷을 흘려 줄을 살려 두거나, 풀이 오래 쉰 연결을 먼저 닫게 해서 피합니다.
관련 항목
방화벽이 패킷에서 읽는 값
IP 주소 · 포트 번호 · 패킷 · 헤더 · 프로토콜 · TCP 플래그
방화벽이 통과 여부를 정할 때 쓰는 장치
접근 제어 목록 · 패킷 필터링 · 기본 차단 정책 · 허용 목록 · 연결 추적 · 상태 테이블
방화벽이 놓이는 경계와 그 형태
경계 방화벽 · 호스트 방화벽 · 보안 그룹 · 네트워크 ACL · DMZ · 게이트웨이
방화벽 구실을 하는 제품과 도구
netfilter · iptables · nftables · ufw · pf · firewalld
패킷 내용까지 들여다보는 갈래
심층 패킷 검사 · 웹 애플리케이션 방화벽 · 프록시 · 리버스 프록시 · TLS 종료
방화벽과 같은 경계에 서는 다른 기능
NAT · 라우터 · 로드 밸런서 · VPN · 포트 포워딩 · 네트워크 분할
방화벽 때문에 생기는 증상과 진단 단서
타임아웃 · 연결 거부 · 포트 스캔 · 커넥션 풀 · 킵얼라이브 · 유휴 타임아웃
방화벽이 지키려는 보안 원칙
다른 이름: firewall · 파이어월 · 네트워크 방화벽 · 방화벽 규칙