Solaris

IPFilter 방화벽 솔라리스 사용법

알 수 없는 사용자 2008. 3. 5.
728x90

윈디하나의 솔라나라: IPFILTER

IPFilter

설치할 IPFilter 버전

  • IPFilter 4.1.10

들어가기 전에

  • IPFilter는 솔라리스에서 무료로 사용할 수 있는 방화벽이며 솔라리스 10에는 기본으로 포함되어있다. (방화벽 소프트웨어인 SunScreen을 대체할 예정이다) 상용 방화벽 장비보다는 못하지만 공개 소스치고는 성능과 기능이 매우좋다.
  • 최종 갱신일: 2005-12-14
  • 이 문서는 http://www.solanara.net/(새 창으로 열기) 에서 최신버전을 구할 수 있다.

1. 설치 전에

PATH 경로를 지정해준다.
root@wl ~ # vi .profileif [ -d /opt/ipf/ ]then  PATH=$PATH:/opt/ipf/bin; export $PATH;fi

2. IPFilter 설치

* IPFIlter는 http://coombs.anu.edu.au/~avalon/(새 창으로 열기) 또는 ftp://coombs.anu.edu.au/pub/net/ip-filter/ 받을 수 있다. ip_fil4.1.10.tar.gz(새 창으로 열기)http://coombs.anu.edu.au/~avalon/ipf-mentat.html(새 창으로 열기)에서 pfil-2.1.7.tar.gz(새 창으로 열기)을 받아야 한다.
* 솔라리스 10 부터는 IPFilter가 내장되어있으므로 설치과정이 필요 없다.
root@wl ~ # gtar xvfz ip_fil4.1.10.tar.gzroot@wl ~ # gtar xvfz pfil-2.1.7.tar.gzroot@wl ~ # cd pfilroot@wl ~/pfil # /usr/ccs/bin/make packageroot@wl ~/pfil # pkgadd -d /tmp/pfil.pkg # pfil.pkg파일을 보관해 다른 시스템에 설치해도 된다.# 시스템에 설치되어있는 NIC 종류별로 (lo제외) 한줄씩 /etc/opt/pfil/iu.ap에 등록되어있어야 한다.# 같은 NIC가 두개라도 한 종류이므로 한줄만 들어가게 된다.root@wl ~/pfil # ifconfig -alo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1        inet 127.0.0.1 netmask ff000000pcn0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2        inet 192.168.0.11 netmask ffffff00 broadcast 192.168.0.255        ether 0:c:29:d4:e0:bdroot@wl ~/pfil # cat /etc/opt/pfil/iu.ap        pcn     -1      0       pfilroot@wl ~/pfil # cd ..root@wl ~ # cd ip_fil4.1.10root@wl ~/ip_fil4.1.10 # /usr/ccs/bin/make solarisroot@wl ~/ip_fil4.1.10 # cd SunOS5root@wl ~/ip_fil4.1.10/SunOS5 # /usr/ccs/bin/make packageroot@wl ~/ip_fil4.1.10/SunOS5 # sync; sync; reboot # 재시작한다
make package하면 자동으로 패키지가 생성되고 인스톨 된다. SunOS5디렉토리에 ipf.pkg 파일이 생성되는데 다른 시스템에는 이 패키지 파일을 사용해도 된다. 바이너리는 /opt/ipf에, 설정파일은 /etc/opt/ipf에 있다. IPFilter를 설치한 후 재시작해야 한다.
root@wl ~ # /etc/init.d/ipfboot start # 시작하기. /etc/rc2.d/S65ipfboot에 등록되어있다.# ipf를 시작한 상태에서 올바르게 설치되었는지 확인한다.root@wl ~ # ndd /dev/pfil qif_statusifname ill q OTHERQ ipmp num sap hl nr nw bad copy copyfail drop notip nodata notdataQIF1 0x0 0xd40d2cf0 0xd40d2d74 0x0 1 806 0 3 14 0 0 0 0 0 0 0pcn0 0xd3c49a9c 0xd4054180 0xd4054204 0x0 0 800 14 695 572 0 0 0 0 0 0 0root@wl ~/pfil # strconf < /dev/pcnpfilpcnroot@wl ~ #

3. 기초적인 사용방법

- 기본적으로 방화벽은 들어오는 패킷을 막는데 사용한다. IPFilter의 공식 사이트에 있는 매뉴얼과 튜토리얼, 하우투문서(특히 튜토리얼 문서는 꼭 읽어보자)를 읽어야 하며, 네트워크과 TCP/IP에 대한 최소한의 지식이 필요하다. /opt/ipf/examples에 좋은 예제가 있으니 참고하자.
- 서드 파티로 IPFilter에서 설정파일, 즉 룰셋을 생성시켜주는 프로그램이 있다.
- 다음은 필자가 간단하게 쓴 예제이다. 필자의 모든 예제에서 호스트의 IP는 192.168.0.11, NIC 장치이름은 pcn0이다.
root@wl # ifconfig -alo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1        inet 127.0.0.1 netmask ff000000pcn0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2        inet 192.168.0.11 netmask ffffff00 broadcast 192.168.0.255        ether 0:c:29:d4:e0:bd
  1. 모든 패킷 막기
    root@wl # vi /etc/opt/ipf/ipf.confblock in allblock out allroot@wl # /etc/init.d/ipfboot reload
    block: 패킷을 블로킹.
    in: 인바운드 패킷을 지정.
    all: 모든 패킷을 지정.
    out: 아웃바운드 패킷을 지정.

    - 따라서 [block in all]은 들어오는(in) 모든(all) 패킷을 블로킹(block)한다. 또한 나가는(out) 모든(all)패킷을 블로킹(block) 한다. 는 뜻이 된다.
    - 이 이후부터는 ipf.conf의 내용만 적도록 하겠다. [root@wl # vi /etc/opt/ipf/ipf.conf]와 [root@wl # /etc/init.d/ipfboot reload]를 삭제하고 예를 들 것이다.
  2. 들어오는 패킷은 막고 나가는 패킷은 허용
    위와 같이 하게 되면 인터넷이 안된다. 적어도 워크스테이션에서 파이어폭스를 띄워 인터넷은 되어야 작업이 가능할 것이다. 따라서 다음과 같이 수정해본다.
    block in allpass out all
    pass: 패킷을 통과시킴.

    - pass out all부분만 바뀌었다. 나가는(out) 모든(all)패킷을 통과(pass)시킨다.
  3. 외부 접속및 데이터 교환 허용
    위와 같이 해도 인터넷 안된다. 나가는 패킷은 허용되어있는데 들어오는 패킷은 허용되어있지 않기 때문이다. 즉, 데이터를 받을 수가 없다. 우리가 원하는것을 조금 다시 써본다면, 워크스테이션에서 접속을 시도한 곳은 데이터 교환이 되고 외부에서 워크스테이션으로 접속을 시도한 것은 모두 블로킹하도록 하자. 다음과 같이 수정한다.
    block in allpass out on pcn0 proto tcp from any to any keep statepass out on pcn0 proto udp from any to any keep statepass out on pcn0 proto icmp from any to any keep state
    on: 다음에 오는 인터페이스를 지정한다.
    proto: 다음에 오는 프로토콜을 지정한다.
    from: 소스 주소
    to: 목적지 주소
    keep state: 상태 유지

    [pass out on pcn0 proto tcp from any to any keep state]는 pcn0인터페이스(on pcn0)에서 모든곳에서(from any) 모든곳으로(to any)으로 가는 tcp 프로토콜을(proto tcp) 아웃바운드 패킷(out)에 한해 상태를 유지하면서(keep state) 허용한다는 뜻이 된다. 즉 접속한 상태는 허용하면서, 데이터 교환은 되는 것이다.
  4. 성능향상
    IPF는 룰을 위에서부터 차례대로 검사한다. (IPF뿐만 아니라 모든 방화벽이 그렇다) 시스템에 있는 NIC로 패킷이 들어오면 ipf.conf에 있는 모든 룰을 위에서부터 하나하나 확인해보는 것이다. 자. 생각해보자. 위의 글에서, 첫번째룰(block in all)에서 인바운드 패킷을 막았다. 그리고 룰의 내용으로 보아 아래의 룰은 더이상 확인할 필요 없다. 그러나 단순한 IPF는 아래의 룰도 확인한다. 한가지 예를 들어보자.
    block in allpass out on pcn0 proto tcp from any to any keep statepass out on pcn0 proto udp from any to any keep statepass in all
    위와 같은 룰이 있다면 처음엔 막으려고 생각했는데, 마지막줄에서 모두 통과시킨다. 결과적으로 인바운드 패킷은 통과한다. 물론 위 예는 극단적인 것이다. 따라서 더이상 룰을 확인할 필요 없다는 것을 IPF에 명시해줘야 한다. 그 지시어가 quick이다.
    block in quick allpass out on pcn0 proto tcp from any to any keep statepass out on pcn0 proto udp from any to any keep statepass out on pcn0 proto icmp from any to any keep statepass in all
    quick: 빨리. 더이상 아래의 룰을 확인할 필요 없다.

    - 첫번째 줄에 quick 지시어를 추가했다. 모든 인바운드 패킷은 첫번째의 룰에서 블록/통과 여부가 블록으로 결정된다. quick지시어가 있기 때문에 이 룰을 만족한 모든 패킷은 아래의 룰을 확인하지 않는다. 마지막 줄에 pass in all이 있지만 첫번째 룰만 보고 더이상 확인하지 않기 때문에 결과적으로 패킷은 블록된다.
    - 성능향상을 위해서는 quick를 잘 써야 한다. 자주 사용될 룰을 위로 올리는 것이 ipf 성능향상의 지름길이다.
    - [pass out quick on pcn0 proto icmp from any to any keep state]이란 룰에서 붉은색 글자는 동작방식을, 파란색 글자는 패킷의 조건을 나타낸다. 파란색 글자의 내용과 일치하는 패킷에 대해 붉은색 글자로 된 내용을 수행한다. 그것이 IPF의 동작 방식이다.
  5. 외부에서 웹서버(80번 포트) 접속.
    pass in quick on pcn0 proto tcp from any to any port=80 keep stateblock in quick allpass out on pcn0 proto tcp from any to any keep statepass out on pcn0 proto udp from any to any keep statepass out on pcn0 proto icmp from any to any keep state
    port: 포트 번호

    - [to any port=80] 부분이 목적지의 포트 80에 해당하는 패킷임을 가리킨다.
  6. 192.168.0.8에서만 ftp에 접속하게 하기: ftp의 포트는 21번이다.
    root@wl # vi /etc/opt/ipf/ipf.confpass in quick on pcn0 from 192.168.0.8 to 192.168.0.11 port=21block in quick on pcn0 from any to 192.168.0.11 port=21root@wl # /etc/init.d/ipfboot reload
  7. ping 막기. ping은 ICMP프로토콜의 ECHO를 사용한다. 이 프로토콜에 대해 응답하지 않도록 하면 된다. 아래 예제는 들어오는 프로토콜을 무시하도록 했다. 다른 방법으로는 icmp-return 패킷을 잡아 블록하는 방법도 있다.
    block in quick on pcn0 proto icmp from any to any icmp-type echo
  8. 어떠한 패킷이 블록되었는지 확인하기 위해 로깅을 해야할 필요가 있다. 이때에는 다음과 같이 한다.
    root@wl # vi /etc/opt/ipf/ipf.confblock in log quick on pcn0 from any to any # in 또는 out 뒤에 log라는 단어를 추가하면 된다.root@wl # /etc/init.d/ipfboot reloadroot@wl # /opt/ipf/bin/ipmon # 로그 보기01/01/2005 00:00:00.000000 pcn0 @0:1 b xxx.xxx.xxx.xxx,ppp -> xxx.xxx.xxx.xxx,ppp PR udp len 20 76 IN mbcast-------------------------1 ---2 ---3 4 -----------------------------------------5 -----6 --------7 --------81. 패킷 도달 날짜 및 시간2. 패킷이 처리된 인터페이스 이름3. 룰 이름. 0번째 그룹(기본그룹)의 1번째 룰.4. Block, Pass의 앞글자.5. 소스주소,포트 -> 목적지주소,포트6. [PRotocol 프로토콜이름 또는 번호]7. [LENth 헤더길이 총길이]8. 추가 정보Ctrl+Croot@wl #

4. NAT

  1. 흔히말하는 [IP공유기]의 원리가 바로 NAT이다. Network Address Translator의 약어로 사설 IP를 시스템에 설정된 IP로 바꿔서(Translate) 전송해준다. 아래의 예제에서 pcn1은 리얼 IP를 가진 인터페이스의 이름이다. (사설 IP를 가진 인터페이스의 이름은 NAT를 구성할 때 알 필요 없다)
    root@wl ~ # vi /etc/rc2.d/S69inet        [ ! -x /usr/sbin/in.routed ] || /usr/sbin/in.routedelse        /usr/sbin/ndd -set /dev/ip ip_forwarding 1 1)firoot@wl ~ # /usr/sbin/ndd -set /dev/ip ip_forwarding 1root@wl ~ # vi /etc/opt/ipf/ipnat.confmap pcn1 192.168.0.0/16 -> 0.0.0.0/32 proxy port ftp ftp/tcpmap pcn1 192.168.0.0/16 -> 0.0.0.0/32root@wl ~ # /etc/init.d/ipfboot reload
    1) 솔라리스 9 x86 u7의 경우 223번째 라인에 있다. 타 시스템은 라인 위치가 다를 수 있다. [/usr/sbin/ndd -get /dev/ip ip_forwarding] 명령을 내린 후 [0]이라 나오면 NAT가 작동하지 않는다.
    192.168.0.0/16 아이피를 가진 시스템에서 오는 패킷은 pcn1을 통해, pcn1이 가진 리얼 아이피로 바뀌어 재 전송될 것이다. 만약 pcn1이 두개 이상의 아이피를 가졌다면 두가지중 한가지 IP로 바뀌어서 전송된다. 한개의 아이피만 사용하려면 0.0.0.0/32가 아니라 xxx.xxx.xxx.xxx/32로 써주면 된다. 만약 두개 이상의 아이피중 하나로 보내도록 하려면 xxx.xxx.xxx.xxx/16 과 같이 써 주면 된다. [proxy port ftp ftp/tcp] 부분은 192.168.0.0/16을 가진 시스템에서 ftp를 port방식으로 사용하기 위해 필요하다. ftp를 pasv방식으로 사용한다면 지워도 된다.

  2. 포트 포워딩은 rdr 명령을이용한다. 아래에 예제는 pcn1 인터페이스의 80포트로 오는 모든 패킷을 192.168.0.3번으로 포워딩 하는 것이다.
    root@maid /etc/opt/ipf # cat ipnat.confmap pcn1 192.168.0.0/16 -> 0.0.0.0/32 proxy port ftp ftp/tcpmap pcn1 192.168.0.0/16 -> 0.0.0.0/32rdr pcn1 0.0.0.0/0 port 80 -> 192.168.0.3 port 80root@wl ~ # /etc/init.d/ipfboot reload
  3. 포트포워딩시 보낼IP와 포트 콤마(,)를 이용해 로드밸런싱을 구현할 수 있다.(로드 밸런싱 알고리즘은 Round Robin이며 Failover와 같은 기능은 지원되지 않는다)
    rdr pcn1 0.0.0.0/0 port 80 -> 192.168.0.3, 192.168.0.4, 192.168.0.5 port 80
    pcn1, 80포트로 들어오는 패킷은 192.168.0.3, 192.168.0.4, 192.168.0.5으로 분산되어 전송된다.

5. 참고

  1. 주로 사용하는 포트 번호

    내용              포트FTP DATA           20FTP                21SSH                22 (TCP/UDP)TELNET             23SMTP(SENDMAIL)     25DOMAIN(BIND)       53 (TCP/UDP)HTTP               80POP3              110RPC               111 (TCP/UDP)SFTP              115 NetBIOS Name      137 (TCP/UDP)NetBIOS Datagram  138 (TCP/UDP)NetBIOS Session   139 (TCP/UDP)IMAP              143SNMP              161 (UDP)SNMP Trap         162 (UDP)IRC               194SSL               443SMB               445Syslog            514 (UDP)ORACLE           1521NFS              2049 (TCP/UDP)MySQL            3306Terminal Service 3389PCAnyWhere       5631PCAnyWhere       5632 (UDP)X-Window         6000 (TCP/UDP)WEB CACHE        8080 (TCP/UDP)
    - 포트 번호는 각 어플리케이션의 설정을 통해 변경할 수 있다.
    - /etc/services 파일에 더 많은 내용이 들어있다.
  2. netstat 용 상태 변화 차트 (TCP 접속시)

    SERVER> →CLOSED1→LISTEN2→SYN_RCVD4→ESTABLISHED6CLIENT> →CLOSED1→SYN_SENT3→ESTABLISHED5
    1어떠한 접속 요청도 없는 상태이다. netstat 에서는 CLOSED라는 상태는 표시되지 않는다.
    2서버쪽에서 포트를 오픈한 상태이다. 오픈된 포트는 LISTEN으로 표시된다.
    3클라이언트에서 연결요청패킷(SYN패킷)을 보낸 상태이다.
    4클라이언트에서 보낸 연결요청패킷에 대해 응답패킷(SYN-ACK패킷)을 보낸 상태이다.
    5서버에서 준 응답패킷에 대해 응답패킷(ACK패킷)을 보낸 후 바로 ESTABLISHED 상태로 넘어간다.
    6클라이언트에서 보낸 응답패킷을 받으면 바로 ESTABLISHED 상태로 넘어간다.

    ※ 보낸 패킷 위주로 다시 정리하자면
    1) 클라이언트에서 SYN 패킷 전송
    2) 서버에서 SYN-ACK 전송
    3) 클라이언트에서 ACK 전송
    위와 같이 되며 이 3단계를 3-way handshake 라 한다.
  3. netstat 용 상태 변화 차트 (TCP 접속 해제시)

    SERVER> →ESTABLISHED1→CLOSE_WAIT3→LAST_ACK6→CLOSE8CLIENT> →ESTABLISHED1→FIN_WAIT_12→FIN_WAIT_24→TIME_WAIT5→CLOSE7
    1접속된 상태
    2접속종료요청패킷(FIN-ACK패킷) 전송한 상태
    3접속종료요청패킷받은 후 응답패킷(ACK패킷) 전송한 상태
    4응답패킷을 받은 상태
    5응답패킷만 받고 두번재 응답패킷(FIN-ACK패킷)을 받지 못한 상태. FIN_WAIT_2에서 일정시간동안 FIN-ACK패킷을 받지 못하면 TIME_WAIT상태로 된다.
    6응답패킷(FIN-ACK)패킷을 보낸 상태.
    7FIN_WAIT_2 또는 TIME_WAIT 상태에서 6에서 전송한 FIN-ACK를 받았거나, TIME_WAIT상태에서 일정 시간이 지났을때 해당된다. FIN-ACK를 받았다면 ACK 패킷를 보낸다.
    8ACK패킷을 받았거나 일정한 LAST_ACK에서 일정한 시간이 지나면 CLOSE상태로 된다

    ※ 보낸 패킷 위주로 다시 정리하자면
    1) 클라이언트에서 FIN-ACK 패킷 전송
    2) 서버에서 ACK패킷 전송
    3) 서버에서 FIN-ACK 패킷 전송
    4) 클라이언트에서 ACK 패킷 전송
    위와같이 4단계로 진행된다.
    NETSTAT에서 FIN_WAIT_2, TIME_WAIT가 많은 경우 어플리케이션의 오류일 확률이 있다. 양측에서 명시적으로 커넥션을 종료 해줘야 기다리는 시간을 줄일 수 있다.
  4. 주요 ICMP 타입 및 코드, 예약어, 설명

    http://www.iana.org/assignments/icmp-parameters 에서 발췌
    이름             타입    코드  ipfilter예약어 설명ICMP_ECHOREPLY      0       0  echorep        Ping 응답.ICMP_UNREACH        3       4  needfrag       최적의 MTU 세팅을 위해 사용됨.ICMP_ECHO           8       0  echo           Ping 요청.ICMP_TIMXCEED      11       0  timex          TTL 만료시 사용됨. traceroute 또는 tracert에서 사용.
  5. 참고 웹사이트

    http://www.phildev.net/ipf/ (IPFilter FAQ)
    http://coombs.anu.edu.au/~avalon/flc.html (Filter Language Compiler)
    http://inc2.com/isba/ (ISBA: 웹기반 룰셋 관리)
    http://www.fwbuilder.org/ (Firewall Builder: 룰셋 관리)
728x90

댓글