PF(Packet Filter)는 BSD용 방화벽입니다. 원래 IPF라고 개인이 만든 공개 방화벽이 있어서, 여러 BSD 계열 UNIX에서 주로 사용하였었습니다. 다른 개발자들이 라이센스에 대해 명확하지 않은 부분에 대해서 설명 요구에 대한 응답에 만족하지 못한 오픈소스 개발자들이 새롭게 만든 방화벽이 PF입니다. 정말 너무나도 빠르게, IPF와 기능은 유사하게 만들어졌습니다. IPF는 소스는 공개였지만, 소스 분기는 허용하지 않고 원 개발자가 필요한 패치만 해서 하나의 버전을 유지하겠다고 했었습니다…
하여간 PF가 OpenBSD 개발자들에 의해서 순식간에 만들어지고, 여러개발자들이 참여가 가능했기 때문에 금방 여러가지 추가 기능들이 구현됐습니다. 오픈 소스 최고의 방화벽으로 자리 잡았고, 상용 방화벽이 갖추지 못한 좋은 기능들도 많이 가지고 있습니다.
FreeBSD에서 PF 방화벽을 사용하려면 /etc/rc.conf 에
pf_enable=”YES”
pflog_enable=”YES”
를 추가해야합니다.
정책 설정은 /etc/pf.conf 에서 합니다.
설정 파일에서 가장 중요한 부분은 pass/block이죠…
pass/block in/out (log) on 인터페이스
proto 프로토콜
from 주소/마스크비트 port 포트
to 주소/마스크비트 port 포트
1.2.3.x 에서 오는 모든 udp 패킷을 막고 싶다면…
block in proto udp from 1.2.3.0/24 to any
80포트로 오는 걸 열어주고 로그로 남기고 싶으면,
pass in log proto tcp from any to port 80 keep state
keep state하면 생성된 TCP 세션에 대해서 들어오고 나가는 패킷이 방화벽을 통과합니다.
패킷이 왔을때 위에서 부터 비교가 되며… 맨 마지막 매치가 선택됩니다.
단, quick이 설정되어 있으면 그 매치가 선택됩니다.
아래는 현재 사용중인 설정입니다. 추가적인 보안 관련 설정이 여러가지 있습니다..
ext_if=”em0″
set limit { states 80000, frags 5000 }
set block-policy drop
set skip on lo0
scrub in all
antispoof for $ext_if
block in all
block out all
table <bruteforce> persist
table <sshbruteforce> persist
block in quick log proto tcp from <bruteforce> to port 80
block in quick log proto tcp from <sshbruteforce> to port 22
pass in on $ext_if proto tcp from any to $ext_if port 22 \
flags S/SA keep state \
(max-src-conn-rate 10/30, overload <sshbruteforce> flush global)
pass in on $ext_if proto tcp from any to $ext_if port 80 \
flags S/SA synproxy state
pass in on $ext_if proto tcp from any to $ext_if port 80 \
flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 300/10, \
overload <bruteforce> flush global)
위에 설정에서 ssh나 http로 하나의 IP에서 여러개의 요청이 한번에 오면 막는 기능이 동작합니다. HTTP의 경우 최대 100개의 동시 연결, 10초간 300개 이상의 연결이 발생하게 되면 공격자로 인식하고 기존 연결을 모두 끊어버리고 연결을 막습니다.
한번 등록되면 방화벽 재시작 전에는 해당 IP에서 연결이 안됩니다. 일정 기간이 지나면 풀리게 하는 방법은 expiretable를 사용하면 가능합니다.
FreeBSD에서는
# cd /usr/ports/security/expiretable
# make install
# /usr/local/sbin/expiretable -t 2h bruteforce
2시간 이상 지난 IP를 풀어주는 명령으로 crontab에 등록해서 사용하면 됩니다.
최신 버전 PF를 사용하면 pfctl로 같은 기능을 할수 있다고 합니다.
# pfctl -t bruteforce -T expire 7200
방화벽 시작, 재시작, 설정 파일 다시 읽기, 종료 방법:
# /etc/rc.d/pf start
# /etc/rc.d/pf restart
# /etc/rc.d/pf reload
# /etc/rc.d/pf stop
# /etc/rc.d/pflog start
# /etc/rc.d/pflog stop
방화벽 로그를 실시간으로 보는 방법
쌓인 로그를 보는 방법
# tcpdump -r /var/log/pflog
방화벽 상태 보기
# pfctl -s all
# pfctl -vvs all (보다 자세한 정보 보기)
방화벽 공격 IP 보기
# pfctl -t bruteforce -T show
마지막으로… 원격에서 방화벽 잘못 설정하면 IDC로 튀어가야합니다.
신중을 기해야합니다.
한가지 터득한 방법은…
# /etc/rc.d/pf reload; sleep 15; /etc/rc.d/pf stop
restart보다는 reload가 그나마 안전합니다. reload할 때는 세션 테이블이 초기화 되지 않습니다.
DDoS의 공격의 종류가 많고 어디가 bottleneck이 되느냐에 따라 해결방법이 틀려집니다. 서버 자체의 부하를 일으켜 서비스 거부 공격을 받는 경우 PF로 많은 공격을 막을수 있습니다.
pfstat을 설치하면, PF의 여러가지 상황을 모니터링 할수 있습니다.
# cd /usr/ports/sysutils/pfstat
# make install
pfstat 홈페이지의 설정파일을 복사하고, 인터페이스명과 파일 저장 위치들만 바꿔주고
crontab에 아래처럼 등록했습니다.
# crontab -l
* * * * * /usr/local/bin/pfstat -q
*/5 * * * * /usr/local/bin/pfstat -p