많은 중소기업 및 학과 등 각처에서 여러가지 용도로 리눅스 서버가 활용되고 있다. 그러나 최근 사용자 수의 증가와 해킹으로 인해 서버가 다운되거나 성능이 저하되는 등 다양한 문제들이 발생한다. 또 일부 기능이 아예 마비되기도 한다. 이러한 서버 문제 등은 업무 마비로 이어지는 경우가 대다수. 이에 리눅스 서버를 관리함에 있어 많은 관리자들이 어려워하는 관리 테크닉을 서버, 메일, DB, 네트워크 분야로 나눠 케이스 바이 케이스로 알아 본다.

글: 김상헌, 박지용, 이효범 (고려대학교 리눅스 동아리 KULS)


서버의 보안성 검사

리눅스 서버의 보안성을 위해서는 미리 제공되는 네트워크 툴들로 보안성을 검사하는 것이 필요하다. nmap, netstat나 iptable 같은 것들을 이용하면 간단하게 기본적인 보안 상태를 체크하거나 조작할 수 있기 때문에 유용하다.

nmap을 이용한 포트 스캔

nnamp은 해킬 툴로도 널리 알려져 있지만 보안을 위해 사용될 수도 있다. nmap은 여러 스캔 기능들을 제공하는데 이를 이용해 역으로 서버의 보안성을 체크해 불 수 있다. 다음과 같은 명령어는 서버상에 어떤 포트가 열려 있는지를 쉽게 보여 주고 있다:

 nmap host -p min_port-max_port

<그림 1>과 같은 결과를 볼 수 있는데 쓸모없는 포트가 많이 열려 있는 것을 볼 수 있다. "/etc/inetd.conf"나 "/etc/rc.d" 등의 밑에서 쓸모없는 listening port를 제거해 주면 된다.

netstat로 네트워크 상황 점검하기

netstat로 네트워크 커넥션과 프로토콜에 대한 정보를 종합적으로 표시하는 툴이다. netstat로 알 수 있는 정보들에는 네트워크 인터페이스 상황, 라우팅 테이블 상황, 프로토콜 통계 정보 표시 등이 있다. 먼저 네트워크 인터페이스의 상황을 알아보기 위해서는 "netstat -i"의 명령어가 사용된다. 그 결과는 <그림 2>와 같다.

그림 2. netstat -i 명령을 통해 알아 본 네트워크 인터페이스 상황

라우팅 테이블을 때때로 패킷 스니핑 공격의 시발점이 되므로 라우팅 테이블의 적절한 상태를 체크하는 것이 중요하다. 라우팅 테이블의 상태는 "netstat -r"로 볼 수 있다. netstat -r 명령을 내리면 <그림 3>과 같은 결과가 출력된다.

그림 3. "netstat -r" 명령을 통해 알아 본 라우팅 테이블 상태 정보

프로토콜별로 통계 정보를 표시할 수도 있다. "-s" 옵션을 지정하면 <그림 4>와 같은 결과를 볼 수 있다.

그림 4. "nestat -s" 명령으로 알아 본 프로토콜별 통계 정보

또한 현재 열려 있는 포트 상태도 불 수 있다. 이것은 부적절한 스포트웨어(트로이 목마) 등의 설치를 파악하는데 도움이 되는 정보를 제공할 수 있다. "netstat -a"라 입력하면 <그림 5>와 같은 화면을 볼 수 있는데 stat는 현재 포트의 상태를 나타낸다.

그림 5. "nstat -a" 명령을 통해 알아 본 포트 상태

상태

의미

STABLISHED

소켓은 확립한 접속 상태에 있다(TCP 3웨이 핸드새이크가 이루어 지고 데이터를 전송 중이다).

SYN_SENT

소켓은 접속을 확립하려고 시도한다(SYN_SENT stat는 주로 클라이언트가 서버에게 연결을 요청하기 위해 SYN을 보내고 ACK를 기다리는 상황을 말한다).

SYN_REC

접속은 초기화 중이다(SYN이 보내지면 서버는 ack과 syn을 리턴한다. 그리고 클라이언트 측에서 다시 ack를 보낼 때까지 기다린다).

LISTEN

소켓은 접속 대기 상태이다.

TIME_WAIT

주로 서버측에서 close()를 호출해 연결을 종료한 경우이다.

CLOSE_WAIT

서버 입장에서는 passive close 상태로 주로 연결 중단을 요청받은 경우에 해당된다.

CLOSE

모든 접속이 종료된 상태이다.

표 1. 포트 상태(STAT)별 의미

네트워크 상태에 대해 이해하는 것은 지금 서버가 어떤 상황에 놓여 있는냐를 파악하는데 중요하다. 예를 들면, ps aux나 who로 부적절한 공격 시도에 대해 검출했다 하더라도 지금 현재 네트워크가 어떤 작업을 하는 상태인지 모른다면 관리에 많은 장애를 초래할 것이다.

iptables로 패킷 흐름 제어하기

iptable은 커널 2.4부터 ipchain을 대체하고 있다. iptable은 직집 패킷에 대한 룰을 지정함으로써 우리가 커널에게 패킷 흐름을 제어하도록 할 수 있다. 일반적으로 iptable은 <그림 6>과 같은 패킷 흐름에 관한 모델을 사용한다.

그림 6. 필터모델

iptable은 여러 가지 테이블을 갖는데 위 테이블은 필터방식이라 한다. iptable의 구성은 <표 2>와 같다. 가장 큰 개념으로 테이블이 있으며 테이블마다 각가의 체인들이 있고 그 체인들에 적절한 룰을 설정함으로써 패킷의 흐름을 제어할 수 있다.

테이블

체인

Filter

input, forward, output

Nat

prerouting, output. postrouting

Mangle

prerouting, output, input, forward, postrouting

표 2. iptable의 테이블 구성

또한 <표 3>과 같은 옵션을 사용해 룰을 지정할 수 있다.

옵션

의미

-p

프로토콜을 지정한다(icmp, tcp, udp 등).

-s

패킷의 소스를 지정한다.

-d

패킷의 목적지를 지정한다.

-i

들어오는 패킷을 지정한다(input, forward, prerouting).

-o

나가는 패킷을 지정한다(output, postrouting).

-j

룰에 맞는 패킷에 대해 어떤 정책을 취할 것인지 결정한다 (DROP, REJEST, ACCEPT).

표 3. iptable의 옵션과 의미

다음과 같은 예를 들면 설명하면, 송신지가 local인 icmp 패킷을 모두 드롭(DROP)시키는 룰을 input chain에 설정한다:

 iptables -A input -s 127.0.0.1 -p icmp -j DROP

일정기간 패스워드를 변경하지 않은 사용자에 대해 메시지 발송하기

사용자들이 개개인의 패스워드를 자신만 알 수 있도록 설정해 놓지만, 보안을 위해 주기적으로 패스워드를 교체해 주는 것이 좋다. 그러나 이를 계속 기억하면서 암호를 변경해야 된다는 것을 상기하는 것은 어렵다. 그러므로 서버 입장에서 오래 동안 패스워드를 변경하지 않는 사용자에게 경고 메시지를 발송한다면, 좀더 효과적인 패스워드 관리를 할 수 있을 것이다. 다음과 같은 셀 스크립트를 작성해 cron으로 설정해 놓는다면, 일주일 동안 패스워드를 변경하지 않은 사용자가 로그인했을 때 경고 메시지를 보내게 된다.

coroy's password is not updated for a 7 Days

메일 설정 테크닉

최근 MS 블래스터 웜 등의 윈도우 웜으로 윈도우의 보안 신뢰성이 약해짐에 따라 자연히 서버용 운영체제로 주목받고 있는 리눅스가 서버 시장에서 대안으로 떠오르고 있다. 메일, ftp, 웹 등 리눅스는 여러 방면에서 서버 시장의 준비된 대표 주자이다. 그러나 리눅스 또한 보안에 있어 완벽하다고는 볼 수 없다. 여전히 악의적인 크래커나 스크립트 키디(기존의 코드를 짜집기해 악성 프로그램을 만드는 사람)들이 잘못된 설정으로 인한 보안 결정을 노리고 있는 것도 사실이다.

특히, 센드메일 같은 경우는 복잡한 설정으로 인해 설정을 방치하여 SMTP 서버가 스팸용 릴레이(relay) 서버로 악용되는 경우도 많다. 이러한 설정상의 문제는 SMTP 서버와 같이 초기 설정에 대한 방치로부터 일어나게 된다. 그렇다면 초기 설정을 그대로 방치함에 따른 보안상 위협과 어떤 해결책이 있는 지 알아 본다.

센드메일 버전 정보 은폐하기

통칭해 "메일 서비스"라고 불리는 POP과 SMTP는 각각 메일을 받는 역할과 보내는 역할을 하는 두 개의 서비스이다. 이 중 널리 사용되는 SMTP 서버인 센드메일의 경우 설정이 매우 복잡해 설정 자체를 컴파일하는 매크로까지 패키지에 포함되어 있다. 센드메일은 버그 트랙을 찾아보면 수많은 버전별 버그들의 목록을 볼 수 있고 버전별 익스플로이트도 많이 공개되어 있으므로 센드메일의 버전 정보를 노출하는 것만으로도 공격에 대해 상당한 위협이 될 수 있다.

센드메일을 텔넷으로 접속하면(telnet targetserver:25) <그림 9>와 같은 화면을 볼 수 있다.

그림 9. 센드메일을 텔넷으로 접속하면 디폴트로 버전 정보가 노출된다.

이러한 메시지를 센드메일의 배너라 부르는데 디폴트 설정은 위와 같이 센드메일의 버전 정보를 노출하도록 설정되어 있다. 다음과 같이 설정하면 "$v"에 의해 버전 정보를 노출되므로 다음과 같이 설정을 변경한다:

 smtpGreetingMessage = $j Sendmail$v/$z ; $b

                  |
                  V
 smtpGreetingMessage = $j arondight's smtp server ;$b

그러면 <그림 10>과 같은 메시지가 나타나게 되어 자신의 센드메일 버전 정보를 은폐할 수 있다.

그림 10. 설정을 변경해 센드메일 버전 정보를 은폐할 수 있다.

메일 릴레이를 이용한 스팸 공격

다음은 텔넷으로 SMTP에 접속해 직접 메일을 보내는 과정이다. 텔넷 상에서 위와 같은 명령을 직접 입력해 명령을 수행할 수도 있다.

그림 12. 텔넷으로 SMTP에 접속해 직접 메일을 보내는 과정

이와 같이 SMTP는 자신으로부터 뿐만 아니라 메일을 경유하여 발송할 수 있도록 도와주는데 이것을 메일 릴레이(mail Relay) 기능이라고 한다.

메일 릴레이을 이용하면 발송지는 릴레이를 해 준 SMTP 서버가 되는데 이를 악용해 악성 스펨을 발송하는 경우가 적지 않다. 그래서 악성 스패머의 SMTP로 악용되는 경우는 잘못하면 해당 서버의 관리자가 스패머로 오인받게 되는 상황도 발생한다. 이를 막기 위해서는 합법적인 즉, 신뢰관계가 확실한 호스트에게만 릴레이를 허가해 주어야 한다. "/etc/access"를 보면 다음과 같은 설정이 있다:

 user1.host.net RELAY

 user2.host.net RELAY

 spam.host.net REJECT

위 설정은 user1과 user2에서만 릴레이를 허용하고 스팸 서버에 대해서는 거부 메시지와 함께 메일을 반송하게 한다. 이와 같이 하면 user1과 user2는 SMTP를 사용해 메일을 보낼 수 있게 된다. 그러나 이 같은 경우는 합법적인 권한을 가진 시스템 사용자의 계정과는 상관없이 SMTP 사용 여부를 결정하고 또한 스패머의 목록을 전부 등록할 수 없으므로 비효율적이다. 이런 점에 있어 보안 레이어(Security Layer)에 의한 방법은 스팸에 대한 또 다른 해결책이 될 수도 있다.

SASL(Simple Authentification and Security Layer)는 센드메일 8.11부터 지원되는데 SASL을 이용하기 위해서는 send-mail.cf 파일에 다음 두 줄을 추가해애 한다:

 C{TrustAuthMech}DIGEST-MD5 CRAM-MD5 LOGIN

 AuthMechanisms=LOGIN GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5

SASL이 설정된 경우 접속시 <그림 13>과 같은 과정을 볼 수 있다.

그림 13. SASL이 설치된 경우 접속시 나타나는 과정

"AUTH CRAM-MD5 PLAIN LOGIN" 부분이 나오면 SMTP 서버는 인증이 허용된 사용자에 한해서만 릴레이를 해 주게 된다.

데이터베이스 운영 테크닉

데이터베이스를 운영하다 보면, 파일이 깨져 데이터베이스에 접속할 수 없거나 운영하는 게시판에 다음과 같은 에러 메시지가 뜨면서 게시물을 볼 수 없는 경우가 있다. MySQL 서버가 불의의 사고로 비정상적으로 종료되거나 쓰기 작업을 제대로 끝내지 못하면 이러한 증상이 발생할 수 있다:

 ERROR 1016: Can't open file: 'XXXX.MYD'. (errno: 145)

이러한 사고를 대처하기 위해 가장 좋은 방법은 미연에 백업을 수시로 해 두고 데이터베이스 에러 체크를 통해 깨진 파일을 빠르게 복구해 두는 것이다. 미리 백업해 놓으면 깨진 파일들을 날려도 백업 파일로 복구할 수 있지만, 예상하지 못한 사고는 항상 발생하는 법. 이럴 경우 깨진 파일을 다시 복구하는 방법에 대해 알아 보자. 해당 데이터베이스로는 리눅스에서 많이 사용되는 MySQL을 토대로 한다.

MyISAM 테이블(".MYI", ".MYD")을 체크하거나 복구하기 위해서는 myisamchk 명령어를 이용해야 하고 ISAM 테이블(".ISM", ".ISD")에 같은 일을 하려면 isamchk 명령어를 이용해야 한다.

MyISAM에 대해

MyISAM는 현재 MySQL에서 보편적으로 쓰이는 테이블 형식이다. 인덱스 파일은 ".MYI"에 저장되고 데이터 정보는 ".MYD"에 저장 된다. ISAM 데이블 형식은 현재는 잘 쓰이지 않고 앞으로 MySQL에서 사라질 것이다. ISAM 테이블을 다음과 같이 MyISAM으로 변환할 수 있다.

ALTER TABLE tbl_name TYPE = MyISAM;

ISAM 테이블은 인덱스가 ".ISM"에 저장되고 데이터는 ".ISD"에 저장된다. 이 밖에 Merge, Heap, InnoDB 등의 다른 테이블이 있고 이전에는 지원하지 않던 트랜젝션은 BDB와 InnoDB 테이블이 지원한다. 또한 InnoDB는 외래 키(Foreign Key)를 지원한다.

복구 방법

먼저 루트 권한으로 로그인하고 복구 작업을 하기 전에 다음과 같이 명령하여 MySQL 데몬을 죽인다:

 mysqladmin -uroot -p shutdown

해당 MySQL 데이터베이스 폴더로 이동해 문제가 있는지 일단 테이블을 체크한다:

 kuls:/var/.../test# myisamchk weather.MYI

문제가 있는 테이블은 복구 명령어를 사용해 복구한다:

 kuls:/var/.../test# myisamchk -r weather.MYI

복구를 성공적으로 마쳤다면 MySQL 데몬을 재실행한다:

 kuls: safe_mysql&

그림 14. MySQL 데몬을 재실행하는 화면

복구하기 전에 만약의 사고를 대비해 데이터베이스 파일을 모두 다른 백업 폴더로 복사하고 복구 명령을 실행하기 바란다. 에러 검사에서 에러가 발견되지 않았지만 이상이 있을 경우 "-e(--extend-check)" 옵션을 주어 다시 체크해 본다. -e 옵션을 주면 시간은 더 걸리지만 자세히 검사하게 되므로 미처 발견되지 못한 에러를 발견할 수 있다.

myisamchk, isamchk과는 별도로 mysqlcheck이라는 명령어도 있다. 이 명령어는 MyISAM 테이블에서만 사용할 수 있고 myisamchk와의 차이점으로는 MySQL 서버를 종료하지 않고도 에러 체크와 복구 작업을 할 수 있다는 점이다. 확장 검사 옵션은 "-e(--extend)"이고 복구 옵션은 "-r(--repair)"이다.

옵션

설명

-r(--recover)

복구를 할 때 기본으로 주어야 할 옵션

-q(--quick)

속도는 빠르지만, 완벽한 복구가 안될 수도 있다.

-f(--force)

데이터 손실이 일어나도 강제로 복구.

-B(--backup)

변경하는 파일을 "filename-time.BAK"명으로 백업시키고 복구하는 명령.

표 4. myisamchk의 복구 옵션

MySQL DB 백업 및 복구 방법

간단하게 데이터베이스를 백업하고 복구하는 방법을 살펴 보겠다. 먼저 백업을 위한 명령은 다음과 같다:

 $ mysqldump -u계정 -p 백업할_DB_명 > 백업_파일명

 예) mysqldump -ucorory -p corory > corory_db

위와 같이 명령하고 이어 묻는 패스워드를 입력하면 원하는 DB을 백업할 수 있다.

마찬가지로 일단 mysql -u계정 -p 명령으로 MySQL에 접속하고 다음과 같이 명령할 수 있는데, 여기에서 database 대신 "--all-databases"를 입력하면 전체 DB가 백업된다:

 $ mysqldump -옵션 database 백업할_DB명 > 백업_파일명

옵션

설명

-q(--quick)

mysql_use_result()를 사용해 덤프(dump)를 신속하게 한다.

--add-drop-table

각 create statement 앞에 드롭(drop) 테이블 절을 추가한다.

--add-locks

MySQL에 삽입하는 속도를 빠르게 하기 위해 덤프하기 전에 LOCK 테이블을 추가하고 덤프한 다음 UNLOCK 테이블을 추가한다.

-e(--extended-insert)

다중 insert 구문을 사용해 보다 빠르게 삽입할 수 있도록 한다.

--opt

-q, --add-drop-table, --add-locks, -e --lock-tables을 모두 사용한다.

표 5. mysqldump의 옵션

보통 "--opt"을 옵션으로 주어 덤프하면 다른 필요한 옵션들이 자동 첨가되므로 사용를 권장한다.

백업과 마찬가지로 다음과 같이 명령하면 복구도 간단히 할 수 있다:

 $ mysql -u계정 -p 복구할_DB_명 < 백업_파일명

NIS/NFS 권한 강화 테크닉

NIS 권한 강화하기

NIS(Network Information System)는 한 시스템 상의 계정 정보를 여러 호스트에서 공유하기 위해 사용되는 패키지이다. NIS는 서버/클라이언트 구조로서 rpc를 사용한다. rpc는 한 네트워크 상에 있는 프로그램이 다른 호스트에 정보를 요청하는데 사용되는 프로토콜로 마치 원격에 있는 특정 프로시저를 마치 자신에게 있는 것처럼 사용할 수 있다.

NIS는 사용하면 각 시스템 상에 호스트 정보를 개별적으로 변경해 줄 필요없이 NIS 정보를 제공하는 서버에서 한 번만 갱신해 주면 전체적으로 반영되는 장점이 있다. 하지만 NIS는 많이 사용되는 패키지 중 하나지만 처음부터 안전을 염두해 두고 만든 것이 아니다. 만약 누군가가 여러분의 NIS 도메인을 알 수 있다면 그들은 고스란히 여러분의 새도(shadow) 파일까지 훔쳐 볼 수 있다. 이 파일은 존 더 리퍼 같은 크래킹 프로그램을 사용하면 단순한 패턴의 암호인 경우는 30분이 채 못가서 깨지는 경우도 있다. NIS 패키지는 기본적으로 "yptools"라는 것을 갖고 있는데 이 중 ypcat을 이용하면 "ypcat shadow.byname"과 같은 명령어로 쉽게 새도 파일을 훔쳐 볼 수가 있다.

따라서 로컬 사용자에 대한 ypcat의 권한을 chmod o-x로 해두는 것이 좋다. 또한 NIS 도메인을 nisdomain 등의 초기 설정으로 놓아 두는 것은 보안상 심각한 결점으로 남는다는 사실을 명심하기 바란다.

NFS 루트 권한 제한하기

NFS(Network File System)는 NIS와 마찬가지로 널리 사용되는 rpc 관련 패키지이다. NIS와 마찬가지로 NFS 또한 관리를 소홀히 할 경우는 많은 문제점을 야기시킬 수 있다. NFS 같은 경우 처음 패키지를 설치할 경우 모든 호스트에 대해 nfsmount(이것을 "export"라 한다)를 허용할 수 있도록 "/etc/exports" 설정파일이 비어 있다. 이와 같은 경우 nfsmount된 디렉토리는 다른 호스트에게 루트 권한을 허용하게 되는데 이 경우 쉽사리 피해를 입기 쉽다.

따라서 "/etc/exports"에는 꼭 필요한 디렉토리에 대한 접근만을 허가하면 반드시 root_squash를 걸어 루트 권한을 적용하지 못하도록 하는 것이 중요하다.

"--NFS"로 X윈도우 사용하기

일반적인 경우 NFS로 파일 공유시 X윈도우를 띄우면 <그림 15>와 같은 에러 메시지가 나타나다.

그림 15. NFS로 파일 공유시 X윈도우를 띄우면 나타나는 에러 메시지

이것은 NFS-user-server가 lockd를 제대로 작동시킬 수 없기 때문인데 이를 해결하기 위해서는 커널 컴파일시 "fileSystem -> network file system -> nfs" 부분에 체크를 해주고 "nfs-kernel-server"를 설치해야 한다.

방화벽에 뚫려 있는 포트 찾기

많은 기업 및 공공 기관에서 보안을 위해 방화벽을 설정해 놓고 있다. 방화벽 내에 필요한 프트만 열어 놓고 나머지는 모두 닫아 놓는데, FTP 등의 서비스를 위해 별도의 포트가 필요한 경우가 있다. 그러한 경우 방화벽에서 막아 놓지 않은 포트를 찾는 방법을 알아 보자.

  • 방화벽 외부에 있는 컴퓨터와 그 IP 주소
  • 포트 스캐너(여기서는 pnscan을 사용한다)
  • 방화벽 내부에 있는 컴퓨터
  • tcpdump

그림 16. 방화벽이 설치된 회사 시스템의 구조

편의상 방화벽 외부에 있는 컴퓨터를 A, 내부에 있는 컴퓨터를 B라 하겠다. A의 IP 주소가 1.2.3.4인 것을 B 컴퓨터는 알고 있다.

B 컴퓨터는 A가 주는 패킷 중 방화벽을 통과한 것만 받을 수 있으므로 B에 도착한 모든 A의 패킷을 잡아 포트를 검사하면 방화벽에 뚫려 있는 포트를 알 수 있게 된다.

tcpdump -i eth0 src 1.2.3.4

A 컴퓨터는 포트 스캐너를 사용해 B의 원하는 포트를 포트 스캔한다.

pnscan 4.3.2.1 1:1024

포트 스캐너로 인해 B의 1~1024까지 포트에 각각 한번씩 패킷이 도착함으로 B 컴퓨터에서는 외부 서비스를 위해 사용할 포트를 손쉬게 알 수 있다.


<출처: http://www.just4fun.pe.kr/wiki/X_b8_ae_b4_aa_bd_ba_bc_ad_b9_f6_b0... >

,