신입 때 방화벽 룰을 짜라는 얘기를 처음 들었을 때 손이 덜덜 떨렸습니다. iptables 매뉴얼은 옵션이 100개가 넘어 보였고, 잘못 건드리면 SSH가 끊겨서 서버가 통째로 격리된다는 얘기를 여기저기서 들었거든요. 실제로 그 뒤에 몇 번 원격 서버에서 SSH가 끊겨 콜을 부른 적도 있고요. 알고 보면 기본 구조는 단순합니다. 어떤 체인에 어떤 조건을 만나면 어떻게 처리할지를 규칙 목록에 넣는 것뿐이에요. 오늘은 INPUT/OUTPUT/FORWARD가 뭐고, 최소한 방어 룰을 어떻게 짜는지 정리해볼게요.
개념 / 원리
iptables는 커널의 netfilter 위에 얹힌 유저 도구예요. 패킷이 커널 네트워크 스택을 지날 때 정해진 "체인"에 걸린 규칙을 위에서 아래로 검사합니다. 매칭되면 -j 뒤에 지정한 타겟(ACCEPT/DROP/REJECT/…)으로 처리하고 검사가 끝납니다.
가장 자주 쓰는 체인 세 개는 이렇습니다.
| 체인 | 언제 걸리나 | 대표 용도 |
|---|---|---|
| INPUT | 이 서버가 받는 패킷 | 서버 자체 보호 |
| OUTPUT | 이 서버가 보내는 패킷 | outbound 제한 |
| FORWARD | 이 서버를 거쳐가는 패킷 | 라우터·NAT 역할일 때 |
일반 서비스 서버는 INPUT만 잘 잠가도 90%가 끝납니다. 라우터·게이트웨이 역할이 아니면 FORWARD는 신경 쓸 일이 거의 없어요.
패킷을 처리하는 타겟은 셋만 알면 됩니다.
- ACCEPT: 통과.
- DROP: 조용히 버림. 상대방은 응답이 없어서 타임아웃 날 때까지 기다립니다.
- REJECT: "포트 닫힘" 응답을 보내고 버립니다. LAN 안쪽에선 REJECT가 트러블슈팅에 편하고, 외부에는 DROP이 정보 노출을 줄여 안전합니다.
기본 정책(policy)도 중요해요. 규칙에 안 걸린 패킷을 어떻게 할지 정하는데, INPUT을 DROP으로 두고 필요한 것만 ACCEPT하는 화이트리스트 방식이 표준입니다.
실전 예제
전형적인 웹 서버 최소 룰을 짜봅시다. 순서가 매우 중요합니다. 무작정 -P INPUT DROP부터 하면 SSH 접속이 끊깁니다.
# 1) 현재 룰 초기화
sudo iptables -F
sudo iptables -X
# 2) 기존 세션은 유지 (제일 먼저!)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 3) 로컬 루프백 허용
sudo iptables -A INPUT -i lo -j ACCEPT
# 4) SSH 먼저 열기 (이거 잊으면 원격 서버 격리)
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# 5) HTTP/HTTPS 열기
sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
# 6) ICMP(ping) 허용 - 원하면
sudo iptables -A INPUT -p icmp -j ACCEPT
# 7) 나머지는 다 버림
sudo iptables -A INPUT -j DROP
핵심은 ESTABLISHED,RELATED를 맨 위에 두는 것입니다. 이거 하나로 이미 맺어진 세션(SSH, DB 응답 등)이 살아있으니 다른 룰을 마음 편히 잠글 수 있어요.
규칙 확인은 이렇게 봅니다.
sudo iptables -L INPUT -v -n --line-numbers
# 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
# 2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
# 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW
# ...
재부팅 후에도 유지하려면 저장이 필요합니다. Debian/Ubuntu는 netfilter-persistent, RHEL은 iptables-services를 씁니다.
sudo apt install iptables-persistent
sudo netfilter-persistent save
주의할 점
첫째, -P INPUT DROP은 마지막에. 정책을 먼저 DROP으로 바꾸고 SSH 룰을 넣기 시작하면 그 순간 접속이 끊깁니다. 무조건 -A INPUT ... ACCEPT 규칙을 다 넣은 뒤 마지막에 정책을 바꾸거나, 아예 정책은 ACCEPT로 두고 마지막 규칙을 -j DROP으로 두세요.
둘째, 원격 작업 시 안전장치. SSH가 끊겨 격리되는 걸 막으려면 크론에 몇 분 뒤 iptables -F를 예약하고 작업하세요. 작업 성공하면 크론을 지우고, 실패해서 접속이 끊기면 몇 분 뒤 룰이 초기화되니 다시 들어갈 수 있습니다.
셋째, 규칙 순서는 위에서 아래. 위쪽에서 매칭되면 아래는 안 봅니다. 그래서 특정 IP 차단 룰은 일반 허용 룰보다 위에 있어야 합니다.
넷째, iptables vs nftables. 최신 배포판(RHEL 9, Ubuntu 22.04 이상)은 내부적으로 nftables를 쓰고 iptables 명령은 호환 레이어입니다. 학습 목적이면 iptables로 시작해도 되지만, 신규 시스템은 처음부터 nft 명령을 쓰는 걸 권장하는 배포판이 늘고 있어요.
다섯째, 컨테이너·클라우드에선 별도 방화벽 존재. Docker는 자체 iptables 룰을 자동으로 심고, AWS/GCP는 Security Group·VPC Firewall이 앞단에 있습니다. 이걸 안 보고 iptables만 만지면 왜 안 되는지 답답한 상황이 나옵니다.
마무리
정리하면 세 줄입니다.
- INPUT을 잘 잠그면 서버 자체 방어는 대부분 끝난다. FORWARD는 라우터일 때만 신경.
- 규칙 순서는 (ESTABLISHED,RELATED) → (lo) → (SSH) → (필요 포트) → (DROP), 정책은 마지막에.
- 원격 작업 시 크론 안전장치, 재부팅 후 유지는
netfilter-persistent같은 도구로 저장.
'IT·리눅스 > 리눅스' 카테고리의 다른 글
| 리눅스 메모리 - RSS, VSZ, Shared 실제로 얼마를 쓰는 걸까 (0) | 2026.07.06 |
|---|---|
| tmux 입문 - SSH 연결이 끊겨도 작업 살리는 법 (0) | 2026.06.19 |
| 프로세스 vs 스레드 - 리눅스의 PID, TID, PPID 한 번에 정리 (0) | 2026.06.18 |
| find 명령어 실전 활용 - 운영에서 진짜 쓰는 10가지 패턴 (0) | 2026.06.17 |
| 디스크 I/O 모니터링 - iostat과 iotop으로 병목 잡기 (0) | 2026.06.16 |