요즘 공부하고 있는 iptables 를 이용한 방화벽 구축 관련하여…

 한가지 문제가 되는 부분이 있었다.

 그것은 바로 방화벽을 설정하게 되면 이상하게 네임서버 질의가 안되는 것.

 문제의 발단은 다음의 스크립트를 이용하여 방화벽을 설정하는 것 부터 시작이었다.

#!/bin/sh

IPTABLES=/sbin/iptables
MODPROBE=/sbin/modprobe

### 기존 규칙을 제거하고 체인 정책을 DROP으로 설정한다.
echo “[+] Flushing existing iptables rules…”
$IPTABLES -F
$IPTABLES -X
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
### load connection-tracking modules
$MODPROBE ip_conntrack
$MODPROBE ip_conntrack_ftp

###### INPUT 체인 ######
echo “[+] Setting up INPUT chain…”
### 상태 추적 규칙
$IPTABLES -A INPUT -m state –state INVALID -j LOG –log-prefix “DROP INVALID ” –log-ip-options –log-tcp-options
$IPTABLES -A INPUT -m state –state INVALID -j DROP
$IPTABLES -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

### ACCEPT 규칙
#ftp
$IPTABLES -A INPUT -i eth0 -p tcp –dport 20 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -i eth0 -p tcp –dport 21 –syn -m state –state NEW -j ACCEPT
#ssh
$IPTABLES -A INPUT -i eth0 -p tcp –dport 22 –syn -m state –state NEW -j ACCEPT
#whois
$IPTABLES -A INPUT -i eth0 -p tcp –dport 43 –syn -m state –state NEW -j ACCEPT
#domain
$IPTABLES -A INPUT -i eth0 -p tcp –dport 53 –syn -m state –state NEW -j ACCEPT
#http
$IPTABLES -A INPUT -i eth0 -p tcp –dport 80 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -i eth0 -p udp –dport 80 -m state –state NEW -j ACCEPT
#https
$IPTABLES -A INPUT -i eth0 -p tcp –dport 443 –syn -m state –state NEW -j ACCEPT
#rsync
$IPTABLES -A INPUT -i eth0 -p tcp –dport 873 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -i eth0 -p udp –dport 873 -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -p icmp –icmp-type echo-request -j ACCEPT
$IPTABLES -A INPUT -i ! lo -j LOG –log-prefix “DROP ” –log-ip-options –log-tcp-options

###### OUTPUT 체인 ######
echo “[+] Setting up OUTPUT chain…”

### 상태 추적 규칙
$IPTABLES -A OUTPUT -m state –state INVALID -j LOG –log-prefix “DROP INVALID ” –log-ip-options –log-tcp-options
$IPTABLES -A OUTPUT -m state –state INVALID -j DROP
$IPTABLES -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

### 외부로 나가는 연결을 허용하기 위한 ACCEPT 규칙
#ftp
$IPTABLES -A OUTPUT -p tcp –dport 20 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p tcp –dport 21 –syn -m state –state NEW -j ACCEPT
#ssh
$IPTABLES -A OUTPUT -p tcp –dport 22 –syn -m state –state NEW -j ACCEPT
#whois
$IPTABLES -A OUTPUT -p tcp –dport 43 –syn -m state –state NEW -j ACCEPT
#domain
$IPTABLES -A OUTPUT -p tcp –dport 53 –syn -m state –state NEW -j ACCEPT
#http
$IPTABLES -A OUTPUT -p tcp –dport 80 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 80 -m state –state NEW -j ACCEPT
#https
$IPTABLES -A OUTPUT -p tcp –dport 443 –syn -m state –state NEW -j ACCEPT
#rsync
$IPTABLES -A OUTPUT -p tcp –dport 873 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 873 -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p icmp –icmp-type echo-request -j ACCEPT

### 기본 OUTPUT LOG 규칙
$IPTABLES -A OUTPUT -o ! lo -j LOG –log-prefix “DROP ” –log-ip-options –log-tcp-options

 보기에는 별 문제가 없는 방화벽 스크립트이다.

 기본적으로 모든 입력에 대해 DROP 정책을 고수하고 서비스하는 특정 포트들에 대해 접근을 허가하는 내용인데… 특이점으로 ftp에 대한 포트와 rsync를 위한 포트를 개방한 부분에 있다.

 이는 동아리에서 서비스 중인 미러링 사이트 유지를 위해 필요한 부분이었기 때문에 특별히 신경썼던 부분이었다.

 해당 스크립트를 적용시킨 후, ssh 접속 및 ftp, http 접속이 정상적으로 이루어지는 것을 확인하여 아무런 문제가 없는 줄 알았다.

 하지만… 미러링을 위한 rsync 스크립트를 돌리자마자 다음의 오류를 발생하며 프로세스가 정지가 되는 것이었다.
 

rsync: getaddrinfo: releases.ubuntu.com 873: Temporary failure in name resolution
rsync error: error in socket IO (code 10) at clientserver.c(122) [receiver=3.0.3]

 에러 발생 메시지가 늘 그렇듯이 처음보는 에러메시지였다. 하지만 에러 메시지 중 익숙한 부분이 눈에 들어왔다. 바로 “getaddrinfo” 라는 부분과 “socket IO” 부분.

 그렇다. 네트워크 프로그래밍에서 주소를 받아오는 함수부분인 것이다. 다른곳도 아니고 주소를 알아내는 모듈이 실패를 했다는 메시지가 나오니 그래서..설마하는 마음으로 dig 명령어를 이용한 IP 질의를 해보았다.

 역시나였다. dig, nslookup 등등의 명령어가 먹히지 않는다. 이상했다.

 resolve 질의를 위한 부분 역시 스크립트에서는 명백히 명시를 해놓았기 때문이다. 무엇이 문제일까. 구글링 및 kldp를 비롯하여 여러곳을 뒤져보아도 속시원한 답을 찾을 수 없었다.

 단 하나, 똑같은 상황이 있었는데 네임서버 설정이 잘못되있는 경우 그런 에러가 발생한다는 것만 알 수 있었다.

 하지만 이미 네임서버는 설정이 정상적으로 되어 있는 상황이었고, 같은 네임서버를 설정해놓은 다른 보통의 서버(위의 스크립트를 적용시키지 않은)들은 아무 문제없이 질의가 이루어지는 상황이었다.

 한참….을 헤멘후에야 그 해답을 알 수 있었는데..

 그 정답은 바로 다음의 라인이었다.

$IPTABLES -A INPUT -p udp –dport 53 -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 53 -m state –state NEW -j ACCEPT

 차이를 알겠는가? 바로 프로토콜 설정부분이었다. 기존의 스크립트는 -p tcp 만을 옵션으로 하였기 때문에 udp의 경우는 방화벽에 차단당했던 것이었다.

 늘 그렇다. 알고나면 별것아닌것. 에효… 진즉에 service 파일좀 살펴볼껄… 별것아닌 에러에 이렇게 곤란을 느낀것이 부끄럽기만 하다.

Tags: ,

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.