설정 변경과 시스템 보안 설정

기본적인 사용 환경을 설정하고 나면, 이제 솔라시스는 동작 상태에 있게 된다. 하지만 이것만으로 관리자의 기본 임무가 끝나는 것은 아니다. 하드웨어와 소프트웨어 만큼의 성능이 나야만 완성된 시스템으로 평가받을 수 있다. 마지막으로 시스템의 주요 패러미터를 통해 성능을 튜닝하는 법과 보안을 위한 설정에 대해 알아보겠다.

김봉환_ bhkim@korea.sun.com 한국 썬마이크로시스템 시스템엔지니어링본부 과장
컴퓨터에서 튜닝이라 함은 시스템에서 운영되는 소프트웨어가 시스템에서 제공되는 모든 자원을 균형되고 조화롭게 주어진 시간동안 변함없이 잘 사용해 가장 좋은 결과를 낼 수 있도록 하는 작업이다. 따라서, 가장 우선적으로 해야 할 것은 사용할 시스템에서 실행할 애플리케이션의 타입이다. 애플리케이션의 실행시 패턴을 분석해 어떤 형태의 작업을 많이 하는지를 예측할 수 있어야 하는데, 이 부분은 실제로 개발을 직접하는 경우가 아니면 알기 힘든 경우가 많다.
따라서, 상용 소프트웨어와 자체적으로 개발한, 혹은 공개 소스를 직접 적용하는 경우로 나눠 생각해야 한다. 애플리케이션이 어떻든 간에 튜닝할 때는 기준을 갖고 있어야 하는데, 크게 CPU, 메모리, 디스크, 네트워크의 4가지로 나눌 수 있다.

상용 소프트웨어의 튜닝
일반적으로는 상업용 소프트웨어의 경우는 대체로 튜닝에 대한 고려가 이미 되어 있어 설치 매뉴얼이나 혹은 별도의 튜닝가이드를 제공하는 경우가 많다.
대표적인 데이터베이스 소프트웨어인 오라클을 생각해 보자. 이 소프트웨어는 사용자가 추가한 레코드를 디스크에 저장하는 것이 기본 작업이고, 입력된 내용을 기반으로 사용자의 질의를 분석해 디스크에 저장된 내용을 이렇게 저렇게 바꿔서 보여주는 역할을 한다. 당연히 디스크를 많이 사용하게 됨을 예측할 수 있다.
또 하나는 디스크에 저장하기 전에 속도 개선을 위해 메모리를 버퍼 영역으로 쓸 것이란 것도 어느 정도 예상된다. 따라서 이런 소프트웨어는 디스크의 성능과 메모리의 양이 속도에 비례한다는 것을 쉽게 예측할 수 있다.
일반적으로 메모리의 속도는 사용자가 결정할 수 있는 것이 아니므로, 메모리의 양을 조절함으로써 성능 향상을 도모할 수 있다. 물론 시스템 메모리의 최대치를 끌어다 쓰는 것으로 설치시 권고하고 있다. 여기서는 오라클 설치시 오라클을 위한 메모리의 양을 정하는 방법을 살펴보겠다.
솔라리스 커널은 동적으로 링크되는 모듈을 포함해 거대한 하나의 독립된 프로그램이다. 따라서, 여러 개의 모듈에서 사용되는 모듈별 로컬 변수(모듈내에서 정의된 변수들)과 커널 전체에 영향을 주는 커널 글로벌 변수들이 있다.
일반적으로 시스템 튜닝을 한다는 것은 이 변수들의 값을 적절하게 변경함으로써 더 좋은 결과를 도모하는 것이다. 여기서 잊지 말아야 하는 것은 썬과 같이 하드웨어와 운영체제를 같이 만드는 경우에는 대개 자체 제작 시스템에 대해 잘 알고 있으므로 운영체제가 그 시스템에 맞도록 기본적으로 튜닝이 모두 되어 있다고 봐야 한다. 단, 시스템에 따라 메모리의 양이나 디스크의 속도는 다를 수 있다. 따라서 이런 요소들에 대해 기본 설정값에 따라 애플리케이션을 실행보지도 않고, 시스템 튜닝에 대한 강박 관념에 빠질 필요는 없다.

공유메모리, 세마포어, 메세지 큐
데이타베이스들은 모두 임시 영역으로 공유 메모리를 사용하고, 여러 개의 프로세스들이 공유 메모리를 사용할 때를 위해 세마포어를 사용하며, 프로세스간 통신을 위해 메세지 큐를 사용한다. 이 값들이 설정되어 있는 것을 확인하려면 #sysdef | tail -24 사용한다 또한 공유 메모리 등의 사용 상태를 확인하기 위해서는 #ipcs를 사용한다(화면 1).
확인한 공유 메모리의 크기가 현재 시스템이 제공하는 메모리에 비해 너무 작은 경우 성능을 향상시키기 위해 공유 메모리의 크기를 확대할 수 있다. 공유 메모리를 포함해 세마포어나 메세지 큐의 크기를 변경하고자 하는 경우에는 /etc/system 파일을 직접 변경해야 한다(화면 2).
공유 메모리 관련 패러미터는 다행이도 설정값과 상태를 보여주는 전용 명령어가 있어 상대적으로 편리하다. 물론, 설정할 때는 편집을 해야 한다는 불편함이 있다. 그러나 그외 튜닝할 수 있는 값들은 일반적으로 전용 명령어가 없다. 따라서 앞서 언급한 대로 커널의 일반 변수를 보듯이 디버거를 이용해 변수값을 살펴야 한다. 물론, 설정하는 방법은 /etc/system 파일을 수정해야 한다.
예를 들어, 현재 시스템에 많은 사용자가 로그인하거나 혹은 서비스를 하는 프로세스가 많이 있거나, 디스크에 크기가 작은 파일들의 읽기/쓰기 작업이 많은 경우에 가장 기본적으로 설정할 수 있는 커널 패러미터는 ‘maxusers’다.
따라서 현재 maxusers값이 어느 정도 설정돼 있는지를 알기 위해서는 다음과 같이 입력한다. 물론 이 경우 /etc/system에 설정된 명령어가 없거나 혹은 제대로 설정돼 있는지를 확인하기 위해 사용한다.

#echo “maxusers/D” | mdb -k

이 설정값과 관련해 흔히 발생하는 오류는 웹서버와 같은 경우에는 실제 로그인하는 사용자가 없기 때문에 숫자를 작게 사용해야 하는게 아닌가하고 생각하는 경우다. 그러나 한명의 사용자가 일반적으로 4~5개의 프로세스를 돌린다고 가정하면, 이 숫자 이상의 다른 종류의 프로세스가 실행되면 maxusers 값을 올릴 것을 권고한다.
그외 튜닝이 필요한 경우에 해당하는 커널 패러미터는 다음과 같다.

·ufs_throttles, ufs_HW, ufs_LW
확인 방법은 #echo “ufs_throttles/D” | mdb -k이다.
디스크에 써야할 작업 건수를 의미하는 것으로, 기본적으로 이 값이 0보다 크다는 것은 운영체제가 쓰는 속도보다 디스크가 느리거나 혹은 쓰기 행위를 하는 작업이 많은 것이다. 흔히 파일 시스템 상에 크기가 큰 파일들을 쓰기하는 프로세스가 많은 경우 발생한다.
실행하고 있는 프로세스는 많으면서 CPU 상태는 idle이 많고 프로세스 상태는 blocked로 돼 있는 경우가 일반적이다.
ufs_throttles의 값이 0보다 크면, 스토리지가 고속인지를 확인해 고속 디스크라면 ufs_HW와 ufs_LW값을 높인다. 기본 설정값은 일반적인 단일 SCSI 디스크 수준의 속도에 맞춰져 있다.

cat /etc/system
set ufs_HW=1048576
set ufs_LW= 524288

따라서, RAID 0나 5로 구성되거나 혹은 하드웨어 RAID 스토리지는 일반 디스크의 경우보다 쓰기 속도가 빠르므로 ufs_HW/ufs_LW를 상향 조정함으로써 성능을 개선할 수 있다.
그렇지 않으면 운영체제가 내장하고 있는 파일 시스템 버퍼링때문에 생길 수 있는데, 해당 작업이 많은 파일 시스템을 forcedirectio의 속성을 주어 재마운트함으로써 성능을 개선할 수 있다. 가급적이면 forcedirectio를 사용할 것을 권고한다.
또 한가지 주의할 것은 ufs_LW는 ufs_HW 값의 1/2로 설정하며, ufs_HW값보다 크지 않도록 주의한다(화면 3)
확인 방법은 #echo “ncsize/D” | mdb -k이고, 파일 시스템에 접근하는 쓰레드나 프로세스가 많은 경우에 늘려준다.
솔라리스 8 6/00 이전에는 #kstats -n ncstats로 확인해서 “enters”의 값이 높으면 증가시킬 필요가 있으며, 솔라리스 8 6/00 이후에는 #kstats -n dnlcstats에서 pick_last 값이 크면 키우도록 한다.
이 패러미터는 파일 정보를 캐쉬하는 메모리 영역을 크게 잡아주는 역할을 한다. 따라서 같은 파일들을 빈번하게 읽는 웹 서버나 메일 서버, 미디어 파일 서버 등에서 효과가 있다. 기본적으로 Maxusers값을 이용해 자동으로 설정되는데, 자동설정 공식은 다음과 같다. 최대치는 MAXINT까지 설정할 수 있는데, 이 경우 커널 메모리를 많이 소모한다.

=4 x ( v.v_proc + maxusers ) + 320

·maxusers
확인 방법은 #echo “maxusers/D” | mdb -k이다.
보편적으로 시스템에서 많은 사용자가 로그인하거나 사용할 애플리케이션이 많은 경우 늘리도록 한다. 기본적으로 이 값에 의해 max_nprocs와 maxuproc값이 결정된다. 이 값을 높게 설정하면 커널에 의해 과도한 메모리가 선점될 수 있으므로 데이터베이스, 파일 서버 등에서 적은 프로세스만 실행되는 경우에는 이 값을 작게 하는 것이 좋다.

#cat /etc/system
set maxusers=1024

·noexec_user_stack
확인 방법은 #echo “noexec_user_stack/D” | mdb -k이다.
32 비트 애플리케이션에서 버퍼 오버플로우 공격을 어렵게 만드는 역할을 하며, 64비트 애플리케이션은 기본적으로 설정돼 있다.

online enable
#echo “noexec_user_stack/W1” | mdb -kw

영구 변경
#cat /etc/system
set noexec_user_stack=1
set noexec_user_stack_log=1

·rlim_fd_max
확인 방법은 #echo “rlim_fd_max/D”|mdb -k이다.
하나의 프로세스당 최대 오픈 파일 개수로, 애플리케이션들이 파일을 열 때 영문없이 죽는 경우 조정해보도록 한다. .

·rlim_fd_cur
확인 방법은 #echo “rlim_fd_cur/D” | mdb -k이다.
rlim_fd_max의 값과 같지 않은 경우에는 이 값을 일단 크게 하도록 한다.
실행중인 프로세스의 fd 관련 값을 알기 위해서는 #plimit 나 $pfiles 를 사용한다.
프로세스 내의 최대 오픈 파일 개수인데, setrlimit()이라는 시스템 콜로 최대 rlim_fd_max까지 증가시킬 수 있다. 기본적으로 애플리케이션은 먼저 이 값의 영향을 받는다. 그 다음 모자라면 증가시키는 방법을 쓰도록 한다.
간혹 rlim_fd_cur을 증가시키지 않은 경우에는 /etc/system에 값을 설정해야 한다. 멀티 쓰레드를 사용하는 웹서버와 같은 경우에는 4096 이상의 값을 올리도록 권장된다.

#cat /etc/system
set rlim_fd_max=4096
set rlim_fd_cur=4096

·Bufhwm
확인 방법은 #sysdef | grep bufhwm이다.
운영체제가 I/O를 위해 별도로 확보하는 캐슁 영역으로, 대량의 파일 시스템 쓰기 작업이 발생하는 경우 커져야 한다. 기본값은 실제 메모리의 2%이다.
주의할 것은 메모리가 매우 크다면 이 값도 매우 커지게 된다. 이런 경우에는 낮출 수 있으며, 특히 HA 환경에서는 이 값이 클수록 시스템 충돌이 발생했을 때 파일 시스템이 손상될 가능성이 높아진다.

#cat /etc/system
set bufhwm=1024786

·ufs_ninode
확인 방법은 #echo “ufs_ninode/D” | mdb -k이다.
대량의 파일을 많이 읽어야 하는 경우(UFS 상에서) 이 값을 키울 필요가 있다. #kstat -n inode_cache에서 maxsize reached가 maxsize보다 크면 변경해야 한다. 하지만 값을 너무 과도하게 키우면 idle queue가 길어지고, ufs 작업시 시간을 오래 걸리는 경우를 유발한다.

#cat /etc/system
set ufs:ufs_ninode= 16884

·tmpfs_minfree
확인 방법은 #echo “tmpfs_minfree/D” | mdb -k이다.
/tmp에 파일을 많이 사용하는 경우에 다음과 같은 에러가 나면 크기를 바꾼다.

“fs-name:File system full, swap space limit exceeded”
#echo “tmpfs_minfree/W100” | mdb -kw

네트워크 설정
네트워크와 관련된 부분은 커널 패러미터 설정법과 마찬가지로 /etc/system에서 설정할 수 있으나, 네트워크 관련 커널 패러미터 변경은 특별히 시스템 사용중에 변경할 수 있는 방법을 제공한다. 이렇게 하기 위해 솔라리스는 별도의 디바이스를 통해 원하는 값을 변경할 수 있다.
네트워크는 크게 네트워크 카드와 TCP, IP로 나눠 설정할 수 있다. 네트워크 인터페이스는 여러 가지가 있으므로, 여기서는 100Mbps 고속 이더넷 네트워크인 hme를 대상으로 설명한다.
인터페이스에서는 시스템의 성능 향상을 위한 조정값은 없다. 일단 관련 인터페이스에서 조정 가능한 변수를 보기 위해서는 #ndd /dev/hme ?를 입력하면 (화면 4)와 같은 결과를 얻을 수 있다.
여기서 시스템의 네트워크 카드가 100Mbps 전이중(full duplex)으로 설정돼 있지 않은 경우, 네트워크의 성능이 제대로 나오지 않을 때 변경하는 것이다. 스위치가 100Mbps 전이중 방식을 지원하는 경우, 다음과 같이 하면 100MB-FDX로 변경할 수 있다.

#ndd -s /dev/hme adv_autoneg_cap 0 <- 자동 설정을 불가능하게 한다.
#ndd -s /dev/hme adv_100fdx_cap 1 <- 100-Full Duplex를 강제 설정한다.
#ndd -s /dev/hme adv_100hdx_cap 0 <- 100-Half Duplex를 강제 해제한다.
#ndd -s /dev/hme adv_10fdx_cap 0
#ndd -s /dev/hme adv_10hdx_cap 0

일반적인 네트워크의 성능이라 함은 네트워크를 사용하는 애플리케이션의 타입에 따라 TCP 연결의 성능을 좋게하는 것을 의미한다. 다음은 tcp의 변경가능한 패러미터를 보는 방법이다(롸면 5).

#ndd /dev/tcp ?
TCP 값의 변경은 애플리케이션의 타입에 따라서 좀 달라질 수 있다.
예를 들면, connection oriented냐 혹은 아니냐에 따라, 영향이 가는 변수가 달라진다. 다음은 짧은 접속을 대량으로 갖는 웹서버 테스트에서 적용되는 튜닝 경우이다.

서버측 튜닝
Operating system changes in (/etc/system)
__ set sq_max_size = 0 (unlimited messages allowed on each IP queue)
__ set segmap_percent = 90 (def: 12, Size of kernel segmap segment)
__ set rlim_fd_max = 70000 (def: 1024 file descriptors)
__ set ge:ge_intr_mode=1 (1=bypass normal communication layer queuing)
__ set ge:ge_tx_fastdvma_min=512 (def: 1024, min packet size to use fast dvma interface)
__ set ge:ge_nos_tmds=2048 (def: 512, transmit descriptors)
__ set pcisch:pci_stream_buf_enable=0 (0=disable PCI cache streaming)
Network Tuning parameters (/usr/sbin/ndd)
__ ndd -set /dev/tcp tcp_time_wait_interval 60000 (def: 240000 ms = 4 mins.)

클라이언트측 튜닝
Network Tuning parameters (/usr/sbin/ndd)
__ ndd -set /dev/tcp tcp_time_wait_interval 60000 (def: 240000 ms = 4 mins.)
__ ndd -set /dev/tcp tcp_smallest_anon_port 5001 (def: 32768)
__ ndd -set /dev/tcp tcp_conn_req_max_q 1024 (def: 128)

보안 관리
보안과 관련해서 시스템 커널을 손봐야 하는 경우는 그리 많지 않다. 사실 커널에 문제가 있다면 리눅스가 아닌 이상 소스에 손을 댈 수가 없으므로, 썬에서 패치를 제공할 때까지 기다려야만 할 것이다. 따라서 시스템이 보안에 노출되지 않도록 하는 것이 중요한다.
또한 기업에 있어 보안대책의 중요성은 자명한 것이다. 만일 웹 서버의 정보나 서비스 자체를 크래킹당해 고객 정보를 도둑맞는 사태가 벌어진다면 회사의 신용은 매우 떨어질 것이다.
또한 개인이 운영하고 있는 웹 사이트의 경우에는 크래킹을 당했다고 해도 심각한 손해는 발생하지는 않을지도 모르지만, 이를 시작으로 보안대책이 점차 소홀해질 경우 그 사이트는 크래커에 의해 적당한 발판(크래커가 타겟을 공격할 경우에 경유하는 사이트)이 될 위험성이 크다. 결과적으로 발판이 된 사이트는 크래킹에 가담한 것이 된다.
보안 확보는 모든 사이트에 있어서 필수적인 과제다. 다만 보안 상의 허점은 항상 새로운 것이 발견되고 있기 때문에, 현 시점의 모든 보안 허점을 막았다고 해도 안심할 수 없다. 하지만 모든 웹마스터가 보안의 권위자가 될 필요는 없다. 기본만 지키면 우선은 안심해도 된다.
패치를 적용하는 것은 보안대책의 기본이다. 아무리 좋은 보안툴을 도입한다 하더라도, 운영체제에 보안 상의 허점이 있으면 아무 의미가 없다. 따라서 SunSolve 사이트(sunsolve.sun.com)에서 패치 리포트를 정기적으로 체크할 것을 권한다.
이곳에는 패치에 대한 정보가 수시로 갱신되는데, 모든 패치가 필요한 것은 아니다. 여기서 어떤 것이 필요한 패치이고, 어떤 것이 그렇지 않은지 자세히 설명하기는 어렵지만 ‘Recommended Patches’와 ‘Security Fives’ 등의 패치는 반드시 적용하기 바란다.
보안 관리의 기반이 되는 것은 보안 정책이다. 보안정책이란 어떻게 정보 시스템의 보안을 확보할 것인가에 대한 지침이다. 기업이나 단체 등 조직별로 적절한 보안정책을 설정해 조직 전체가 지키는 것이 중요한데, 로컬 네트워크 중에 보안이 약한 시스템을 틈타 크래커가 침입해올 위험성이 있기 때문이다.
하지만 조직 전체에서 지켜야 하는 규칙이기 때문에 대상범위가 넓고, 서버 관리자의 권한 밖에 있는 부분도 있는데, 여기서는 보안정책 중에서 웹 서버 관리자와 직접적으로 관계된 어카운트와 서비스 정책에 대해 설명한다.

어카운트 정책
어카운트 정책이란 사용자 어카운트를 관리하기 위한 지침이다. 시스템의 용도에 따라 다르지만, 웹 서버의 경우 일반 사용자의 어카운트를 작성하는 경우가 많기 때문에 주의해야 한다. 사용자가 어떤 방법으로 외부에서 로그인할 필요가 있다고 해서 무턱대고 어카운트를 발행해서도 안되지만, 한 개의 어카운트를 여러 사람이 공유하는 것은 더 위험하다. 예를 들어 컨텐츠 관리자용 그룹을 작성해 파일 퍼미션을 그룹 라이터블로 설정(chmod 명령어에서 파일 퍼미션을 664로 변경)하면 컨텐츠를 관리하는 사람이 여러 명이라도 사용자 어카운트나 패스워드를 공유할 필요가 없다.
또한 루트 어카운트의 경우 디폴트에서 루트 사용자는 콘솔에서 telnet을 이용할 수 있지만, 누가 작업했는지 명확하게 하기 위해 반드시 사용자 어카운트에서 로그인하고, ‘su’를 이용해 루트 어카운트를 사용하도록 한다. 이 작업은 간단한 것이지만 매우 중요한 정보를 제공한다.
보다 안전하게 하기 위해서는 CONSOLE을 root에게만 허용하고 모든 사용자는 자신의 아이디를 사용해서 로그인하고, root가 필요한 경우에는 su root 사용하도록 한다.
또한 기업이나 학교 등에서는 다수의 관리자에게 관리권한을 위임하는 경우가 많은데, 이런 경우에도 루트의 패스워드를 공유하는 것은 매우 위험하다. 이럴 때는 ‘sudo’ 명령어를 이용하면 루트 패스워드를 공유하지 않고도 루트 권한을 이용할 수 있다.
또한 솔라리스 8에서는 root가 해야하는 많은 시스템 관리들을 여러 개로 범주화한 후 특정 사용자들에게 역할을 맡겨 사용자가 특별히 root 어카운트를 공유하지 않고도 원하는 시스템 작업을 할 수 있도록 해주는 기능이 있다. 이를 일러서 ‘역할 기반의 접근 권한 통제(Role base Access control)’라고 한다.

‘sudo’ 명령어 사용
‘sudo’ 명령어를 사용하면 실행에 있어 루트 권한이 필요한 명령어를 일반 사용자가 실행할 수 있는데, 이것은 Sunfreeware.com에 패키지가 있다(www.sunfreeware.com).
(리스트 1)은 인텔용 솔라리스 7에서 ‘sudo’ 패키지를 설치하는 과정을 나타낸 것인데, 직접 컴파일하든 패키지를 이용하든 상관없이 ‘/usr/local/’ 아래의 디렉토리에 설치된다.
또한 설치를 마쳤으면 ‘sudo’의 설정파일(‘/etc/sudoers’ 또는’/usr/local/etc/sudoers’)을 편집하기 위한 전용 명령어인 ‘/usr/local/sbin/visudo’를 사용하는데, 다수의 관리자에 의해 동시에 설정이 변경되지 않도록 설정파일에 락을 걸어둔다.
‘sudoers’에는 사용자별로 실행을 허가하는 명령어를 기술하는데, 일반적으로 자세하게 설정할 필요는 없다. (리스트 2)에 간단하게 그 예를 들었는데, 여기서는 사용자 ‘l abuser’에게 모든 명령어를 실행할 수 있도록 허가하고 있다. 한편 소스에서 컴파일한 경우는 설정 파일의 예제(/usr/local/doc/sudo/sample.sudoers/)가 설치되므로 보다 자세하게 설정하고 싶은 경우 참고하면 좋다.
‘sudo’ 명령어는 실행하고 싶은 명령어를 인수로 지정해 이용하면(리스트 3), 처음에만 패스워드를 찾기 때문에 사용자 패스워드를 입력한다(리스트 3의 Ⅰ). 단 루트의 패스워드가 아니라는 점을 주의하기 바란다. 이후 세션 내에서는 패스워드 없이 ‘sudo’ 명령어를 실행할 수 있다. 이와 같이 sudo 명령어를 이용하면 루트 패스워드를 공유하지 않고 관리작업을 할 수 있다.

(리스트 1) sudo의 설치 순서
$ wget ftp://nce.sun.ca/pub/freeware/intel/7/sudo-1.5.9p3-sol7-intel-local.gz
$ su
Password:
# gzip -d sudo-1.5.9p3-sol7-intel-local.gz
# pkgadd -d sudo-1.5.9p3-sol7-intel-local

(리스트 2) sudoers의 설정 예
# sudoers file.
#
# This file MUST be edited with the ‘wisudo’ command as root.
#
# See the man page for the details on how to writed a sudoers file.
#
# Host alias specification

# User alias specification
# Cmnd alias specificaton

# User privilege specification
root ALL=(ALL) ALL
labuser ALL=(ALL) ALL 자신의 어카운트를 추가

(리스트 3) sudo 명령어의 실행 예
$ sudo /usr/sbin/useradd -m student
Password:
6 플랙
$

서비스 정책
서비스 정책이란 서버가 제공하는 서비스에 관한 규칙으로, 그 핵심은 필요없는 서비스를 중단시키는 것이다. 솔라리스뿐만 아니라 대부분의 운영체제는 다양한 서비스가 디폴트로 시동되도록 설정되어 있는데, 그 상태에서 웹 서버를 공개하는 것은 아주 위험하다. 따라서 웹 서버의 서비스는 최대한 필수적인 것만 설정한다.
지금까지 아파치를 비롯한 다양한 서비스를 제공하는 툴을 설치해 왔는데, 이번에는 반대로 몇 가지 서비스를 삭제해 보자. 먼저 특별히 주의해야 하는 서비스를 구체적으로 제시하고, 각각 어떤 문제가 있는지 살펴보자.

·telnet
telnet 접속은 사용자에게 쉘 이용을 허가하고 있는 경우에 이용되는 것인데, 패스워드를 포함한 모든 통신 데이터가 평문(Plain Text)으로 흐르기 때문에 도청될 염려가 있어 가능한 한 금지시켜야 하는 서비스다. 보안업계에서는 telnet이 열려 있으면 대문이 열려 있다고 표현할 정도이다. 따라서, 굳이 telnet을 써야 하는 경우에는 ssh 기반의 shell을 사용하도록 하고, 클라이언트인 텔넷 터미널도 SecureCRT같은 것을 사용하도록 한다.

·ftp
ftp는 웹 서버에 컨텐츠를 탑재할 경우에 많이 사용되는데, telnet과 마찬가지로 패스워드가 평문으로 전송되기 때문에 도청될 위험이 있다.

·r계 서비스(rlogin, rsh, rcp 등)
r계 서비스는 ‘/etc/hosts.equiv’나 ‘~/.rhosts’ 파일에 신뢰할 수 있는 호스트 및 사용자명을 미리 기술해 이용하므로 인증없이 로그인 및 원격지로부터 명령어를 실행하는 서비스이다. 패스워드가 네트워크 내부에 흐르지 않는다는 이점이 있지만, 통신 자체는 평문으로 행해지기 때문에 도청에 약할 뿐만 아니라 스푸핑에도 약하기 때문에 가능한 한 금지시켜야 할 서비스이다.

·finger
finger는 개개의 사용자 어카운트 정보를 취득할 수 있는 서비스로, 크래킹의 대상을 결정하는 정보원으로 사용되는 경우가 있다.

·RPC(NIS, NFS 등)
RPC(Remote Procedure Call)는 프로그램 절차의 일부를 프로세스 간 통신으로 네트워크 상의 별도 컴퓨터에 위탁시키는 서비스로, 주로 NIS나 NFS 등에서 이용된다. 이는 IP 스푸핑에 약하며, 웹 서버에서는 컨텐츠를 NFS에서 공유할 경우도 있지만, 성능면에서 보더라도 그다지 권장할 만한 것은 못된다.

불필요한 서비스의 정지
앞에서 보는 바와 같이 이렇듯 일반적으로 이용되는 서비스의 대부분이 크래커의 공격에 대한 위험성을 수반하고 있다. 따라서 이들 서비스를 정지시키려면 ‘/etc/inetd.conf’에 기술된 각 서비스에 대한 항목을 삭제한다. (리스트 4)는 ftp와 telnet 서비스를 정지시키는 설정 예이다. 실제로 이 파일의 정보를 기초로 각 서비스를 시동하는 것은 INETD (InterNET service Daemon)인데, 편집이 끝났으면 INETD를 재시동해 ‘/etc/inetd.conf’를 판독한다(리스트 5).
한편 RPC 서비스 전체를 멈출 경우에는 ‘/etc/inetd.conf’ 기술된 것을 삭제하는 것만으로는 충분하지 않다. 왜냐하면 RPC 서비스 중에는 ‘/etc/rc2.d’ 디렉토리 아래에 스크립트에서 시동된 것이 있기 때문이다. 따라서 ‘/etc/rc2.d/S71rpc’를 s71rpc로 변경하면 RPC를 이용한 서비스는 모두 정지하게 된다.
삭제하면 시동시 경고 메시지가 몇 개 나타나는데, 이것이 신경쓰인다면 ‘/etc/rc2.d’ 디렉토리 아래의 S73cachefs.daemon과 S73nfs. client, S74autofs를 소문자로 시작하도록 변경한다. RPC는 솔라리스 내부 프로그램들끼리의 통신을 위해서도 많이 사용되는 관계로 정지시키기 전에 반드시 확인을 하도록 한다. 예를 들면, CDE는 rpc를 사용하는 대표적인 솔라리스 애플리케이션이다. 굳이 서버로 쓰이는 환경이라면 사용할 필요가 없는 경우가 많으므로, 이 CDE 서비스를 중지한 후 rpc 서비스를 중지하도록 한다.
참고로 앞서 설명한 것처럼 RPC를 이용한 서비스는 보안 취약점이 되기 쉬운데, 솔라리스 7보다 각종 보안 메커니즘을 제공하는 GSS-API(the Generic Security Service API)에 기반해 변경되고, 보안의 안전성과 기밀성이 강화된다. 하지만 솔라리스 7에서는 rpc.cmsd(Sun Solstice AdminSuite Daemon sadmind)에 보안 취약점이 있기 때문에 SunSolve에서 제공되는 보안 패치(ID : 108663-01)를 설치하거나 서비스를 정지해야 한다. 하지만 현재 솔라리스 8에는 이런 문제가 없다. 따라서 위의 패치를 적용한 솔라리스 7이나 8이 있다면 안전하게 RPC 서비스를 운용할 수 있다.
단 솔라리스 7 이전 버전이나 다른 플랫폼이 혼재된 경우에는 RPC 서비스를 모두 정지시키는 편이 낫다.

(리스트 4) /etc/inetd.conf의 설정 예(일부 발췌)
# Ftp and telnet are standard Internet services.
#
#ftp stream tcp6 nowait root /usr/sbin/in.ftpd in.ftpd
#telnet stream tcp6 nowait root /usr/sbin/in.telnetd in.telnetd

(리스트 5) inetd의 재시동 순서
# ps -e|grep inetd 현재 실행중인 모든 프로세스로부터 inted만을 검색
177 ? 0:00 inetd inetd의 프로세스 ID는 177
# kill -HUP 177 inetd의 프로세스를 재시동

TCP 래퍼의 도입
위험한 서비스를 정지시킴으로써 보안 레벨을 높일 수 있지만, 이 상태에서는 콘솔로만 관리 작업을 할 수 있다. 그래서 원격으로도 안전하게 관리될 수 있도록 몇 가지 툴을 도입한다.
일반적으로 클라이언트로부터 요구되는 서비스는 각각 지원한 포트에서 대기하고 있는 데몬이 처리하지만, 동작하고 있지 않은 데몬의 경우 요구별로 INETD가 ‘/etc/inetd.conf’에서 정의돼 있는 데몬을 시동한다.
이 때 문제는 클라이언트의 IP 어드레스에 따라 접속을 허가 또는 거부하거나 정의하지 않은 호출을 받을 때 메시지를 기록하거나 하는 액세스 제어를 행할 수 없다는 점이다. 따라서 TCP 래퍼(Wrapper)는 INETD와 각 데몬의 중개역으로 액세스 제어를 행하는 툴로, 그 구조는 다음과 같다.
클라이언트로부터 접속요구를 받은 INETD는 각 데몬을 호출하기 전에 TCPD(TCP wrapper Daemon)를 호출하고, TCPD가 클라이언트의 IP 어드레스를 조사해 그것이 허가된 호스트로부터의 요구라면 접속을 허가한다. 즉 TCP로 액세스해 온 프로그램에 대해 데몬을 보호(Wrap)하는 프로그램이기 때문에 TCP 래퍼라고 하는 것이다. 이에 따라 외부로부터 포트 스캔을 블록할 수 있을 뿐만 아니라 그와 같은 액세스가 있었다는 것을 즉시 알 수도 있게 해주는 툴로 꼭 도입해 볼 만한 것이다. 솔라리스 9에는 이미 포함되어 있으므로, 환경 파일만 설정을 다시 하면 사용할 수 있다.

TCP 래퍼의 설치와 설정
그러면 이번에는 TCP 래퍼를 설치해 보자. (리스트 6)은 소스파일을 입수하는 것에서부터 설치하기까지의 과정을 나타내는 것으로, (리스트 6)의 1에서는 컴파일시 tcpd를 설치하는 디렉토리(/usr/sbin)와 사용하는 컴파일러(gcc), 시스템 유형(sunos5:Solaris 2.x는 SunOS 5.x)을 지정하고 있다.
설치가 끝났다면 ‘/etc/inetd.conf’를 편집해 서비스를 문자대로 랩한다. (리스트 7)은 ftp와 telnet 서비스를 tcpd로 랩하는 설정 예인데, (리스트 4)에서 삭제한 경우의 내용과 비교해보자. ‘/etc/inetd.conf’를 수정했다면 (리스트 5)와 같이 INETD를 재시동한다. 그런 다음 ‘/etc/hosts.allow(액세스를 인증하는 룰)’와 ‘/etc/hosts.deny(액세스를 거부하는 룰)’를 작성하고 액세스 제어 룰을 설정한다. 이에 대한 각 설정 예를 (리스트 8, 9)에 표시해 두었다.
‘/etc/hosts.deny’에서는 단순히 액세스를 거부하는 호스트를 설정할 수 있을 뿐만 아니라 허가하지 않은 호스트로부터 액세스가 요청될 경우 어떤 행동을 취할 것인가를 기술할 수 있다. (리스트 9)에서는 허가하지 않은 호스트로부터의 액세스가 있을 경우, ‘safe_finger’ 명령어를 사용해 사용자를 조사하고, 그 결과를 루트 사용자에게 메일로 알려주는 행동을 설정하고 있다.
이렇게 해서 TCP 래퍼의 설정도 마쳤는데, 이젠 tcpdchk와 tcpdmatch에서 설정과 움직임을 테스트한다. tcpdchk는 구문이나 랩되어 있지 않은 서비스를 체크하는 툴로, tcpdchk를 실행해 아무것도 표시되지 않으면 문제없는 것이다.
한편 tcpdmatch는 제 1인수로 체크하는 데몬을 제 2인수로 액세스하는 클라이언트를 지정해 실행함으로써 그 클라이언트로부터 액세스가 있을 경우 어떻게 되는가를 표시해 준다. 예를 들어 (리스트 10)에서는 localhost로부터의 telnet 액세스가 허가돼 있는 것을 확인할 수 있다.

(리스트 6) TCP 래퍼의 설치 순서
$ wget ftp://ftp.porcupine.org/pub/security/tcp_wrappers_7.6.tar.gz
$ tar zxvf tcp_wrappers_7.6.tar.gz
$ cd tcp_wrappers_7.6
$ make REAL_DAEMON_DIR=/usr/sbin CC=gcc sunos5 설치할 곳의 디렉토리와 컴파일러, 시스템 타입 지정 Ⅰ
$ su
Password:
# install -c /usr/sbin -u root -g root -m 0755 tcpd tcpd를 /usr/sbin에 설치
# install -c /usr/local/bin -u root -g root -m 0755 tcpdchk
# install -c /usr/local/bin -u root -g root -m 0755 tcpdmatch
# install -c /usr/local/bin -u root -g root -m 0755 try-from
# install -c /usr/local/bin -u root -g root -m 0755 safe_finger 각 툴을 /usr/local/bin에 설치
# install -c /usr/local/man/man8 -u root -g root -m 0644 tcpd.8
# install -c /usr/local/man/man8 -u root -g root -m 0644 tcpdchk.8
# install -c /usr/local/man/man8 -u root -g root -m 0644 tcpdmatch.8
# install -c /usr/local/man/man8 -u root -g root -m 0644 hosts_access.5
# install -c /usr/local/man/man8 -u root -g root -m 0644 hosts_options.5
# install -c /usr/local/man/man8 -u root -g root -m 064 hosts_access.3 각 매뉴얼을 /usr/local/man에 설치
# install -c /usr/local/include -u root -g root -m 0644 tchpd.h 헤더파일을 /usr/local/include에 설치
# install -c /usr/local/lib -u root -m 0644 libwrap.a 라이브러리를/usr/local/lib에 설치

(리스트 7) /etc/inetd.conf의 설정 예(일부 발췌)
ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd
telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd

(리스트 8) /etc/hosts.allow의 설정 예
ALL: localhost 로컬 호스트로부터의 액세는 전부 인정한다
in.telnetd: 192.168.0.0/255.255.255.0 telnet은 자신의 네트워크 인정

(리스트 9) /etc/hosts.deny의 설정 예(1행에서 기술)
ALL:ALL EXCEPT LOCAL firewall.your-company.co.kr :spawn (/usr/local/bin/
safe_finger -l @%h|/usr/bin/mail -s ‘%s denied access from %c’ root) &
자기 사이트의 방화벽 외에서의 액세스는 거부하고, 액세스한 사용자를 조사해 루트에 경고 메일을 보낸다

(리스트 10) tcpdmatch의 실행 예
$ tcpdmatch in.telnetd localhost 제 1인수에 데몬, 제 2인수에 클라이언트(호스트명) 지정
client: hostname localhost
client: address 127.0.0.1
server: process in.telnetd
access: granted localhost는 telnet의 이용이 허가돼 있다
$

그동안 솔라리스를 처음 접하면서 간단한 제품도 설치를 하고, 문제점을 찾는 방법도 알아보았으며, 그것을 통한 튜닝 방법과 시스템을 안전하게 만드는 방법도 살펴보았다.
사실 이 정도 작업을 원활하게 수행한다면, 솔라리스 시스템을 어디에서 운영하든 훌륭한 관리자라고 볼 수 있다. 지금까지 설명했던 것들이 조금은 어려울 수도 있고, 혹은 전혀 이해가 안갈 수도 있지만, 한걸음부터 시작한다고 생각하면 금새 익힐 수 있을 것이다. 가급적이면 여기서는 실행하는 방법등을 자세히 적는다고 부족한 점이 군데군데 보이는 점 또한 인정하지 않을 수 없다. 좋은 기회가 있으면 더 좋은 글로 만날 수 있기를 바란다.

'Security' 카테고리의 다른 글

Tomcat 보안 개요  (0) 2009.03.12
centos5 geoip patch하기  (0) 2008.07.30
MySQL DB 보안(1)  (0) 2007.06.11
FreeBSD 보안 하드닝 Tip  (0) 2007.06.11
SSH 보안설정  (0) 2007.06.11
, .