2012-09-07

Linux]리눅스보안의 기초




          리눅스 보안의 기초

         

          보안

  리눅스 운영체제가 인기가 좋은 이유 중 하나는 다른 서버 운영체제에 비해 저렴하다는 것과, 기능과 성능에 있어서 강력하다는 것일 것입니다. 그러나 강력한 시스템인 동시에 관리하기 어렵고, 그에 따른  보안 위험도 크다는데 문제가 있습니다. 본 기사는 리눅스 시스템에 있어 기본적이면서 일반적인 보안에 대해 설명하고자 합니다. 본문은 또한 와우리눅스 7.0 까치를 기준으로 설명하고 있지만 다른 레드햇 계열 리눅스 시스템에도 적용이 가능합니다.
         


          물리적 보안

  보통 서버가 연구실이나 외부 사람이 많이 오가는 곳에 설치되어 있다면 그 사람들 중 물리적인 크래킹을 하려는 사람이 있는데 이에 대한 방어를 할 수 있는 것은 주로 BIOS와 LILO(리눅스 부트 로더)에 대한 패스워드를 설정하는 작업과 콘솔에서 root로 로그인을 못하게 설정하는 것으로 구성됩니다.
       


          ■ BIOS


  콘솔로의 접근을 막기 위해서는 BIOS 에 암호를 설정해두고, 플로피와 CD-ROM으로의 부팅은 하지  못하도록 설정합니다. 일단 물리적으로 시스템에 접속하게 되면 시스템을 보호할 방법은 없다는  것을 명심해야 합니다.


          ■ LILO


   다음과 같이 lilo 설정 파일 (/etc/lilo.conf)을 수정하여 부팅시 암호를 걸 수 있습니다.           

               password=xxx

   와 같이 패스워드를 설정함으로써 부팅 프로세스가 진행되는 동안 시스템을 보호할 수 있습니다.    restricted 옵션을 사용하여 싱글 유저모드로 부팅할 때와 같이 특별한 옵션을 사용할 때에 대비하여 패스워드를 물어보도록 설정합니다.
         

          boot=/dev/sda
          map=/boot/map
          install=/boot/boot.b
          prompt
          message=/boot/message
          default=linux
          timeout=00 # 대기 시간을 00초로 설정합니다.
          restricted # 특수한 옵션을 사용할 경우 암호를 묻습니다.
          password=openlinux # 이 라인을 추가하고 암호를 설정합니다.
          image=/boot/vmlinuz-2.2.17-8wl2smp
          label=linux
          initrd=/boot/initrd-2.2.17-8wl2smp.img
          read-only
          root=/dev/sda6

         
  리로(LILO) 설정파일의 암호가 암호화되지 않은 일반 텍스트이므로, 루트만이 억세스 할 수 있도록  다음과 같이 합니다.

          # chmod 600 /etc/lilo.conf
         

   리로(LILO) 설정 파일을 수정한 다음 리로를 실행하여 갱신합니다.

          # /sbin/lilo  -v

         

  마지막으로 리로 설정 파일의 변경을 막기 위해  lilo.conf 파일을 chattr 명령으로 변경 불가로          만듭니다. (이 명령은 ext2 파일 시스템에서만 사용 가능합니다.)
         

          # chattr  +i /etc/lilo.conf
         


          ■ Control-Alt-Delete


  리눅스에서는 Ctrl + Alt + Del 키 조합을 사용하여 시스템을 리부팅 시킬 수 있습니다. 문제는 이러한 기능을 로그인 대기 상태에서도 사용할 수 있고 내부의 다른 사람이 이러한 기능을 이용하여 콘솔에서 서비스중인 시스템을 리부팅 시킬 수 있다는 점입니다. 따라서 Control-Alt-Delete 키 조합을 사용하지 못하도록 합니다.
   /etc/inittab 파일에서 다음과 같은 라인을 찾아 주석처리 합니다.

          #ca::ctrlaltdel:/sbin/shutdown -t3 -r now


  수정한 것을 리부팅하지 않고 바로 적용하려면,

          # /sbin/telinit  q

  와 같이 합니다.

         
          패치 설치

    설치 후 시스템이 재시동되고 나면 반드시 패치를 설치합니다.  패치는 OS별로 제공되어지는데 레드햇 리눅스는 다음 사이트를 참조하기를 바랍니다.


          레드햇 리눅스 패치 사이트 : http://www.redhat.com/support/errata/

  여기에 있는 보안, 버그 패치들을 적용하지 않으면 시스템은 쉽게 침해 당할 것입니다. 또한 리눅스   시스템은 고립된 네트워크에 연결된 채 중계 서버를 통해 패치되어야 함을 잊지 말도록 합니다.  레드햇의 경우 rpm 파일을 다운받으면 다음의 명령어를 통해 쉽게 설치할 수 있습니다.

          # rpm -Uvh wu-ftpd-2.6.0-l.i386.rpm : wu-ftpd 패치하는 명령어


        사용하지 않는 서비스 제거

  리눅스 시스템을 보안 위험으로부터 보호하는데 있어, 제일 처음으로 하는 작업이 바로 불필요한 서비스를  제거하는 것입니다. 리눅스 시스템은 디폴트로 여러 유용한 서비스를 설정하고 실행하도록 되어 있습니다.
  그러나, 이 서비스들의 대부분은 일반적인 환경에서는 필요하지 않으며, 보안측면에서 볼 때, 잠재적인 위험을 지니고 있습니다. 이러한 서비스를 제거함으로써 보안 영역을 크게 넓힐 수 있습니다.


          ■ xinetd 서버를 사용하는 경우


  리눅스 6.2까지는 네트워크 연결을 처리하기 위해서 inetd를 사용하였습니다. 그러나 레드햇 리눅스  7.0부터는 inetd를 사용하지 않고 보다 확장된 xinetd를 사용합니다. xinetd 서버를 사용하는 경우에는   /etc/xinetd.d/ 디렉토리 아래에 서비스 이름으로 구분되어 있으므로 서비스 파일을 열어서 수정합니다.
  텔넷 서비스의 경우 telnet 파일을 수정합니다. 다른 서비스도 동일한 방법으로 설정합니다.

          service telnet
          {
         disable = yes # 이 항목을 추가하면 서비스를 하지 않습니다.
         flags = REUSE
         socket_type = stream
         wait = no
         user = root
         server = /usr/sbin/in.telnetd
         log_on_failure += USERID
          }


          이렇게 수정한 후 아래와 같이 xinetd 서버를 재시작하면 시스템에 적용 됩니다.

          # killall -USR2 xinetd
         


          ■ inetd 서버를 사용하는 경우 (레드햇 6.2)


 먼저, /etc/inetd.conf 파일을 보도록 합시다.  이 파일에는 디폴트로 여러 다양한 서비스들이 설정되어 있으나, 대부분 ftp와 telnet만이 필요합니다.  다른 불필요한 서비스들은 주석(#)으로 처리하여 제거하도록 합니다.

          예)

          # ....

          ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd -l -L -i -o

          telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd

          #gopher stream tcp nowait root /usr/sbin/tcpd gn

          #smtp stream tcp nowait root /usr/bin/smtpd smtpd

          #nntp stream tcp nowait root /usr/sbin/tcpd in.nntpd

         

    pop, imapd, rsh과 같이 inetd에 의해 실행되는 많은 서비스들이 보안 취약점에 노출되어 있습니다. 다음  명령어를 이용하면 가능한 서비스들을 확인할 수 있습니다. 이 명령어는 코멘트 처리되지 않은 서비스들을 보여 줍니다.

          # grep -v "^#" /etc/inetd.conf

         

          ※ 불필요한 서비스 제거를 위한 단계별 명령어 순서

          1. 소유자(root)만이 읽기/쓰기가 가능하도록 퍼미션을 바꾸어 줍니다.
              또한, 반드시 /etc/inetd.conf 파일의 소유자는 root 이어야 합니다.
       

          # chmod 600 /etc/inetd.conf

          # chown root.root /etc/inetd.conf
         

          2. 편집한 후에는 다음처럼 시그널을 보내 inetd 서버를 재구동합니다.

          # killall -HUP inetd

         
          3. super-user만이 이 파일에 대해 접근할 수 있도록 'inetd.conf'파일을 셋팅하는 
             것으로 일단 셋팅되면  수정, 삭제 또는 rename할 수 없습니다. 나중에 
             inetd.conf 파일을 수정하고자하면 플래그를 -i로
             바꿔주면 됩니다.

          # chattr +i /etc/inetd.conf

         


          ■ rc 스크립트


   보안이 약한 데몬이 떠 있지 않다면 그 만큼 안전하다는 것이므로 부팅시 필요없는 데몬을 죽이는 것만으로도  80% 이상의 방어를 할 수 있습니다.
  다음은 init 프로세스에 의해 어떤 서비스가 시작될 지 결정하는 .rc 스크립트들입니다. 레드햇의 경우 이 스크립트들은 /etc/rc.d/rc3.d에 있습니다. 자동으로 Gnome이나 KDE등의 GUI 환경으로 부팅되도록 설정되어 있다면 /etc/rc.d/rc5.d에 있습니다.
  시동되도록 되어 있는 것을 멈추게 하려면 대문자 S를 소문자 s로 바꿉니다. 또 원한다면 레드햇의 유틸리티를 사용할 수 있습니다. '/usr/sbin/ntsysv' 명령을 실행하면 부트 프로세스중에 구동시킬 스크립트를 선택할 수 있습니다.
  다른 방법은 대부분의 배포판에서 볼 수 있는 'chkconfig' 를 사용하는 것입니다.

  다음의 스크립트들은 디폴트로 설치되는 것들이나 시스템에서 주요한 기능은 하지 않는 것들입니다. 필요하지 않다면 시동되지 않도록 설정합니다.

          스크립트   설 명

          S05apmd     laptop에만 필요
          S10xntpd   Network Time Protocol
          S11portmap     NIS, NFS같은 rpc 서비스가 있을 때만 필요함
          S15sound        사운드 카드 설정 저장
          S15netfs        nfs client, nfs 서버에서 파일시스템을 마운트할 때 사용
          S20rstatd       r 서비스 실행을 하지 않도록 함, 원격 사용자에게 
                                  너무 많은 정보를 제공함.
          S20ruserd        
          S20rwhod
          S20rwalld
S20bootparamd 디스크가 없는 클라이언트에서 사용
          S25spuid        프락시 서버
          S34yppasswdd    NIS 서버에만 필요함, 아주 취약한 서비스
          S35ypserv       NIS 서버에만 필요함, 아주 취약한 서비스
          S35dhcpd        dhcpd 서버 데몬을 구동함
          S40atd          크론과 비슷한 at 서비스에 이용
          S45pcmcia       laptop에만 쓰임
          S50snmpd        SNMP 데몬, 시스템 관련 정보를 원격 사용자에게 보냄
         

  이름에 포함된 숫자들은 초기화 되는 순서를 결정하는 요소로서, 이것은 어떤 배포판인지 어떤 버전인지에  따라 달라집니다.

         
          스크립트        설 명
          S55named        DNS 서버, 사용한다면 최신으로 업데이트한다.        
                                     http://www.isc.org/bind.html
          S55routed       RIP, 정말 필요한 경우가 아니면 실행하지 않는다.
          S60lpd          프린팅 서버
          S60mars-nwe     Neteware file과 프린터 서버
          S60nfs          NFS 서버에 사용, 꼭 필요하지 않으면 실행하지 않는다.
          S72amd          AutoMount 데몬, 원격 파일시스템 마운트에 사용
          S75gated        OSPF와 같은, 다른 라우팅 프로토콜 구동에 사용
          S80sendmail     이 스크립트를 정지시키더라도 여전히 email를 보낼 수 있으며, 
                                  단지 수신이나 중계는 불가능할 것이다.
          S85httpd        아파치 웹서버, 가장 최신 버전으로 업데이트할 것을 권고한다. 
                                   http://www.apache.org/  
          S87ypbind       NIS 클라이언트라면 필요함
          S90xfs          X 폰트 서버
          S95innd         News 서버
          S99linuxconf    브라우저를 통해서 리눅스 시스템을 원격으로 구성하는데 사용
       

  부팅시 스크립트를 변경하기 전에 얼마나 많은 서비스들이 실행되고 있는지 알려면 다음 명령어를 사용합니다.
         
          # ps aux | wc -l


 조정 후 확인하기 위한 명령어는 다음과 같습니다.

          # netstat -na --ip



          ■ /etc/rc.d/init.d 디렉토리와 파일들의 퍼미션


   "/etc/rc.d/init.d" 디렉토리와 파일들의 퍼미션을 다음과 같이 수정하여 루트만이 억세스 할           수 있도록 합니다.

          # chmod -R 700 /etc/rc.d/init.d/*
         

  부트 타임때 필요로 하는 모든 표준의 프로세스들의 시작, 중지를 위한 책임이 있는 스크립트들은 루트만이 억세스 할 수 있도록 퍼미션을 고정시켜야 합니다.

         


          계정관리 보안



          ■ 암호시스템 보안


  첫 번째는 /etc/passwd 파일을 안전하게 하는 것입니다. 우선 시스템이 /etc/shadow를 사용하는지  확인합니다. 이것은 모든 사용자의 패스워드를 root만이 접근 할 수 있는 파일에 해쉬형태로 안전하게 저장한다는 것을 의미합니다. 또한 해커들이 제일 먼저 노리는 패스워드가 손쉽게 접근되고 크랙되는 것을 방지합니다. 쉐도우 패스워드 파일을 사용하는 것이 레드햇 리눅스의 디폴트이지만 확인을 해야 합니다.
  다음 명령어를 실행하면 자동으로 패스워드 파일을 /etc/shadow 파일로 변환해 줍니다.

          # pwconv
         


          ■ 기본 시스템 계정 관리


  두 번째는 /etc/passwd 파일에서 대부분의 디폴트 시스템 계정들을 제거하는 것입니다. 리눅스는 이런 계정들을 불필요할지도 모르는 시스템 작업을 위해 제공합니다. 필요하지 않다면 제거해야 합니다. 계정을 많이 가지면 가질수록 침입될 가능성은 높아집니다. 'news' 계정이 그 한 예입니다. 뉴스그룹 서버로 사용하기 위해 nntp를 서비스하는 경우가 아니면 이 계정은 불필요합니다. ftp 서버를 운영하지 않는다면 익명 ftp 접속에 사용되는 'ftp' 계정도 삭제해야 합니다. /etc/passwd 파일에 ftp 계정이 있어 익명 ftp 접속이 허용되어 있고 사용자 ID가 'anonymous'나 'ftp'이면 이 경우 어떤 패스워드라도 로그인이 허용됩니다. 관례상 접속자의 host명을 패스워드로 사용하기도 합니다.


          [ /etc/passwd 파일의 시스템 계정 예 ]

          root:x:0:0:root:/root:/bin/bash
          bin:x:1:1:bin:/bin:
          daemon:x:2:2:daemon:/sbin:
          adm:x:3:4:adm:/var/adm:
          lp:x:4:7:lp:/var/spool/lpd:
          mail:x:8:12:mail:/var/spool/mail:
          uucp:x:10:14:uucp:/var/spool/uucp:
          nobody:x:99:99:Nobody:/:

  ftp 서버를 운영한다면 /etc/ftpusers 파일도 수정해야 합니다.
         

          [ /etc/ftpusers 파일의 예 ]

          root
          bin
          daemon
          adm
          lp
          mail
          uucp
          nobody


  이 파일에 기록된 계정은 ftp를 사용해서 이 시스템에 접속할 수 없습니다. 이것은 root, bin과 같은 공통의 시스템 계정을 사용해 ftp로 연결하는 것을 제한합니다. 리눅스는 디폴트로 이 파일을 가지고 있습니다. root 권한으로 이 시스템에 ftp를 통해 접속하는 것을 막으려면 이 파일에 root가 포함되어 있는지 확인합니다. ftp 접속시 사용할 계정은 이 파일에 포함되면 안됩니다.


  또 root로는 시스템에 telnet 접속을 못하도록 합니다. root로 작업 할 때는 따로 일반계정을 두어 자기의 계정으로 접속한 뒤 su를 사용해 root로 전환하도록 합니다.

         


          ■ 일반 유저의 su root 방지


  특정 유저만 su root 할 수 있도록 설정하려면 다음과 같이합니다. 이런 종류의 명령어를 실행시킬 수 있는 사용자들을 제한함으로써 시스템의 보안성을 향상시킬 수 있습니다. /etc/pam.d/su 파일의 처음에 다음을 추가합니다.

          auth sufficient /lib/security/pam_rootok.so debug
          auth required /lib/security/Pam_wheel.so group=wheel


  /etc/group 의 wheel 그룹에 su root를 허용하고자 하는 사용자 그룹을 등록합니다. 즉, wheel 그룹에 속한 유저만이 su 명령을 사용하여 root 로 로그인 할 수 있습니다.

          wheel:x:10:root,junilove,juni8004
         


          ■ 쉘 로그 파일


 bash 쉘은 사용자가 입력한 500여개의 지난 명령어를 ~/.bash_history 에 남기게 됩니다.         이는 내가  사용한 명령어들을 다른 사람들이 알게 됩니다. 다음과 같이 크기를 줄이거나,          0으로 설정해 아예 로그를  남기지 않도록 하여 크래커가 로그 파일의 내용을 이용할 수          없도록 합니다. 이러면 .bash_history 파일에  아무런 기록이 남지 않습니다.  이렇게 해도 HISTSIZE라는 환경변수가 있기에 키스트로크에 대한 히스토리 관리는 유지됩니다. 단지 .bash_history 파일에 저장되지 않을 뿐입니다.

          HISTFILESIZE=30
          HISTSIZE=30

 또는 로그아웃 할 때마다 로그 파일을 삭제하도록 다음과 같은 라인을 ~/.bash_logout 에 추가합니다.
         
          # rm -f $HOME/.bash_history



          ■ root 계정 환경 설정


  루트 계정은 유닉스 시스템에서 가장 강력한 권한을 가지고 있는 계정입니다. 만약  관리자가 콘솔로의  접속 후, 로그아웃 하는 것을 잊고 루트 프롬프트를 그대로 놔두었다면, 위험한 상황이 벌어질수도 있습니다. 이런 상황을 피하기 위해 TMOUT  변수를 사용할 수 있습니다. /etc/profile 파일 또는 루트의 해당 쉘의 설정파일,  예를 들어, bash 라면 ~/.bash_profile 에 다음과 같이 설정합니다.

          HISTSIZE=0
          HISTFILESIZE=0
          TMOUT=300

   숫자는 초단위입니다. 300초 즉, 5분동안 아무런 입력이 없다면 자동으로 로그아웃 합니다. HISTSIZE 와 HISTFILESIZE 를 0으로 해두는 것도 만약을 위한 조치입니다.



          파일 시스템 마운트


  잘못된 파일 시스템 마운트 옵션도 보안에 문제가 될 수 있습니다.

          [ 파일 시스템 마운트 설정 파일(/etc/fstab)의 옵션 ]

          옵  션            설  명

          defaults        기본 옵션, 쓰기,읽기 가능, quota, suid 가능
          noquota       유저 쿼타가 적용되지 않음
          nosuid          SUID/SGID 억세스 불가, SUID/SGID를 사용자의 
                               홈 디렉토리에서 쓰게 할 이유는 전혀 없습니다.
          nodev           특별한 장치 또는 문자 사용 불가 (예를 들어 /dev 같은)
          noexec         이 파티션상의 모든 바이너리 실행 불가
          quota            유저 쿼타 사용
          ro                  읽기 전용으로 마운트
          rw                  읽기, 쓰기 허용
          suid               SUID/SGID 억세스 허용

         
 /etc/fstab 의 형식은 다음과 같습니다

          [ /etc/fstab의 예 ]

          /dev/hda9 /tmp ext2 defaults,rw,nosuid,nodev,noexec 1 2
          /dev/fd0 /mnt/floppy auto sync,user,noauto,nosuid,nodev 0 0
          /dev/cdrom /mnt/cdrom auto user,noauto,nosuid,exec,nodev,ro 0 0


  fstab의 수정 후에는 파일 시스템을 다음과 같이 다시 마운트 합니다.

          # mount -oremount /tmp/
         

          시스템 정보 숨기기

  기본적으로 리눅스 서버로 로그인 할 때, 배포본, 버전, 커널 버전, 서버이름 등이 나타나도록 되어 있습니다. 이것은 서버를 노리는 크랙커들에게 더 많은 정보를 줄 뿐입니다.


          ■ "/etc/rc.d/rc.local" 의 수정


    rc.local 에는 매 부팅시마다 /etc/issue 파일을 생성하는 루틴이 있습니다.  이 부분을 모두 주석처리 합니다.


          # This will overwrite /etc/issue at every boot. So, make any changes you
          # want to make to /etc/issue here or you will lose them when you reboot.
          #echo "" > /etc/issue
          #echo "$R" >> /etc/issue
          #echo "Kernel $(uname -r) on $a $(uname -m)" >> /etc/issue
          #
          #cp -f /etc/issue /etc/issue.net
          #echo >> /etc/issue

  그런 다음, /etc 디렉토리 아래에 있는 "issue.net" 와 "issue" 파일들을 삭제합니다.


          # rm -f /etc/issue
          # rm -f /etc/issue.net
         


          SUID/SGID 프로그램 찾기


   일반 유저가 루트 권한으로 실행 시킬 수 있는 불필요한 SUID/SGID 프로그램들을 최소화 합니다. SUID와 SGID는 잠재적인 보안 위험 요소이기 때문에 철저하게 감시되어야만 합니다. 이러한 프로그램들은 이들을 사용하는 사용자들에게 특별 권한을 부여해 주기 때문에, 보안에 불안 요소를 주는 이러한 프로그램들이 설치되는 일이  없도록 해야 합니다. 크랙커들이 좋아하는 트릭중의 하나는 SUID 루트 프로그램을 침탈하고, 그 후에 SUID 프로그램을 통해 백도어로 들어오는 것입니다. 다음의 명령어를  사용하면 시스템에 있는 모든 UID/SGID 프로그램을 찾아낼 수 있습니다.

          # find / -type f  ( -perm -04000 -o -perm -02000  ) -exec  ls  ­lg {} ;

  그런 다음 퍼미션을 바꾸어 줍니다.

          # chmod a-s [프로그램]


  어떠한 프로그램인지 잘 모를 경우에는 man [프로그램] 또는 info [프로그램] 등으로  확인한 후  변경합니다.


  중요한 시스템 파일의 퍼미션

          파일           퍼미션    설명

          /var/log       751     모든 로그 파일을 담고 있는 디렉토리
          /var/log/messages 644 시스템 메시지
          /etc/crontab 600 시스템 크론탭 설정
          /etc/syslog.conf 640 Syslog 데몬 설정파일
          /var/log/wtmp 660   who 명령에 의해 보여지는 현재 로그인한 유저가 
                                             누구인지  기록하는 파일
          /var/log/lastlog 640 last 명령에 의해 보여지는 마지막에 로그인한 
                                               유저가  누구인지 기록하는 파일
          /etc/ftpusers 600 FTP 서버에 접속할 수 없는 유저 리스트
          /etc/passwd 644 시스템의 유저 계정 리스트
          /etc/shadow 600 암호화된 계정 패스워드를 담고 있는 파일
          /etc/pam.d 750 PAM 모듈 설정 파일
          /etc/hosts.allow 600 접근 설정 파일
          /etc/hosts.deny 600 접근 설정 파일
          /etc/lilo.conf 600 부트로더 설정파일
          /etc/securetty 600 root 로그인을 허가하는 TTY 인터페이스 리스트
          /etc/shutdown.allow     400 ctrl+alt+del 사용을 허가하는 유저 리스트
          /etc/security 700 시스템 접근 보안 정책 파일들
          /etc/rc.d/init.d 750 시작 부트 스크립트 파일
          /etc/sysconfig 751 시스템과 네트워크 설정 파일
          /etc/services 600 서비스명과 포트를 나타내는 파일입니다.
          /etc/inetd.conf 600 인터넷 슈퍼서버 데몬 설정파일
          /etc/cron.allow 400 cron 사용을 허가하는 유저 리스트
          /etc/cron.deny 400 cron 사용을 불허하는 유저 리스트
          /etc/ssh 750 보안쉘(ssh) 설정 파일
          /etc/sysctl.conf 400 최근 레드햇 리눅스에서 커널 tunable 옵션을 담고 있는 파일

         

   레드햇 리눅스를 기반으로 리눅스 시스템을 안전하게 하기 위한 기본적인 조치사항들을           살펴 보았습니다.



   100% 안전한 시스템은 없지만 여기서 기술된 것만 적용해도 리눅스 시스템의 안전성은 상당히 높아질 것입니다. 시스템의 안전한 보호를 위해서는 지속적으로 보안 사항들을 살펴보아야 할 것입니다. 또한 CERT 홈페이지(http://www.certcc.or.kr/)를 위시한 보안 전문 컨설팅 사이트와 시스템 벤더 사이트를 정기적으로 방문하여 보안 권고 사항들에 대해서 주의깊게 살펴보며, 새로운 취약성이 발견되면 그에 따른 패치설치 및 보안 권고에 충실히 따르도록 해야 합니다.


          참고자료

          리눅스 시스템 관리자를 위한 보안 지침Ⅰ, CERTCC-KR, http://www.certcc.or.kr
          Linux Security Tips, 임은재님 번역, http://kltp.kldp.org
          리눅스 보안 하우투, http://kldp.org/HOWTO/html/Security/Security-HOWTO.html
         

Linux] 리눅스 튜닝전략


리눅스 시스템 튜닝 전략 Ver 0.1
글쓴날 : 2000년 2월
글쓴이 : 문태준
(http://www.taejun.pe.kr, taejun@taejun.pe.kr, taejun@hitel.net)
본 내용은 System performance Tunning 부록 B를 번역 및 편집한 것입니다. 리눅스에 맞게 변경하려고 한 것인데 아직은 베타판입니다. 좀더 수정작업을 해야합니다. 여러분들 의견 주시면 감사하겠습니다.

참고자료 :
System Performance Tunning (O'REILLY 출판사, 영문판) 부록B
(92년도에 나온 책이지만 시스템 관리측면에서 많은 도움을 주는 책입니다)
Essential System Administration (한빛 번역판)
7장 시스템 자원관리
(유닉스 시스템 관리에 관련된 내용을 담고 있습니다. 내용은 괜찮은 편이지만 번역 자체가 깔끔하지는 않습니다)
0. 들어가며
성능에 문제가 생기기전에 시스템을 분석하는것이 정말로 중요하다. 하루중 서로 다른 시간대에 시스템의 load average 가 어느정도 되는지, 대부분의 사용자가 어떤 작업을 하고자하는지?
그리고 시스템의 다른 일반적인 정보에 대해서는 미리 알고 있다고 하고 시작하겠다.
시스템에 문제가 생긴다면 다음을 먼저 점검해보자 ㅇ CPU 로드 측정
ㅇ 메모리 문제 점검
ㅇ 메모리에 문제가 없다면 디스크 I/O 점검
ㅇ 디스크와 메모리에 문제가 없는데도 시스템에 문제가 생기면 CPU의 오버헤드에 문제가 있다.
1. 프로세스 통계 설정(Process Accounting)
먼저 시스템에 프로세스 통계를 설정할 수 있는 프로그램이 설치되어 있어야한다. 필자의 경우 패키지가 포함이 되어있었다. 이에 대해서는 통계 설정에 관련된 내용을 참고한다. 본 필자가 작성한 것이 있으니 그것을 보면 될 것이다.
2. 문제가 생기기전 점검사항
시스템이 정상적으로 작동할때 정기적인 모니터링을 해 두어야 시스템에 문제가 생겼을때 어떻게 해야할지 알 수 있다.
ㅇ 주요 사용자들한테 성능이 괜찮다는 동의를 먼저 얻어야한다. 그리고 시스템
성능을 계속 유지할 수 있도록 정기적으로 점검한다.
ㅇ 시스템 통계 프로그램을 설치했다면 그것을 사용하자. 시스템에서 CPU,
I/O, 메모리 집약적인 다섯개의 프로그램들을 알고 있어야한다.
ㅇ vmstat 등의 프로그램을 이용 I/O연산이 얼마나 분산되어있는지, CPU가
작동하지 않고 노는 시간(idle)은 얼마인지, 정상적인 부하가 걸릴경우
메모리를 얼마나 사용하고 있는지 확인한다.
3. 문제가 생겼을경우
시스템이 정상적으로 잘 작동하고 있을때 모니터링을 했다면, 사용자가 불평하기전에 언제 시스템 성능이 나빠지는지 알수가 있다. 그러면 이러한 문제에 대해서 어떻게 대응해야할지도 알 수가 있을 것이다.
ㅇ 어떤 프로그램을 실행하고 있으며 어떻게 사용하고 있는가? 예를 들어
네트웍을 통해 파일에 접근하고 있다면 네트웍 성능이 떨어지는게 문제의
한 부분이라는걸 알 수 있을 것이다.
ㅇ load average를 보기 위해 uptime 을 실행하자. 줄어들고 있는가 늘어나고 있는가?
높은가 낮은가?
ㅇ ps aux 를 실행해보자
- 디스크 액세스나 페이징을 기다리고 이는 프로세스가 있는가? 그렇다면,
I/O와 메모리를 점검하자.
- CPU, 메모리를 가장 많이 사용하는 프로세스를 찾으면 부하분산에 도움이 될 것이다.
ㅇ vmstat 5 5 를 시행해보자(5초간 5번)
- cpu에서 시스템에서 사용하는 cpu시간(sy 항목)이 50%를 넘는가? 그렇다면 I/O에서
문제가 있는 것으로 예상된다. 소스코드에 접근할 수 있다면 해당 프로그램이
효율적으로 I/O를 사용하는지 점검하자.
- 시스템 전체 부하가 높은데도 cpu에서 휴지시간(idle time, id 항목)이 10%를 넘는가?
그렇다면 I/O나 메모리에 문제가 있는 것으로 예상된다.
- 휴지시간이 항상 0인가? CPU가 100% 사용되는것은 좋은 일이다. 그러나 항상
100% busy인 상태에 있다면 어디선가 작업이 계속 축적되고 있는것이다.
이는 cpu의 과부하를 말해준다.
- 디스크의 활동이 분산되지 않았다면, I/O 작업을 효율적으로 분산시켜야한다.
이중에서 한가지도 해당하지 않고 메모리와 I/O관련 튜닝을 할 필요가 없다고 분석되었다면 CPU에 과부하가 걸린것이다.
CPU의 과부하에 대처할 몇가지 방법이 있다. 그렇지만 CPU의 과부하는 메모리와 I/O문제로 나누어지기때문에 찾아내기 힘든 부분이다.
- 필요없는 대몬을 없앤다. rwhod와 routed는 시스템 성능을 저해하는 프로그램으로
이를 없애는 것만으로도 많은 도움이 될 것이다.
- at이나 cron등을 이용 작업을 밤이나 시스템의 부하가 적을때 실행하는 것도
좋은 방법이다.
- CPU집약적인 작업은 nice를 이용 실행우선순위를 낮추면 편집과 갈은 상호대화적인
작업의 성능이 향상될 것이다.
- cpu집약적인 작업의 실행우선순위를 높이면 작업 자체는 빨라지겠지만 상호대화적인
작업의 성능은 떨어질 것이다.
- nice를 이용하는것은 임시방편일 뿐이다. 부하가 계속 증가한다면 nice를 이용하는
것에도 한계가 있다. 시스템을 업그레이드하거나 부하를 분산할 시스템을 구입하자.

4. 메모리 문제 파악하기
시스템에 과부하가 걸려있는데도 휴지기간(idle time)이 많거나 ps에서 많은 양의 메모리를 필요로 하는 프로그램이 실행되고 있다면 메모리 문제를 생각해 볼 수 있다.
ㅇ vmstat 5 를 실행해보자.
- swap-out이 지속적으로 항상 발생한다면 메모리가 부족한 것이다. 주기적으로 swap-outs이
발생하는건 정상적인 것이다. BSD 시스템에서는 비상호대화적인 작업을 스왑아웃한다.
현재 실행하고 있는 프로그램에서 스왑아웃이 계속 발생한다면 프로그램이 죽을 수도 있으며
심각하게 메모리가 부족하다는것을 가리킨다. 스왑아웃필드(so)가 항상 0에 가까워야한다.
- ps나 통계시스템에서 메모리 집약적인 작업이 있는가? RSS필드나 storage integral이 큰
프로그램을 찾아보자.
(RSS는 프로세스가 사용중인 실제 메모리 크기. kbytes 단위.)
(storage integral은 sa -K 옵션을 이용해 볼수있음.)

메모리 문제를 해결할 몇가지 방법을 찾아보자.
- 시스템에서 버퍼 캐쉬가 있다면 크기를 줄인다. 대신 디스크 I/O성능에 영향을 줄 수있다.
- 정적으로 할당한 스트림 버퍼(STREAMS buffers)가 있다면 , 버퍼(2048-4096 byte)의 크기를 줄인다.
그러면 네트웍의 성능은 떨어질 수 있지만 netstat 를 이용해 현재의 시스템에서
실제로 필요한 버퍼의 크기를 예상할 수 있을 것이다.
- 커널 테이블의 크기를 줄인다. 이를 통해 시스템의 자원을 제약할 수 있다. (파일 갯수, 프로세스
갯수등)
- 많은 메모리를 필요로 하는 프로그램은 밤에 돌리자.
- 많은 메모리를 필요로 하는 프로그램은 배치 큐를 이용해 작업하자. at, cron등 활용
- 자기만 사용하는 프로그램이라면 프로그램에서 메모리를 효율적으로 사용하는지 점검하자.
- 메모리 요구량을 줄이기 위해 공유 메모리를 사용하자.
- sendmail은 메모리를 많이 사용하는 프로그램으로 sendmail을 실행하는데 사용되는 시간에
제한을 두자. 아니면 네트웍을 재구성해서 메일서버를 다른 시스템으로 옮길 수 있다.
- 이막스는 메모리를 많이 사용하는 프로그램으로 다른 에디터를 사용하자.
- 이 모든게 안되면 메모리를 구입하자
5. 디스크 I/O 문제 파악하기
시스템에 과부하가 걸려있는데도 휴지기간(idle time)이 많다면 디스크 I/O 문제를 생각해 볼 수 있다. 보통 메모리 문제와 I/O문제는 서로 관련이 되어있다.
ㅇ vmstat 5 를 실행한다. 그리고 이것을 정상적인 시스템 상황과 비교해본다. 정상적인
경우보다 디스크 연산이 더 높은가?
ㅇ 디스크 활동이 시스템 디스크에 골고루 분산되어있는가?
ㅇ 그렇지 않다면 가장 활동적인 디스크가 가장 빠른 디스크인가?
ㅇ 디스크 활동이 디스크의 특정 영역에 집중되어있는가? 디스크에 적당히 분포되어있는가?
아니면 서로 다른 반대방향의 지점에 있는가?
ㅇ NFS를 사용하고 있는가? 사용자들이 자신의 지역?파일에 접근하는데 속도가 느리다고
보고를 하는가? 원격 파일시스템을 사용하는가? 만약 원격 파일시스템을 사용하면
네트웍 상황에 대해서 살펴보자. 이경우에는 지역 디스크 I/O문제는 아니다.
ㅇ vmstat를 이용 메모리 상황을 살펴보자. 시스템에서 페이징이나 스와핑이 계속 일어나고
있다면, 메모리에 문제가 있으며 이경우 디스크 I/O에 심각한 문제를 초래할 수 있다.
먼저 메모리 문제를 살펴보아야한다.
이에 대한 해결책을 찾아보자.
ㅇ 파일시스템을 재구성하고 가능한한 I/O작업을 분산시킨다.
ㅇ 루트 파일시스템에 가장 빠른 디스크 드라이브와 컨트롤러를 사용한다. 루트 파일
시스템이 대부분 가장 많은 I/O작업을 한다. 특정한 파일의 성능이 중요하다면 성능이
중요한 파일을 하나의 파일시스템에 넣고 이 파일시스템에 가장 빠른 드라이브를
사용한다.
ㅇ 퍼포먼스가 중요한 파일을 블락 사이즈가 큰 파일시스템에 넣는다.
(리눅스에서 기본은 1k)
ㅇ 버퍼 캐쉬의 크기를 늘린다. 그러면 대신 메모리에 문제가 생길 수 있다.
ㅇ 단편화를 제거하기 위해 주기적으로 파일시스템을 재구성한다.
ㅇ 자주 사용하는 파일을 파일시스템의 시작부분에 집중시키는 프로그램을 사용할수 있다.
디스크 용량에 문제가 생길 수도 있다. 파일시스템에 여유공간이 부족한가?
그렇다면 몇가지 방법을 생각해보자.
- 필요없는 파일을 cron 등을 이용 정기적으로 삭제하자. 오래된 코어 덤프 파일,
에디터 백업파일, auto-save 파일 등등.
ㅇ 디스크 쿼터를 이용해 사용자의 디스크 용량 사용을 제한할 수 있다.
ㅇ 매우 작은 파일이 모여있는 파일시스템에는 작은 블럭 사이즈를 사용한다.
(소스 코드, 작은 데이타 파일 등등)
6. 네트웍 문제 점검
네트웍 문제 점검
ㅇ rlogin이나 NFS를 이용하 파일에 접근하는 사용자가 성능이 느리다고 생각이
든다면 이는 네트웍 용량이나 데이터 정합성이 문제가 있을 수 있다.
ㅇ netstat -i 를 실행하자. 충돌(collison)이 크면 네트웍에 오버헤드가 걸렸다고
생각할 수 있다. input이나 output 에러가 많다면 하드웨어 문제일 수 있다.
입력에러가 많다면 네트웍의 특정한 곳에 문제가 있을 가능성이 크며
출력에러가 많다면 시스템과 네트웍 인터페이스에 문제가 있을 가능성이 크다.
ㅇ 충돌이나 네트웍 하드웨어의 문제가 아니라면, 어떤 시스템이 가장 느린지를
찾아야한다. spray 프로그램을 이용해 느린 시스템에 다량의 패킷을 보내자.
dropped 패킷이 크다면, 원격 시스템은 아마도 들어오는 자료에 대해 충분히
빠르게 대응하지 못할 것이다. 원격 시스템에 cpu, 메모리, 디스크 I/O문제가
있는지 확인하자. 그게 아니라면 그 시스템은 네트웍의 과부하에 견디지 못할 것이다.
네트웍을 다시 재구성하고 느린 시스템을 파일 서버로 사용하지 말자.
ㅇ droppted 패킷이 많다면 데이타 corruption 이 많다는 것이다.
원격 시스템에서 netstat -s를 실행한다. 그리고나서 지역 시스템에서 원격 시스템으로
spray 명령을 사용하고 다시 netstat -s 를 실행한다. UDP socket full drops가
증가하는게 spray의 결과에서 나온 drop 패킷과 같거나 더 많다면 원격 시스템은
느린 네트웍 서버이다. socket full drops 의 증가하는 숫자가 dropped 패킷보다
작다면 네트웍에 문제가 있는지 확인해보자.
ㅇ nfsstat 를 실행하고 클라이언트의 RPC 데이타를 관찰해보자.
생략...
ㅇ 현재의 시스템에서 스트림 기반 네트웍 작업을 한다면, netstat -m (?. 안돔)
을 실행하자. 충분한 스트림 버퍼가 있는가?
네트웍 부하 줄이는 방법
ㅇ 사용자가 네트웍을 통해 I/O집약적인 프로그램을 실행하지 않도록 막자.
grep 프로그램이 I/O 집약적인 프로그램중의 대표적인 예이다. 대신 네트웍을 통해
로그인해서 작업하자.
ㅇ 네트웍에 연결된 컴퓨터와 디스크를 재구성해서 가능한 많은 사용자가 지역
지역 시스템에서 작업을 하도론 만든다.
ㅇ 디스크없는 워크스테이션의 숫자를 줄인다. 가능하다면 이런 워크스테이션은 제거한다.
ㅇ 뛰어난 네트웍 성능을 가진 시스템을 파일서버로 사용한다.
ㅇ 스트림 버퍼가 작다면(그리고 SunOS 4.0이나 System V.3또는 이전 버전을 운영한다면)
버퍼를 늘리기 위해 커널을 재구성한다.
데이터 integrity(정합성)에 문제가 있다면 유일한 해결책은 문제가 있는 하드웨어를 찾아서 바꾸는 것이다. 네트웍 분석툴이 이러한 작업을 하는데 반드시 필요할 것이다.
7. 터미널 I/O
유닉스 시스템은 전형적으로 터미널에 아주 높은 우선순위을 준다. 그래서 키보드에서 작업을 하고 반응을 확인하는데 문제가 생기는 경우는 거의 없다. 그렇지만 몇가지 문제가 생길 수 있느것을 생각해보자.
ㅇ ps에서 getty 프로세스에서 사용하는 시간이 계속 늘어나고 있다면
누군가가 터미널 라인에서 채팅을 하고 있는 것이다. 파일을 수정해서
터미널 라인을 사용하지 못하게 하자. (어떤 파일은 시스템과 연관되어 있다)
ㅇ 사용자가 터미널의 성능에 대해 불평을 하는 경우 시스템에 직접 연결된 것인지,
아니면 rlogin을?사용한 것인지, X 터미널인지, 아니면 다른 방법을 이용해 연결한
것인지 확인을 하자. 이럴경우 터미널 I/O문제라기보다 네트웍에 문제가 있을
가능성이 많다.
ㅇ 상호대화적인 작업에서 반응이 느리다면 CPU 성능에 관련된 문제를 해결하는게
좋다. System V.2, V.3 또는 SunOS 4.0를 사용하고 있다면 스트림 버퍼가 부족할 수도 있다.
netstat -m을 실행하고 samll data blocks 할당에 문제가 있는지 살펴조자(?)
그러다면 커널에서 스트림 버퍼를 더 작게한다?
8. 일반적인 팁
몇가지 상호대화적인 작업의 성능을 향상시킬수 있는 몇가지 팁이 있다.
ㅇ pwd 대신 dirs를 사용한다.
ㅇ ps를 가급적 사용하지 않는다.
ㅇ sh 를 사용하는 경우, 경로를 줄여서 사용한다.
ㅇ 디렉토리당 파일을 최소화한다.
ㅇ 이막스대신 vi 등을 사용한다.
ㅇ grep이나 fgrep 대신 더 빠른 egrep을 사용한다.?
ㅇ NFS를 사용하는 경우 grep이나 I/O집약적인 프로그램을 실행하지 않는다.
ㅇ 원격시스템의 파일에 접근하려면 NFS대신 rlogin을 사용한다.