'iptables'에 해당되는 글 5건

  1. 2009/04/28
    SSH의 Brute Force Attak을 막기
  2. 2009/04/27
    DoS 공격 방어 모듈 mod_evasive 설치기 (1)
  3. 2009/04/27
    CentOS 5.3 + Kernel 2.6.29.1 + iptables 의 connlimit 모듈 설치하기 (2)
  4. 2009/04/26
    iptables에 대한 이모저모
  5. 2009/04/26
    SSH포트를 변경하기
가장 무식하지만서도 가장 확실한 SSH의 Brute Force Attack을 막기

SSH Brute Force Attack이란 흔한 사용자 이름과 암호로 ssh를 계속 접속해서 해킹을 시도하는 방법으로 잘못 이용되었을 경우 악영향을 끼친다. 기본으로 SSH 포트를 바꾸어버려 어느정도 SSH BFA를 막을 수도 있겠지만 확실한 해결책이 못된다.

방어방법
1. 강한 비밀번호 설정
2. RSA 인증 방식 사용
3. iptables를 이용한 패킷 Drop
4. sshd 로그를 이용하여 공격을 막기

1. 강한 비밀번호 설정
웬만하면 쉬운 비밀번호나 알아내기 쉬운 비밀번호를 쓰지 않도록 하는것이 좋다. 이미 쉬운비밀번호나 알아내기 쉬운 비밀번호들은 해커들의 Dic파일속에 존재하기 때문에 BFA를 몇시간째 돌리고 있으면 인츰 비밀번호가 깨질 수 있다. 특정된 구절의 이니셜을 이용하여 비밀번호를 설정하면 가장 좋다. 아니면 한글 사용자일 경우 다른 분의 이름 영문자타법에 특수문자 조합으로 설정하며 되겠다.
우점: 너무 심플하다.
결점: 비밀번호를 바꾸어도 BFA때문에 생기는 시스템 부하를 줄일수 없다.

2. RSA 인증 방식
기존에 비밀번호를 통한 인증방식보다 좀 더 고급적인 인증방식이다. 이런 방식으로 인증방식으로 바꾸면 일반 비밀번호를 통한 해킹은 전혀 의미가 없게 된다. ^^

① ssh-keygen -t rsa를 이용하여 RSA 키를 새로 생성한다. 위 명령어를 실행하면 /home/username/.ssh/id_rsa (private 키) and /home/username/.ssh/id_rsa.pub (public 키)가 생성된다.

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
32-digit_hexadecimal_fingerprint username@hostname

② ssh 클라이언트 측 /home/username/.ssh/authorized_keys파일속에 기존에 만들어진 키들을 조합하여 넣는다. 알다싶이 이파일속에는 여러가지 public키들이 위치하여 이런 키들에 대한 관리가 용이해질 수 있다.

# cat /home/username/.ssh/id_rsa.pub >> /home/username/.ssh/authorized_keys

이렇게 생성된 authorized_keys파일을 ssh클라이언트측에 저장하여 매번 ssh접속시 사용 할 수가 있다. 위에 든 예제는 Linux상에서 public 키를 이용하여 인증하는 방식이고 윈도우에서 접속하려면 위 방식과 좀 다르다. 일단 쉘접속 툴로 많이 사용되는 SecureCRT에서 RSA 인증을 하는 과정을 보여주면 다음과 같다.
SecureCRT상에서 SSH세션을 새로 생성해준다. 다음 Session Option->Connection->SSH2 를 클릭하면 다음과 같은 대화창이 뜰거다.



위 대화창에서 볼 수 있다싶이 Authentication 방식에서 password란이 체크가 되지 않았다. Default값으로 password가 체크되어있을 것이다. 체크를 해제하고 Publickey를 선택한 상태에서 옆에 Properties버튼을 클릭하여 이미 생성한 RSA Public 키를 불러 들여오자.



단 주의할 점은 서버상 유저 루트 디렉토리 퍼미션이 700으로 설정이 되어야 정확히 인증이 된다. (이점은 좀 이상하다. 하지만 퍼미션을 707로설정하고 로그인을 시도한 결과 인증을 받을 수 없었다.)

③ 서버측 /home/username/.ssh/id_rsa 여기에는 이미 private 키가 생성이 되었으므로 별도의 작업이 필요 없다.

④ 마지막으로 /etc/ssh/sshd_config파일을 수정하여 비밀번호를 통한 인증방식을 무효화 한다. 또한 RSA Authentication 인증방식을 Yes을 바꾸어주고 주석문속에 해제한다.
마지막으로 service sshd restart하여 ssh데몬을 재시작 해준다.
우점: 보안이 상당히 믿음직스럽다. 일반 password방식보다는 한단계 업그레이드 된 인증 방식이다. 또한 password를 통한 무단 Brute Force Attack을 줄일 수 있다.
결점: 서버접속 할려면 public key를 갖고 있어야 할 뿐만 아니라 passphrase를 알고 있어야 한다. RSA인증 방식에 대한 이해를 못한 유저들은 이런 키를 자기절로 생성하여 쓸수 없으므로 다른 사람의 도움이 필요할것이다.

3. iptables를 이용한 패킷 Drop

① 정말로 약한 암호를 사용하는 사용자가 있을 경우 해당 계정이 해킹당할 수 있으며, 이 해킹당한 계정으로 로컬 커널 익스플로잇 등을 사용해서 루트를 빼앗길 수도 있다. 되도록이면 로컬 사용자를 적게 만들고 또한 만들었으면 비밀번호를 복잡하게 설정하여 이런 BFA를 어느정도 막을 수 있어야 한다. 하지만 해커가 사용하고 있는 Dictionary가 막강하면 암호를 복잡하게 만들었다 할지라도 뚤릴수 밖에 없게 된다.

② 그렇지 않더라도, 사용자 인증 로그(auth.log)에 짧은 시간 내에 수많은 실패 로그가 쌓여 다른 로그를 보는 데 방해가 될 수 있다.

③ 접속을 받는 동안 SSH 데몬이 암호학적 계산을 해야 하므로 시스템 자원을 소모할수도 있다.

iptables 는 리눅스 커널에 기본적으로 포함되어 있는 방화벽으로, 아주 다양한 방화벽 규칙을 만들 수 있으며, iptables 모듈을 사용해서 기능을 확장할 수도 있다. 다음은 iptables로 SSH Brute Force Attack을 막는 간단한 규칙이다. 이 규칙은 iptables 기본 모듈인 state와 recent를 사용한다.

state 모듈과 recent 모듈은 man 페이지에 자세하게 문서화되어 있기 때문에 문서를 참조하면 구체적인 사용법데 대하여 알수 있으므로 여기서는 생략하겠다. state 모듈은 언제 접속이 시작되고 끝나는지 추적할 수 있게 하고, recent 모듈은 IP 주소의 목록을 만들고 최근 접속 시간을 기록할 수 있게 한다.

규칙은 ssh 포트로 20초간 5회 이상 접속을 시도하면 10분간 접속을 차단하는 것이다.

우선 blacklist와 ssh 체인을 만든다.

# iptables -N blacklist
# iptables -N ssh

INPUT 체인에서 state 모듈로 ssh 포트인 22번 포트에 접속이 시작되면 ssh 체인으로 보낸다.

# iptables -A INPUT -m state --state NEW -p tcp --dport ssh -j ssh

blacklist 체인에서는 recent 모듈로 "blacklist"라는 목록에 접속 주소를 기록하고 접속을 거부한다.

# iptables -A blacklist -m recent --set --name blacklist
# iptables -A blacklist -j REJECT

규칙의 핵심인 ssh 체인은 다음과 같다.

# iptables -A ssh -m recent --update --seconds 600 --hitcount 1 --name blacklist -j REJECT
# iptables -A ssh -m recent --set --name ssh
# iptables -A ssh -m recent --update --seconds 20 --hitcount 5 --name ssh -j blacklist
# iptables -A ssh -j ACCEPT

이 규칙을 순서대로 설명하면 다음과 같다.
첫 번째 규칙은 접속 주소가 이미 "blacklist"에 들어 있고, 지난 10분간 1회 이상 접속이 있었으면 접속을 거부한다.
두 번째 규칙은 접속 주소를 "ssh" 목록에 기록한다.
세 번째 규칙은 접속 주소가 이미 "ssh" 목록에 들어 있고, 지난 20초간 5회 이상 접속이 있었으면 blacklist 체인으로 보낸다.
네 번째 규칙은 여기까지 통과한 경우 ssh 접속을 허락한다.

따라서 전체 스크립트는 다음과 같이 된다.

iptables -N blacklist
iptables -N ssh
iptables -A INPUT -m state --state NEW -p tcp --dport ssh -j ssh
iptables -A blacklist -m recent --set --name blacklist
iptables -A blacklist -j REJECT
iptables -A ssh -m recent --update --seconds 600 --hitcount 1 --name blacklist -j REJECT
iptables -A ssh -m recent --set --name ssh
iptables -A ssh -m recent --update --seconds 20 --hitcount 5 --name ssh -j blacklist
iptables -A ssh -j ACCEPT

4. sshd 로그를 이용하여 공격을 막기
서버에 들어오는 ssh 공격에 대하여 sshd 데몬은 그것들을 특정된 로그파일에 저장해주고 있는데 이렇게 생성된 파일을 참조하고 몇가지 프로그램을 조합하여 사용하는 것을 통하여 ssh 공격을 막을 수 있다.

① sshdfilter는 iptables를 이용하여 블럭을 한다. 동작방식은 상당히 간단한데 firewall 룰을 iptables에 추가하여 특정된 공격을 막는것이다. 이 방식으로 공격을 막기위하여 sshd데몬대신 sshdfilter데몬을 작동시켜야 한다. sshdfilter데몬은 sshd데몬과 흡사한데 단지 다른점이라면 생성된 log에 대한 분석을 해준다는것이다.

② Fail2Ban은 일종 Python스크립트인데 이 스크립트는 sshd로그에 근거하여 커스텀 Firewall룰을 적용시키는 방식으로 공격을 막는다. 공격을 막기 위하여 사용되는 툴로는 iptables, ipfwadm 혹은 ipfw등이다.

③ DenyHosts는 firewall을 이용하여 공격을 막는것이 아니고 관련 룰들을 /etc/hosts.deny에 써주는 방식으로 공격을 차단한다. 단 이것을 사용하기 위하여서는 sshd 데몬이 컴파일 될시 tcp_wrappers를 지원하게끔 되어있어야 한다. 사실 DenyHosts도 Python 스크립트로 씌여졌다. tcp_wrappers를 지원하고 있는 지를 판단하는 방법은 상당히 심플한데 직접 hosts.deny를 편집하고 그 속에 127.0.0.1를 넣어준 상태에서 서버에서 ssh방식으로 자기자신을 접속하게 한다. 만약 접속이 안되면 tcp_wrappers를 지원하고 있는것이다.

참조문서: http://la-samhna.de/library/brutessh.html

저작자 표시 비영리 변경 금지
TRACKBACK 0 AND COMMENT 0



1. mod_evasive이란 무엇인가?

이것은 HTTP Dos 또는 DDos 스택 또는 저돌적인 공격으로부터 아파치를 보호하는데 있다. 또한 ipchains, 방화벽, 라우터등으로 쉽게 구성될 수 있도록 디자인 되었다.
탐지는 주소, URI의 IP 내부 동적 해쉬테이블을 생성함으로 수행되고, 각 아이피별로 거부된다.
- 초당 몇번 이상의 같은 페이지를 요청하는 경우
- 초당 같은 자식노드를 동시에 50번 이상 생성하는 경우
- 일시적으로 블러킹되는 동안 어떠한 요청을 생성하는 경우

2.  mod_evasive의 설치

# wget http://www.zdziarski.com/projects/mod_evasive/mod_evasive_1.10.1.tar.gz

# 압축해제
# tar xvzf mod_evasive_1.10.1.tar.gz

# 디렉토리 이동
# cd mod_evasive

# 모듈 추가
# /usr/local/apache2/bin/apxs -iac mod_evasive.c -> Apache.1.x
# /usr/local/apache2/bin/apxs -iac mod_evasive20.c -> Apache.2.x

# 환경설정
# vi /usr/local/apache2/conf/httpd.conf

# 아파치 1.X와 2.X에서의 모듈명칭이 약간 차이가 있으므로 주의할 것!
# 아래에 해당하는 내용이 존재하는지 확인 한다. 없으면 추가.

LoadModule evasive_module    modules/mod_evasive.so -> Apache.1.x
LoadModule evasive20_module    modules/mod_evasive20.so -> Apache.2.x

<IfModule mod_evasive.c>
        DOSHashTableSize        3097
        DOSPageCount              3
        DOSSiteCount                50
        DOSPageInterval            1
        DOSSiteInterval              1
        DOSBlockingPeriod        30

        DOSEmailNotify            webmaster@yoursite.com
        DOSLogDir                   "/usr/local/apache2/logs/mod_evasive.log"
        DOSSystemCommand      "su - someuser -c '/sbin/... %s ...'"
</IfModule>

# 환경설정 검사
# apachectl configtest
# 재시작
# apachectl -k restart

3. 각 지시자에 대한 설명

- DOSHashTableSize
각 자식 해쉬테이블 마다 탑레벨 노드의 수를 지정한다.
수치가 높으면 높을수록 더 많은 퍼포먼스가 나타나지만 테이블스페이스에 메모리를 남기게 된다, 접속량이 많으면 이 수치를 높혀도 된다.

- DOSPageCount
이것은 같은 페이지 또는 URI, 인터벌당 요청수에 대한 카운트 수이다.
지정된 값이 초과되면 클라이언트에 대한 IP 정보가 블러킹리스트에 추가된다.

- DOSSiteCount
지정된 시간동안 같은 페이지를 지정된 수 보다 초과될경우 IP 정보가 블러킹리스트에 추가된다.

- DOSPageInterval
페이지 카운트 시발점, 디폴트는 1초이다.

- DOSSiteInterval
사이트 카운트 시발점, 디폴트는 역시 1초이다.

- DOSBlockingPeriod
클라이언트가 블랙리스트에 추가되어 블러킹되는 총 시간. 이때 클라이언트는 403 (Forbidden) 에러를 출력하게 된다.

- DOSEmailNotify
이 값이 지정되면, IP가 블러킹될때마다 지정된 이메일로 발동된다.
주의 : 메일러는 mod_dosevasive.c 에 정확하게 지정되야 한다. 디폴트는 "/bin/mail -t %s" 이다.

- DOSLogDir
로그 파일 경로

- DOSSystemCommand
이 값이 지정되면, 시스템은 아이피가 블러킹될때마다 명령행을 실행한다.

- DOSWhitelist
차단에서 제외될 호스트
DOSWhitelist    127.0.0.1
DOSWhitelist    127.0.0.* - (와일드카드는(*) 필요하다면 최대 8진수(xxx.*.*.*)까지 사용할 수 있다.)


4. 테스트하기

# perl test.pl <- 다운받은 파일 안에 포함되어 있다.
   HTTP/1.1 200 OK
   HTTP/1.1 403 Forbidden
   HTTP/1.1 200 OK
   HTTP/1.1 403 Forbidden
   HTTP/1.1 403 Forbidden

5. 같이쓰면 좋은 iptables

흔히 DOS 공격방어라고 하면 mod_evasive 모듈을 사용한다고 알려져 있다.
특히, 과도한 DOS 공격이 들어올 경우 아파치가 부하를 견디지 못하고 죽어버리는 경우도 생긴다. 따라서 과다 접속 차단에 대해서는 iptables를 이용하시는것이 근본적이고 효과적 이다.
iptables를 보게되면 connlimit 기능이 있는데 이 설정을 잘 이용하시면
매우 효과적이고 안정적인 서버 운영이 가능하다.

# 1초에 15번 이상의 HTTP 접근을 할경우 (DOS공격) 접근을 차단한다.
# iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 -connlimit-mask 24 -j DROP

# 포트스캔을 차단한다.
# psd match를 사용하기 위하여 커널에 p-o-m패치를 적용시켜 놓아야 한다.
# 상세한 사항은 여기를 클릭하여 확인하기 바란다.
# iptables -A INPUT -m psd -j DROP

# 만약서버가 해킹당해 DOS공격지로 사용될때 적용시킴.
# DNS 쿼리이외에 UDP 패킷이 나가는 것을 방지
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A OUTPUT -p udp ! --dport 53 -m state --state NEW -j DROP

저작자 표시 비영리 변경 금지
TRACKBACK 0 AND COMMENT 1
  1. 2009/06/07 18:44 address edit/delete reply

    안녕하세요. 궁금한 것이 있어서 댓글을 답니다. -connlimit-mask 에서
    -기호가 하나 덜 들어간 것이 맞나요? --connlimit-mask 로 입력하는 것이 맞죠? 초보라서.. 선배님들이 하던 것을 따라하기만도 벅차네요. 좋은 자료 잘 보고 갑니다. 자주 와서 노하우 좀 얻어가겠습니다.




CentOS에 최신커널을 컴파일하여 넣어 보자~

iptables를 건드리다가 connlimit옵션이 먹히지 않아서 찾아보니 현재 사용중인 커널 버젼이 낮음으로 하여 먹히지 않았던 것이 였다.
간단히

# cat /proc/net/ip_tables_matches

를 통하여 현재 iptables상에 올라온 모듈들을 볼 수 있다.
connlimit 모듈이 깔리지 않은 상태에서 해당 모듈이 리스트에 뜨지 않을 것이다.

1. 최신 커널 및 iptables 소스 파일 다운로드 및 설치
현재 커널 버젼을 아래 명령어를 통하여 알아보도록 하자.

# uname -a
Linux localhost 2.6.18-128.el5 #1 SMP Wed Jan 21 10:44:23 EST 2009 i686 i686 i386 GNU/Linux

위에서 보다싶이 현재 사용중인 커널 버젼은 2.6.18이다.
http://www.kernel.org 에 접속하여 최신버젼 커널을 다운로드 받아 온다.

Kernel 2.6.29.1 => http://www.kernel.org/
Iptables 1.4.3.2 => http://www.netfilter.org/
정확히 다운로드 되었으면 다운로드 받은 커널 소스는 /usr/src에 압축을 풀고 iptables소스는 /usr/local/src/에 압축을 풀어놓는다.

# cd /tmp
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.29.1.tar.bz2
# wget http://ftp.netfilter.org/pub/iptables/iptables-1.4.3.tar.bz2
# tar xvfj linux-2.6.29.1.tar.bz2 -C /usr/src
# tar xvfz iptables-1.4.3.2.tar.bz2 -C /usr/local/src

작업을 좀 더 편하게 하기 위하여 미리 심볼릭 링크를 걸어 둔다.

# ln -s /usr/src/linux-2.6.29.1 /usr/src/linux

커널 소스 디렉토리로 들어갔으면 기존에 정상적으로 사용하던 커널의 환경옵션을 그대로 가져 와서 컴파일하는 것이 좋다.
/boot 디렉토리 안을 보면 이름이 config 로 시작하는 커널 환경 변수 정보가 담겨있는 파일들이 있는데 이 중 가장 최근까지 정상적으로 사용해 오던 파일을 복사해다가 /usr/src/linux 디렉토리 안에 .config 라는 이름의 파일로 저장해서 불러들이는 방식을 취하면 된다.

# cp /boot/config-2.6.18-128.el5 /usr/src/linux/.config

2. 커널 설정 및 컴파일
자~ 기본적으로 커널 설정을 하기 위한 초기 작업이 끝났다.
새로 받은 커널 소스 폴더로 이동하여 커널 설정을 해주겠다.

# cd /usr/src/linux
# make menuconfig

제일 하단에서 2번째에 있는 Load an Alternate Configuration File 메뉴를 통해 .config 파일을 로드한다.

Networking --> Networking option --> Network packet filtering framework (Netfilter) 옵션으로 들어가서
Core Netfilter Configuration을 비롯하여 넷필터, iptables 관련 모듈을 모두 체크하고 빠져 나온다.
Core Netfilter Configuration 옵션 안의 모듈들은 가급적 <M> 체크하여 모듈 형태로 저장한다.
iptables관련 모듈들은 하나가 모듈로 컴파일되면 다른 것들도 모듈로 되기를 요구하는 것 같다. connlimit 모듈은 중간 쯤에 나온다. 이해를 돕기 위하여 아래에 스크린샷을 첨부하겠다.


또한 IPv4 컨넥션 트래킹 모듈까지 설치하겠다. NAT에는 필수니까...


# make bzImage
# make modules
# make modules_install
# make install

make install하면 아래와 같은 Warning문이 뜬다.

WARNING: No module dm-mem-cache found for kernel 2.6.29.1, continuing anyway
WARNING: No module dm-message found for kernel 2.6.29.1, continuing anyway
WARNING: No module dm-raid45 found for kernel 2.6.29.1, continuing anyway

일단 커널 설치에는 영향을 주지 않으므로 건너뛰겠다.

마지막으로 grub.conf파일을 편집하여 부팅시 우리가 새로 빌드한 커널을 기본으로 로드하겠다.
/boot/grub/grub.conf를 편집기로 열고 hiddenmenu를 주석문속에 넣는다.
이렇게 하면 부팅할 때 두가지 커널을 alternative하게 선택할 수 있게 된다.
또한 우리가 새로 컴파일한 커널을 Default커널로 띠우기 위하여 default값 1을 0으로 고친다.
서버를 재부팅하면 새롭게 컴파일된 커널을 만날 수 가 있다.^^

새로 부팅하고 uname -a를 쳐보자.

# uname -a
Linux localhost 2.6.29.1 #1 SMP Mon Apr 27 15:30:11 CST 2009 i686 i686 i386 GNU/Linux

정확히 우리가 원하는 커널로 부팅이 되었음을 확인 할 수 있다. 이로써 커널 설치는 끝마리를 맺는다.

3. iptables 설치
자 이제 그럼 iptables를 새로 컴파일 하여 connlimit 모듈을 추가해보자.
일단 새로 부팅한후
# iptables -L -n
해보면 아무내용도 뜨지 않음을 발견할 수 있다.
setup을 이용하여 새로 설정을 한후 iptables 을 내렸다 올리자.

# lsmod | grep connlimit 해보면 모듈이 로드 되지 않았음을 알 수 있다.
# modprobe xt_connlimit 하여 connlimit 모듈을 로드하여 보자.
# lsmod | grep connlimit
xt_connlimit            3500  0
nf_conntrack           58828  4 xt_connlimit,nf_conntrack_netbios_ns,nf_conntrack_ipv4,xt_state
x_tables               13864  7 xt_connlimit,ip_tables,ip6t_REJECT,ip6_tables,ipt_REJECT,xt_state,xt_tcpudp

정확히 로드가 되었음을 확인 할 수 있다. (커널에 컴파일하여 넣었으니 로드가 않되면 이상하다.ㅎㅎ)

여기서는 기존의 rpm 버전 iptables를 삭제하지 않고 그 위에 소스컴파일로 덮어씌우는 방식으로 진행을 하겠다.
왜냐하면 rpm 버전을 삭제한 뒤 소스로 새롭게 설치하게 되면 기존의 rpm 버전에서 제공하던 system-config-securitylevel, lokkit, /etc/rc.d/init.d/iptables 와 같은 실행 스크립트 파일이 존재하지 않기 때문에 따로 스크립트로 구현하지 않는 한 일일이 iptables 룰을 추가해야 하는 불편함을 감수해야 한다.
다행스럽게도 iptables를 소스로 설치하게 되면 바이너리 파일, 환경설정 파일, 라이브러리 등이 rpm 버전과 거의 동일한 경로에 설치되므로 rpm 버전 위에 덮어 씌워 설치하면 기존의 관련 명령어를 그대로 활용할 수 있다는 장점이 있다. (찝찝함이 남아 있는것만은 사실이다. 허나 노가다를 줄이기 위해서는 이 방법이 최상책일 것이다.)
잠시 iptables를 중지하겠다.

# service iptables stop

# cd /usr/local/src/iptables-1.4.3.2
# ./configure
# make
# make install

이제 기존의 rpm 버전 iptables에서 사용되던 명령어들을 백업하고 새로 설치한 소스 버전의 명령어들로 교체하는 작업이 필요하다.
/sbin 디렉토리안의 iptables 관련 명령 삭제 후, /usr/local/sbin 아래에 생성된 iptables 관련 명령들을 심볼릭 링크한다.(총 8개 명령)

# cd /sbin
# mv ip6tables ip6tables.old
# mv ip6tables-restore ip6tables-restore.old
# mv ip6tables-save ip6tables-save.old
# mv iptables iptables.old
# mv iptables-restore iptables-restore.old
# mv iptables-save iptables-save.old

심볼릭 링크를 걸어줄 대상들을 확인해보자~
# ls /usr/local/sbin
ip6tables  ip6tables-multi  ip6tables-restore  ip6tables-save  iptables  iptables-multi  iptables-restore  iptables-save

# ln -s /usr/local/sbin/ip6tables /sbin
# ln -s /usr/local/sbin/ip6tables-restore /sbin
# ln -s /usr/local/sbin/iptables /sbin
# ln -s /usr/local/sbin/iptables-restore /sbin
# ln -s /usr/local/sbin/ip6tables-multi /sbin
# ln -s /usr/local/sbin/ip6tables-save /sbin
# ln -s /usr/local/sbin/iptables-multi /sbin
# ln -s /usr/local/sbin/iptables-save /sbin

iptable을 버젼을 확인 해보면...

# iptables -V
iptables v1.4.3.2

iptables가 정확히 업그레이드 되었음을 볼 수 있다.

# service iptables start
# iptables -L -n

기존에 룰들이 그대로 존재하고 있을 것이다.

connlimit 모듈을 적용해보자.
저작자 표시 비영리 변경 금지
TRACKBACK 0 AND COMMENT 2
  1. 2009/06/07 17:53 address edit/delete reply

    감사합니다.~ 꾸벅~

  2. 2009/09/10 11:02 address edit/delete reply

    자료 감사합니다. 덕분에 쉽게 편하게 이해할수 있었습니다.
    혹 실례가 되지 않는다면 제 개인 블로그에 내용을 담고 싶은데요
    괜찮을 까요?




iptables 초보 딱지 떼기 강좌~

서버 세팅을 하다보면 필수로 장악해야 할 부분이 바로 방화벽 설정이다.
리눅스상에서는 iptables를 이용하여 방화벽을 구축할 수 있다. 하지만 그 설정들이 복잡하여 처음 접해보는 사람들은 구조에 대하여 파악하기 힘들다.
이 강좌는 인터넷을 돌아다니면서 모은 강좌들을 입맛에 맛게 새로 편집한것이다.

1. 패킷필터링의 기본 배경 지식

패킷필터링은 지나가는 패킷의 해더를 보고 그 전체 패킷의 운명을 결정하는 것을 말한다. (iptables의 경우 많은 개발중인 기능에서 헤더에 그치지 않고 data의 내용을 검토하기도 한다. 가장 대표적인것이 string match기능이다.)
일반적으로 패킷은 헤더와 데이타를 가진다. 헤더에 필터링할 정보인 출발지IP:PORT,도착지 IP:PORT, checksum,프로토콜 옵셋등을 가지며 데이터는 각각의 전송데이터가 들어간다.

Netfilter이란?
일반 iptables사용자들이 가장간과하기 쉬운부분중 한 부분이다.
iptables이 패킷을 필터링 하는것이 아니다.
패킷필터링은 커널에 탑제된 netfilter기능으로 하며
iptables은 단지 netfilter의 룰을 세워줄 뿐이다.
즉 다시 말하자면 iptables은 룰셋구축 툴이라는 말이다.

2. 패킷필터링에 대한 심층적인 이해

iptables에 대해

iptable에 기본 Chain은 아래와 같다.

INPUT chain
FORWARD chain
OUTPUT chain

위의 3가지가 기본 체인이다. 체인들의 모식도는 아래와 같다.

------>INPUT------> Linux Box ------>OUTPUT--------->
---------↕-------------------------------↕
---------└---------- FORWARD ---------┘

여러분의 Linux box를 도착지로 삼는 모든패킷은 INPUT Chain을 통과하게 되며
여러분의 Linux box에서 생성되 외부로 보내지는 모든패킷은 OUTPUT Chain을
통과하게 된다.

Forward chain은 엄밀히 말하자면 도착지가 여러분의 Linux box가 아닌 패킷이 통과하게 되는 체인이다.

# iptables -A INPUT -j DROP

엔터키를 누르는 즉시 여러분의 Linux box로 오는 패킷은 모두 거부당할것이다. 즉 모든 통신이 끊어진다.

위의 룰을 굳이 말로 옮기자면

-A:룰을 추가한다
INPUT: 패킷이 들어오는 체인에
-j:패킷의 운명을 결정한다.
DROP: 패킷을 버려라.

즉, INPUT체인으로 들어오는 패킷을 모두 버리는 룰을 추가하는 명령이다.

적용시킨 룰을 보고 싶다면

# iptables -L

이라는 명령을 치면된다.

-A와 같은 위치에 있는 옵션은 아래와 같다.

체인에 새로운 규칙을 추가하기 (-A)
체인의 어떤 지점에 규칙을 삽입하기 (-I)
체인의 어떤 지점의 규칙을 교환하기 (-R)
체인의 어떤 지점의 규칙을 제거하기 (-D)
체인에서 일치하는 첫번째 규칙을 제거하기 (-D)

이제 위에서 내린 룰을 지워 통신이 되게 하자.
아래와 같이 명령을 내리면 된다.

# iptables -D INPUT 1
또는
# iptables -D INPUT -j DROP 하면 될것이다.

첫번째 방법은 index(룰의 순서)를 지정해서 지우는 방법이고, 두번째는 룰의 내용으로 지우는것이다.

Chain INPUT (policy ACCEPT)

(policy ACCEPT)를 설명하자면 여러분들이 세운룰에 해당되지 않을때
마지막으로 기본정책을 따라 패킷의 운명을 결정하게 된다. 여기서는 ACCEPT이므로
패킷은 받아드려질것이다. 하지만 이것을 DROP으로하면 패킷은 버려질것이다.

이제 기본정책을 바꾸어 보자.

# iptables -P INPUT DROP

위의 명령을 내리고 다시 iptables -L을 하면

Chain INPUT (policy DROP)으로 된걸 볼수있다.

-P와 동등 위치의 옵션은 아래와 같다.

새로운 체인 만들기 (-N).
비어있는 체인을 제거하기 (-X).
※ 이 두옵션은 직접체인을 만들었을경우와 제어할경우에 해당된다. 기본체인(INPUT,OUTPUT,FORWARD) 에는 해당되지 않는다.

미리 만들어진 체인의 정책을 바꾸기 (-P)
어떤 체인의 규칙들을 나열하기 (-L)
체인으로부터 규칙들을 지우기 (-F)
체인내의 모든 규칙들의 패킷과 바이트의 카운드를 0 으로 만들기 (-Z)

3. 패킷의 목적지또는 출처 제어

패킷출처 제어옵션 -s

# iptables -A INPUT -s 192.168.0.10 -j DROP

위에 같은 명령을 내렸다면 192.168.0.10으로 부터 온 패킷은 모두 버려지게 된다.

-s(--source,--src와 같은 옵션이다.) : 패킷의 출처 IP 지정

목적지 제어옵션 -d

# iptables -A INPUT -d 192.168.0.12 -j DROP

위와 같은 명령을 내렸다면 192.168.10.12의 IP를 도착지로 가지고있는 패킷은 모두 버려지게된다.

-d(--destination,--dst와 같은 옵션이다.): 패킷의 도착지 IP지정

※ IP지정 이외에 몇 가지 방법이 더 존재한다.
-s www.xxxx.com : 도메인으로 제어
-s 192.168.0.0/24 : 네트워크 또는 집단으로 제어
-s 192.168.0.0/255.255.255.0 :위와 동일

※ 보통 프로그래밍 약속기호처럼 !는 역('not')이라는 것을 표시한다.
ex) -s ! 192.168.0.10 이라고 하면 "출발지가 192.168.0.10이 아닌" 이라는 뜻이된다.

4.프로토콜 제어

프로토콜제어 옵션은 -p이다

-p옵션의 인자는 TCP,UDP,ICMP가 될수있다.

# iptables -A INPUT -p TCP -j ACCEPT

라는 명령을 내렸다면 tcp프로토콜을 쓰는 모든 패킷은 ACCEPT에 의해 허락될것이다.

※ -p의 인자로 TCP,UDP,ICMP의 프로토콜번호를 알고있다면 번호를 써도 상관없다.

포트 제어

포트제어 옵션은 --sport와 --dport이다

--sport는 패킷의 출발지 포트이다.( --source-port와 같은 옵션이다.)

--dport는 패킷의 도착지 포트이다.( --destination-port와 같은 옵션이다.)


# iptables -A INPUT -p tcp --dport 80 -j DROP

위와 같은 명령은 tcp프로토콜의 80(www:웹서버포트)번 포트를 목적지로 하는 패킷을
버리는 것이다.

※ --dport나 --sport의 인자로 서비스이름을 적어도 된다.
ex) --dport www

※ 여러 포트를 지정해야 된다면 --dport 1024:65535 와 같이 지정할수있다.
뜻은 1024 부터 65535번까지라는 뜻이다.

5. 인터페이스 지정

인터페이스는 -i (input interface), -o (output interface)로 지정할수있다.

# iptables -A INPUT -i eth0 -p tcp --dport 80 -j DROP

위의 명령은 -i eth0옵션을 빼고는 port지정 예와 같다.

-i eth0는 eth0로 들오는 모든 패킷을 뜻한다.

보통 리눅스 박스처럼 인터넷과 연결된 디바이스가 1개라면 필요없는 옵션이 되겠지만
만약 eth0, eth1등 2개이상의 인터페이스가 인터넷과 연결되어있다면 위의 옵션은 유용하게 쓰일것이다.

※ INPUT 체인은 -i 옵션만 쓸수 있고, OUTPUT 체인에는 -o옵션만 쓸쑤있다.
반면에 FORWARD 체인은 -i,-o 옵션 두가지 다 쓸쑤있다. 이유는 다음문서에서 다루겠다.

총괄적인 예:

# iptables -A INPUT -i eth0 -d 192.168.0.10 -p tcp --dport 80 -j DROP

해설: INPUT 체인에 - 입력인터페이스가 eth0이고 도착지가 192.168.10.10이고
프로토콜은 tcp이며 도착 포트는 80(www)인 패킷은 DROP시켜라.

이제까지는 별 다른 지식이 없이도 이해할수있는 부분이었다.
하지만 지금부터 나오게될 내용은 tcp/ip의 기반적인 지식을 가지고있어야
이해하기 쉬울것이다.
tcp/ip지식이 필요한 옵션에 대해서는 그에따른 자세한 설명을 하겠지만
이해가 되지 않는 부분은 다른 문서나 책을 찾아보길 바란다.

6. 패킷의 행동 유형에 따른 필터링(--tcp-flags,m state --state)

! 주의 : 밑에 나오는 모든옵션은 TCP프로토콜옵션(-p TCP)가 먼저
선행되어 있어야 적용되는 옵션이다.

① --tcp-flags 옵션은 상태에 따라 유용하게 설정할수있다.
이 옵션을 설정하는 가장 큰 예는 한방향으로만 통신이 되게끔설정하기 위해
많이 사용한다.
tcp/ip는 3핸드쉐이크의 접속방식이다.
즉. 접속요청패킷,접속허가 패킷,확인패킷

접속 단계를 좀더 자세하게 보면

C: Client S:Server

1) C --------- syn -------▷ S
2) C ◁------- syn ack ----- S
3) C --------- ack -------▷ S

이런식으로 접속절차가 이루어진다.

syn패킷은 접속요청 플래그(syn)가 설정된 패킷이므로 syn패킷만 막으면 상대편에서 접속을 할수 없다는 것이다.

※ Dos공격의 일종인 Syn Flooding이 서버에 위에서 말한 syn형패킷을 무수히 많이
보내는 것이다.

이제 본격적으로 --tcp-flags옵션으로 syn 접속형 패킷을 막는것을 하겠다.

# iptables -A INPUT -p TCP --tcp-flags SYN,RST,ACK SYN -j DROP

--tcp-flags에 첫번째 인자는 검사할 리스트 마스크이다.
두번째 인자는 설정되어있어야할 플래그다.
즉 syn,rst,ack플래그중 syn이 set이 1로 되어있으면 위의 --tcp-flags설정에
해당이 되므로 패킷은 DROP된다.

위의 옵션과 같은 뜻을 가진것이 있는데 그것은 --syn이다.
--syn은 '--tcp-flags SYN,RST,ACK SYN'의 뜻을 가지고 있다.

② --tcp-flags보다 더 간단하게 설정하는 방법이 있다.
바로 tcp의 상태천이 다이아그램을 축소시켜 놓은듯한 느낌을 받는 상태에 따른 패킷분류를 iptables은 지원한다.

이것은 확장기능이므로 -m 플래그로 설정은 한다.

사용옵선은 -m state --state 이다.

인자값으로 들어가야할 상태에따른 리스트는 아래와 같다.

NEW : 새로운 접속을 만드는 패킷

ESTABLISHED :존재하는 접속에 속하는 패킷 (즉, 응답 패킷을 가졌던 것)
즉 접속이 허가되고 통신하면서 발생되는 패킷이다.

RELATED :기존의 접속의 부분은 아니지만 연관성을 가진 패킷으로 .
ICMP 에러 나 (FTP 모듈이 삽입 되어있으면) ftp 데이터
접속을 형성하는 패킷.

INVALID :어떤 이유로 확인할 수 없는 패킷. 알려진 접속과 부합하지 않는 ICMP 에러와 'out of memory' 등을 포함한다. 보통 이런 패킷은 DROP 된다.

이제 이 state 옵션을 사용해보자

위의 --tcp-flags옵션에서 예제와 같은 작용을 하는 룰을 만들어보겠다.

# iptables -A INPUT -p TCP -m state --state NEW -j DROP

왜 룰이 이렇게 되는지 차근차근 읽어보았다면 쉽게 이해가 될것이다.

일반적으로 서버는

# iptables -A INPUT -p TCP --dport 특정포트 -m state --state NEW, ESTABLISHED -j ACCEPT

이렇게 룰을 많이 세운다.
뜻은 tcp 특정 포트에 new:접속패킷과,established:통신패킷(정확히 쉽게 설명할
단어가 생각나지 않아 부적절하지만 통신패킷이라 부른다)을 허용하라.

그리고 클라이언트 측에서는 위의 state상태에서 NEW를 빼고 사용한다.

# iptables -A INPUT -p TCP --sport 특정포트 -m state --state ESTABLISHED -j ACCEPT

왜 NEW를 뺄까? 그 이유는
그 이유는 클라이언트입장에서 보면 접속을 허가해달라는 패킷이 필요없다는것이다.
더 쉽게 말하자면 클라이언트는 접속허가를 요청하는 위치이지 요청받는
위치가 아니라는 말이다.
그러므로 ESTABLISHED만 있으면 일반적으로 통신하는데 아무런 문제가 없다

그리고 주의깊게 본 사람이라면 위에 --sport가 쓰여진것을 볼수있을것이다.

왜 서버에서는 --dport로 제어를 하면서 클라이언트는 --sport로 제어를 할까?

지금 리눅스 박스라면 wget을 쓰던지 x-windows에서 브라우져를 쓰던지 아무런 웹사이트에 접속을 하고 바로 콘솔에서 'netstat -nat'라는 명령을 내려보자.

무슨말인지 알겠는가?

서비스를 한번이라도 해본적있는 사람이면 알겠지만 서버는 특정PORT를 열어놓고 접속을 기다린다.
클라이언트는 특정 서버에 접속을 하기 위해 별도로 포트를 생성하고 접속을 시도한다.
이때 클라이언트가 생성하는 포트번호는 1024이후의 랜덤값이다. 이런이유로 클라이언트입장에서는
--dport로 제어를 하지않는게 보통이다. 제어를 하더라도 상관없다. 하지만 그것은
상당한 비효율적인 룰이 될것이다.
저작자 표시 비영리 변경 금지
TRACKBACK 0 AND COMMENT 0



SSH기본 포트 22를 다른 값으로 변경하기

서버를 운영하다보면 여러가지 공격을 많이 받게 되는데 그중에서 가장 흔하면서 또한 가장 기본으로 되는 해킹방법이 바로 포트 스캔이다. 서버에 포트스캔을 막어주는 portsentry를 깔고 기본 쉘접속 포트인 22를 다른값으로 변경하면 해킹을 어느정도 막을 수 있다.(어느정도이다, 절대로 해킹당하지 않는다는 보장은 없다...)

1. ssh 설정변경
ssh설정 파일은 /etc/ssh/sshd_config 에 위치하고 있다.


vi편집기로 열고 #port 22 이 라인중에서 #주석문을 제거하고 port xx로 바꾼다.(xx에는 바꿀 포트숫자를 써준다.)
저장하고 vi편집기에서 빠져나온다.


2. iptables에 새로 추가한 포트에 대한 rule을 추가한다.

또한 iptables에 rule을 추가하여 기존에 22포트를 블럭하고 새로 설정한 포트에 대한 input 컨넥션을 accept해준다.

# iptables -L -n

위 명령어를 이용하여 현재 적용된 iptable 룰들을 살펴 볼수 가 있다.


여기서 주의해서 봐야할 것은 포트 22를 사용하는 SSH가 accept rule로 등록이 되어있는지 확인하는것이다. 보다 싶이 현재 이미 등록이 되어 있는 상태이다. 이 상태에서 우리가 추가한 포트도 xx포트로 접속이 가능하도록 rule을 추가해야 한다.

# iptables -A INPUT -p TCP --dport xx -m state --state NEW -j ACCEPT

(RH나 CentOS일 경우 -A INPUT 대신 -A RH-Firewall-1-INPUT 을 사용하여야 한다.)

또한 기존에 추가된 22포트를 iptables룰에서 삭제 해야한다.

# iptables -D INPUT -p TCP --dport 22 -m state --state NEW -j ACCEPT

(RH나 CentOS일 경우 -A INPUT 대신 -A RH-Firewall-1-INPUT 을 사용하여야 한다.)

# service iptables save

위 명령어를 이용하여 추가한 룰을 iptable에 적용시킨후 다시금 iptable의 상태를 살펴본다.


그림에처럼 22포트는 정확히 삭제되고 우리가 추가한 xx포트가 떠있는것을 확인 할 수 있다.

3. SSH 재시동
포트가 정확히 iptables에 추가되었음이 확인 되면 ssh데몬을 재시동하여 포트 xx에서 서비스를 시작하게 한다.

# service sshd restart

새로운 컨넥션을 만들고 접속을 시도한다.
정확히 쉘에 접속이 됨을 확인 할 수 있다~
저작자 표시 비영리 동일 조건 변경 허락
TRACKBACK 0 AND COMMENT 0




ARTICLE CATEGORY

분류 전체보기 (114)
자바 어플리케.. (45)
제로보드 XE (2)
PSP 정보 (5)
PCSX 2 정보 (3)
ENG 스터디 (5)
리눅스 자료 (10)
잡동사니 (44)

CALENDAR

«   2010/03   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

ARCHIVE