RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
'2006/09'에 해당되는 글 206
출처 블로그 > 불행한 바보
원본 http://blog.naver.com/deepinheart/20000824189
원격 로그 서버 만들기 완벽 가이드

좀 오래된 문서이기는 하나 괜찮은 문서 같아서 올려 봅니다.
좀 오랫된 문서라서 설치 설명에 사용되는 명령어나 패키지들의 버전이 낮지만 설정하는데에는 크게 문제가 되지 않을 겁니다.
이문서를 토대로 혹 최신 버전에서 설치를 하시는 분들은 성공기/체험기나 제가 메일을 주시면 해당 성공기를 올려 드리도록 하겠습니다.

원격 로그 서버 만들기 완벽 가이드
(Complete Reference Guide to Creating a Remote Log Server)

번역 : 이국현 (errai@hitel.net)
영문원문링크:http://www.linuxsecurity.com/feature_stories/remote_logserver-1.html
한글원문링크:http://www.linuxlab.co.kr/docs/01-01-1.htm

이 문서는 Eric Hines에 의해 쓰여진 것으로, 원격 로그서버를 만들기 위한 자세한 설명과 설정방법등을 다룰 것이다.

소개(INTRODUCTOIN)
우선 본 문서에서 언급하고 있는 유틸리티들의 README 화일들에 대해서 열심히 공부해 볼 것을 권한다. 그리고 문서를 읽다 보면 나오는 단어 중 SERVER는 원격 머신(CLIENTS)들로부터 log를 받도록 설정되어진 컴퓨터이고, CLIENT는 원격 로그 서버(REMOTE LOG SERVER)에게 log를 보내도록 설정 되어진 컴퓨터임을 나타낸다.

A. 원격 로그 서버란 무엇인가?(WHAT IS A REMOTE LOG SERVER)
원격 로그서버는 다른 시스템들의 log들을 저장할 하드 드라이브 공간을 제공하도록 미리 설정되어진 시스템일 뿐 그 이상도 이하도 아니다.
이 시스템은 완벽한 보안으로 차단되어 있어야만 한다. 모든 RPC 데몬들이나 다른 기타 서비스들도 암호화되지 않고서는 절대 접근이 허락되지 않는다. 데이타들은 오직 UDP/Port 514 번을 통해서만 전송이 허락된다.
로그서버에 대한 자세한 설정 및 설치등에 대해서 하나씩 하나씩 접근해 보기로 하자.
([역자주] : UDP port 514번은 syslog가 사용하고 있다)

B. SYSLOGD
syslogd의 재 컴파일(Recompiling syslogd)

여러분 컴퓨터에서 원격으로 로그를 남기는 능력을 작동시키기 위해서 첫번째로 할 일은 syslogd의 재 컴파일이다. 이것은 보안상의 이유로써 syslog.conf 화일이 아닌 다른 화일을 읽도록 하기 위함이다. 자세한 내용은 나중에 다루겠다.

NOTES : 이 아이디어는 Lance Spitzner가 쓴 "To Build a Honeypot"이란 whitepaper를 통해 얻게 되었다. 보안 공동체를 위해 공헌을 한 Lance에게 감사의 말을 전한다.
이 뛰어난 아이디어는 침입자가 이 시스템에는 원격 로그를 남기는 기능이 없다고 착각하게 만드는 것이다. 이전에 사용한 /etc/syslog.conf 화일을 남겨놓음으로써 예기치 못한 크래커를 속이는데 도움을 줄 것이다.

STEP 1 : 새로운 버젼으로 컴파일하기 (COMPILING OUR NEW VERSION)
우선 여러분의 운영체제에는 기본적으로 syslogd가 설치되어 있을 것이고 소스코드는 함께 들어있지 않을 것이다. 여러분은 우선 RedHat 이나 Joey's FTP site(syslogd의 개발자)를 통해 소스 코드를 다운로드 받아야 한다. 여러분의 배포판에서 소스 코드를 제공하지 않는다면 오픈 소스 정책에 위반되는 것이다. 그러므로 아래의 링크에서 소스를 다운받길 원하지 않는다면 여러분의 OS vender에서 소스코드를 얻기 바란다. 

SITE 1:ftp://ftp.infodrom.north.de/pub/people/joey/sysklogd/
혹은
SITE 2:ftp://ftp.sourceforge.net/pub/mirrors/redhat/redhat/redhat-6.2/SRPMS/SRPMS/sysklogd-1.3.31-16.src.rpm

만약 RedHat계열의 사용자일 때 rpm-iv-vsysklogd-1.3.31-16.src.rpm 라고 실행한다면 /usr/src/redhat/SOURCES/sysklogd-1.3-31 에 인스톨 될 것이다.

STEP 2 : 기본 설정 화일 위치 변경하기(CHANGING THE DEFAULT CONFIG FILE LOCATION)
여기는 재미있는 부분이다. 이것은 침입자가 여러분의 log화일이 local에 저장된다고 생각하게끔 속인다. 우리는 syslogd가 다른 설정 화일을 읽도록 재컴파일을 할 것이다. 기본으로 설정되어있는 옛 화일은 침입자가 원격 로그가 기록되는지 cat 등을 실행해서 /etc/syslog.conf를 들여다 보았을 때 속일 수 있을 것이다. 재컴파일해서 새로운 바이너리를 얻더라도 옛 설정화일은 남겨놓도록 하자.

기본 설정인 /etc/syslog.conf 를 고친다.

[ehines@myhost sysklogd-1.3-31]$ cd /usr/src/redhat/SOURCES/sysklogd-1.3-31
[ehines@myhost sysklogd-1.3-31]$ vi syslogd.c

syslog.conf 부분을 찾는다.
#define _PATH_LOGCONF   "/etc/syslog.conf"

이제 여러분이 원하는데로 설정 값을 고치면 된다. 여러분은 /etc/.sys/CORE.conf 같이 독창적으로 설정하기 바란다.
새로운 syslogd 바이너리가 생겼다면 이전 것 위에 덮어쓴다.
(대부분은 /sbin/syslogd)이 부분을 실행하기 전에 옛날 버젼은 백업 해두자. 관리자라면 이미 알고 있겠지만, 그렇죠?  :)

NOTES : 간단하게 예전 syslogd를 가지고 (-f 설정화일)형식으로 실행하지 않은 이유는, 침입자가 ps 등으로 프로세스 리스트를 볼 경우 뒤에 붙은 옵션들이 다 보여서 설정화일을 무엇으로 바꾸었는지 다 알게 될 것이다.
그러므로 이와 같은 형식으로 하는게 좋다. 필자는 /etc/syslog.conf 파일을 교묘하게 놔두고, 재컴파일을 통해 설정화일을 바꾸는 것을 추천한다.
그리고 위치만 변경하고 이름은 그대로 두는 것은 위험하다.
간단하게 find / -name "syslog.conf" 로 찾아낼 수 있다.

STEP 3 : 진짜 syslog 설정화일 고치기(MODIFY THE (REAL) SYSLOG CONFIG FILE)
예를 들어, 다음의 syslog.conf 는 모든 메세지를 원격 호스트로 포워딩 하는 것이다.

# 간단하게 모든 메세지를 원격 호스트로 포워딩.
*.*            @hostname

# 모든 커널 메세지를 원격 호스트로 포워딩.
kern.*         @hostname

# 로컬에도 기록하면서 원격으로도 기록을 남김 (실패할 경우 대비)
kern.crit                    @finlandia
kern.crit                    /dev/console

기타등등 여러분이 원하는데로 모든 로그화일을 설정한다.

C. THE CLIENT ( REMOTE LOG SERVER )
클라이언트 서버(혹은 모든 원격 로그들을 수용하는 컴퓨터)는 원격 로그를 남기기 위해서 syslogd에 -r 스위치를 줘서 실행시켜야 한다.  그리고 /etc/services화일에 syslog 514/udp 가 적혀져 있어야 한다.

D. 원격 로그 서버 차단하기(LOCKING DOWN THE REMOTE LOG SERVER)
모든 로그들을 받아들이는 컴퓨터는 완벽하게 외부와 차단되어 있어야 한다.

1. 모든 서비스 종료시키기 (Turn off(ALL SERVICES))

이 컴퓨터는 오직 로그 서버일 뿐이므로 다른 서비스들을 실행시킬 필요가 없다. 다음과 같이 실행한다.

[root@myhost /etc]# cd /etc
[root@myhost /etc]# vi inetd.conf

1) 모든 INETD 서비스 종료시키기 (TURN OFF ALL INETD SERVICES)

여러분은 이 화일에서 '#' 를 추가시킴으로써 주석으로 처리를 할 것이
다. 아래의 모든 서비스들을 주석처리하기 바란다.

a. echo
b. discard
c. daytime
d. chargen
e. time
f. ftp
g. telnet
h. shell
i. login
j. exec
k. comsat
l. talk
m. ntalk
n. dtalk
o. pop-2
p. pop-3
q. imap
r. uucp
s. tftp
t. bootps
u. finger
v. cfinger
w. systat
x. netstat
y. auth
z. linuxconf
zz. swat

2) 모든 RPC 서비스 종료시키기 (DISABLE ALL RPC SERVICES)

[root@myhost /etc]# cd /etc/rc.d

디렉토리를 살펴보면 대문자 "S"로 시작하는 화일들이 보일 것이다. 이것은 시스템이 부팅할 때 시작되는 서비스들이다. 여러분은 mv 명령어를 이용해서 소문자 s로 바꿔주면 된다. 예를 들어 mv S11portmap s11portmap 이라고 해주면 부트 타임때 portmapper 를 시작하지 않게 된다.

아마도 nfslock, apmd, netfs, identd, autofs, portmap, atd, pcmcia 와 isdn, sendmail, gpm, httpd, vmware, xfs,linuxconf, local 같은 서비스들을 꺼주면 될 것이다. rc0.d 에서부터 rc6.d 까지 다 종료시켜 주어야 한다.

2. 계정 삭제(DISABLE ACCOUNTS)

[root@myhost /etc]# vi /etc/passwd

여러분의 패스워드 화일에서 사용하지 않는 계정을 삭제해야 한다. 필자는 /bin/noshell(http://www.
cerias.purdue.edu/coast/archive/data/categ50.html)라는 툴을 다운받을 것을 제안한다.
이것은 계정을 추가하거나 삭제할 때 관리자에게 유용한 프로그램이다.

3. SSH의 설치 (INSTALL SSH)

telnet을 사용하면 sniffing 당할 위험이 있다. 하지만 우리에겐 GNU 오픈소스 공동체의 산물인 OpenSSH이 있다. 자 이제 OpenSSH를 설치해보자.

1) OPENSSH 다운로드 받기 (DOWNLOADING OPENSSH)

여러분의 웹브라우져로 www.openssh.com에 접속한다. 이문서가 쓰여질 때 최신버젼은 version 2.1.1로 SSH1과 SSH2 프로토콜을 둘 다 지원한다. 소스를 다운받고 다음과 같이 한다.

[root@myhost ]# gzip -d openssh-2.1.1p2.tar.gz
[root@myhost ]# tar -xvf openssh-2.1.1p2.tar

모든 사항을 똑같이 할 수는 없을 것이다. 계속 진행하기 전에 INSTALL 화일을 꼭 읽어보기 바란다. 필자는 여러분 각각 시스템이 요구하는 사항까지 이야기 해 줄 수 없다. 이것은 단지 필자의 인스톨을 여러분이 지켜보는 것 일 뿐이다.
우선 Zlib와 OpenSSL을 인스톨을 해야 한다. 

Zlib: http://www.freesoftware.com/pub/infozip/zlib/
OpenSSL 0.9.5a or greater:
http://www.openssl.org/

RPM버젼의 OpenSSL은
http://violet.ibs.com.au/openssh/files/support

GNUmake가 설치되어 있다면 다음과 같이 하면 설치가 될 것이다.

[root@myhost ]# ./configure && make && make install

만약 PAM을 사용한다면 /etc/pam.d/sshd 과 같은 PAM control file도 필요로 할 것이다. 일반적으로는 conrtib/sshd.pam.generic 에 포함하고 있다. 사용하기 전에 여러분의 시스템에 맞게 편집해야 할 것이다. 만약 레
드햇 리눅스 6.2를 사용한다면 contrib/redhat/sshd.pam 이 더 유용할 것이다.
필자는 configure 할 때 --without-pam으로 PAM 지원을 끄는 것을 좋아한다. 만약 발견된다면 PAM은 자동적으로 스위치가 켜질 것이다.
--without-pam 옵션은 대신에 RSA 인증을 사용할 경우에 사용된다.

[root@myhost ]# tar -xvf zlib.tar
[root@myhost ]# cd zlib-1.1.3
[root@myhost zlib-1.1.3]# ./configure && make && make install

설치도중에러가 발생한다면 미안하지만 README 화일을 읽기 바란다. 필자는 에러가 발생하면 README 화일들에서 error에 관련된 사항을 찾아보곤 한다.

OpenSSL을 인스톨 하기 위해서는 다음과 같은 것이 필요하다.
    *  Perl 5
    *  an ANSI C compiler
    *  a supported Unix operating system

[root@myhost ]# tar -xvf openssl-0.9.5a.tar
[root@myhost ]# ./config && make && make test && make install

이제 OpenSSH를 설치한다.

[root@myhost ]# cd openssh-2.1.1p2
[root@myhost ]# ./configure --without-PAM && make && make install

성공적으로 OpenSSH를 컴파일 했다면 다음과 같은 메세지를 보게 된다.
Key generation complete.
Your identification has been saved in /usr/local/etc/ssh _host_key.
Your public key has been saved in /usr/local/etc/ssh _host_key.pub.
The key fingerprint is:
d5:74:83:d0:3f:c4:b4:d6:c5:39:1d:94:ee:9b:a8:61 root
@soc1.priv.nuasis.com
Generating DSA parameter and key.
Your identification has been saved in /usr/local/etc/ssh
_host_dsa_key.
Your public key has been saved in /usr/local/etc/ssh
_host_dsa_key.pub.
The key fingerprint is:
ed:58:65:b9:8b:fe:05:81:c2:8c:06:c9:cb:ac:bb:e6 root
@soc1.priv.nuasis.com

2) OPENSSH의 설정 (CONFIGURING OPENSSH)

기본적으로 설정되어진 것을 사용하더라도 나중에 변경할 때를 대비해서라도 ssh config화일을 봐두자. 설정화일
은 /usr/local/etc/ssh_config, /usr/local/etc/sshd _config 가 있다.
설치가 끝난 후에는 host key와 DSA key가 생성될 것이다.

여러분은 SSH 배포판의 문서를 참조해서 설정을 하기 바란다.

4. 방화벽 (THE FIREWALL)

패킷 필터링은 여러분의 시스템에 어떤 취약점이 발견되지 전까지는 필요하지 않을 것이다. syslog port(514/udp)를 필터링 하는 이유는 syslog server가 쓰레기 값을 전송했을 때 멈출 수 없기 때문이다. 그러나 더 중요한 것은 udp값이 쉽게 spoof될 수 있게 때문이다.
이것은 적어도 여러분이 여러 대의 컴퓨터에서 모든 로그가 하나의 인터페이스로 들어올 때 여러분이 외부로부터 들어오는 모든 것을 안전하게 필터링 하게 해준다.

아래는 리눅스 머신에서 ipchains를 이용한 쉘 스크립트이다.

#!/bin/sh

PATH=/usr/sbin:/sbin:/bin:/usr/sbin

LOCAL_INTERFACE="192.168.1.1/32"
# put your real IP address
LOCAL_NETWORK="192.168.1.0/24"
# put your  local net IP address/mask here
SSH_PERMITTED="192.168.1.2/32 192.168.2.3/32"
# who allowed to ssh
SYSLOG_PERMITTED="192.168.1.5/32 192.168.5.2/32"
# who allowed to log syslog messages

# deny everything
ipchains -P input DENY
ipchains -P output DENY
ipchains -P forward DENY
ipchains -F

#permit ssh
for ipaddr in $SSH_PERMITTED;
do
ipchains -A input -p tcp -s $ipaddr -d 0/0 22 -i $LOCAL_INTERFACE -j
ACCEPT
done

# permit outgoing tcp
ipchains -A output -p tcp -i $LOCAL_INTERFACE -j ACCEPT
ipchains -A input -p tcp ! -y -i $LOCAL_INTERFACE -j ACCEPT

# permit syslog
for ipaddr in $SYSLOG_PERMITTED;
do
ipchains -A input -p udp -s $ipaddr -d $LOCAL_INTERFACE 514 -i \
$LOCAL_INTERFACE -j ACCEPT
done
# if you would like to log all the other connection
#attempts, uncommend these...
#ipchains -A input -p tcp -i $LOCAL_INTERFACE -l -j DENY
#ipchains -A input -p udp -i $LOCAL_INTERFACE -l -j DENY
#ipchains -A input -p icmp -i $LOCAL_INTERFACE -l -j DENY

만약 IP filter 패키지를 이용한다면 대체로 다음과 같을 것이다.
# close everything on local interface
# block in all on le0 from any to any

# pass secureshell
pass in on le0 proto tcp from 192.168.1.2/32 to 192.168.1.1/32 port= 22
pass out on le0 proto tcp from 192.168.1.2/32 to 192.168.1.1/32 port = 22

# or you can replace these two rules with
#pass in on le0 proto tcp from 192.168.1.2/32 to
#192.168.1.1/32 port = 22 keep state
#pass SYSLOG
pass in on le0 proto udp from 192.168.1.2/32 to 192.168.1.1/32 port = 514

5. LOG REPORTING

아무리 좋은 원격 로그 서버를 만들어놔도 여러분이 직접 모니터링 할 수 없으면 무용지물이다. 필자는 다음과 같은 유틸리티를 추천한다.
  *   Logcheck - www.psionic.com
  *   Swatch - www.swatch.org

아래는 간단한 쉘 스크립트(Mr. Bill Pennington)이다. 이것은 매 일/시간/분 로그화일들을 지정된 이름과 장소에 보관한다.

#!/bin/bash
#Simple script to rotate the log files on a daily basis
#Bill Pennington 1/19/2000

#Set the date variable
date=`date +%m-%d-%Y`

#Rename the messages file
mv /var/log/messages /var/log/messages.$date
#HUP the syslog daemon so it writes to a new file
killall -HUP syslogd

#Compress the file
/bin/gzip /var/log/messages.$date
#Rename the secure file
mv /var/log/secure /var/log/secure.$date

#HUP the syslog daemon so it writes to a new file
killall -HUP syslogd

#Compress the file
/bin/gzip /var/log/secure.$date

#Rename mail file
mv /var/log/maillog /var/log/maillog.$date

#HUP the syslog daemon so it writes to a new file
killall -HUP syslogd

#Compress the file
/bin/gzip /var/log/maillog.$date

#Then scp them somewhere

6. 시간 (TIME)

서버는 언제나 정확한 시간과 날짜를 가지고 있어야 한다.  xntpd를 설치한 후에 "ntpdate timeservername"이란 명령을 하루에 적어도 한번정도 실행시켜 줘야 한다.
필자는 하루에 두 번 씩 이 작업을 시킨다. 물론 여러분이 가진 모든 서버에 해야 한다.

7. 다른 SYSLOG 장치 (OTHER SYSLOG DEVICES)

여기에 syslog가 기록하는 것을 설정할 수 있는 CISCO와 같은 다른 장치들이 있다. 여러분의 네트워크와 서버에서 정확한 값을 얻기 위해서는 syslog에서 기록하는 것을 위해 여러분의 모든 장치를 설정해야 한다.

Cisco
모든 Cisco 장치들은 syslog를 지원한다. 아래에 몇 가지 예제가 있지만 직접 여러분의 Cisco 문서를 확인해보기 바란다.

Routers
    In config mode...

    logging <server ip address or name>
    logging facility <facility> defaults to LOCAL7

Pix Firewall
    In config mode... logging host <ip address of syslog server>
logging facility
    <facility> defaults to LOCAL4 logging trap <level> from
    emergencies to debug , be carefull with debug you will get a
ton of traffic!

Switches
    In config mode...

    set logging server enable
    set logging server <ip address of log server>
    set logging session enable
    set logging level all 1 default

Windows NT
여러분은 NT server로 syslog server로 특정작업을 포워딩 시킬 수 있다.
이와 관련된 여러 개의 shareware /freeware  패키지가 있다.
http://www.bhs.com 에서 syslog를 검색해보라.

E. RESOURCES
   * Swatch - http://www.stanford.edu/~atkins/swatch/
   * OpenSSH - http://www.openssh.com
   * LogCheck - http://www.psionic.com/abacus/logcheck/
   * xntp and list of public NTP servers -
http://www.eecis.udel.edu/~ntp/
   * Cisco - http://www.cisco.com
   * Windows NT software - http://www.bhs.com
   * Robert Graham's sniffing FAQ (hints to build `receive-only
device'
      http://www.robertgraham.com/pubs/sniffing-faq.html
   * IP Filter - TCP/IP filtering package:
http://coombs.anu.edu.au/~avalon/

F. 역자 주

개인적으로 판단해서 꼭 필요하지 않다고 하는 내용은 삭제 또는 변경하였습니다. 필자(Eric Hines)가 언급한 번역되지 않은 내용은 원문을 참조하시기 바랍니다. :)

2006/09/08 23:32 2006/09/08 23:32
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 미소
원본 http://blog.naver.com/osang1997/40007954085
보내고 받는 메일의 양 제한하기

시스템의 제한 설정과  서비스의 안정성은 매우 깊은 연관성을 가지고 있다. 기본적으로 대부분의 서비스는 유저가 사용 가능한 시스템의 자원 제한이 거의 설정되어 있지 않은데, 메일 서비스도 마찬가지이다.
최근에는 메일의 이용율이 높아지고, 메일의 컨텐츠도 전통적인 텍스트 방식에서 음성,이미지등 각종 동영상이 주종을 이루면서 용량도 점점 커지고 있다. 물론 그만큼 하드웨어나 메일 서버의 소프트웨어적인 성능도 향상되고 있지만  용량이 큰 메일을 주고 받는다면 당연히 시스템의 부하가 올라가기 마련이고 이로 인하여 같은 서버내 다른 서비스에까지 영향을 미치게 된다.  따라서 시스탬에서 보내는 메일 서비스(SMTP)나 받는 메일 서비스(POP3)를 제공하고 있다면 용량이 큰 파일을 주고 받는 것을 적절히 제한할 필요가 있다.

sendmail 은 로컬의 메일을 외부로 발송하는 SMTP(보내는 메일서버) 기능도 있
지만 외부에서 서버내 계정으로 전송되는 메일을 받아서 서버에 저장하는 기능
도 있다. 이때 기본적으로는 보내거나 받는 메일의 양에 대한 제한이 전혀 없
어 10메가 이상이 넘는 큰 사이즈의 메일이 송 수신 될 경우 서버에 과부하가
걸릴 수 있으므로 아래와 같이 각각의 설정(보내는 메일과 받는 메일의 양)
을 적절히 제한하여 설정하는 것이 좋다.

>> SMTP 서버에서 보내는 양 제한하는 법.

/etc/mail/sendmail.cf (또는 /etc/sendmail.cf. 이는 sendmail 의 패키징 방
법에 따라 다르다.) 파일에서 다음과 같이 MaxMessageSize 부분의 주석을 제거
하고 제한하고자 하는 적절한 값을 입력한다.

# maximum message size
O MaxMessageSize=5024000

위와 같이 설정하였을 경우 현재의 서버를 보내는 메일 서버로 이용시 첨부 파
일이 5M 이상 초과하거나 웹에서 /usr/sbin/sendmail 을 실행하여 외부로 메일
을 발송하는 메일링 리스트등의 프로그램에서도 메일 발송시 5 메가 이상의 메
일은 보낼 수 없게 된다.
5024000 은 byte 단위이며 설정 변경 후 변경된 내용을 적용하려면 killall –
HUP sendmail 로 sendmail 데몬을 Refresh 하면 된다.

>> 받는 메일 서버에서 받는 양 제한하는 법.

외부에서 서버로 들어오는 메일에 대해서 용량을 제한하고 싶다면 같은 파일
(sendmail.cf) 에서 "Local and Program Mailer specification" 부분을 설정
해 주면 된다.

Mlocal, P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=10/30,
R=20/40, M=5024000, T=DNS/RFC822/X-Unix, A=procmail -Y -a $h -d $u

위와 같이 T=DNS/RFC822/X-Unix  앞부분에 M=5024000 부분을 추가해 주면 된
다.
마찬가지로 5024000는 byte 단위이며 각자의 시스템 환경에 따라 원하는 용량
만큼 적절히 설정해 주면 된다   역시 설정 변경 후 sendmail 을 refresh 하
면 적용이 된다.
위의 경우 서버에서는 5메가 이상의 메일은 수신하지 않으며 5메가 이상의 메
일을
보낸 이는

552 5.2.3 <antihong at tt.co.kr>... Message is too
large; 5024000 bytes max
554 5.0.0 <antihong at tt.co.kr>... Service
unavailable
와 같은 에러 메시지를 회신받게 된다. 

아울러
# maximum number of recipients per SMTP envelope
O MaxRecipientsPerMessage=20

와 같은 부분이 있는데, 이 부분은 한번에 메일 발송 시 동시 발송(참조 발송)
이 가능한 메일 계정의 수를 뜻하는 것으로 SMTP 서비스를 제공한다면 이 설정
을 적용하는 것이 좋다. 기본적으로 이 값에도 제한이 없으므로 먼저 주석을
삭제한 후 적절한 값을 설정해 주면 한번에 동시 발송 가능한 메일의 수도 제
한할 수 있다.
(위의 경우에는 한번에 참조 발송이 가능한 메일 유저를 20명으로 제한)
설정이 끝난 후에는 killall –HUP sendmail 로 sendmail 을 재가동해주면 적
용된다.



메일 용량 쿼터 설정하기

각 유저의 홈페이지 공간에 대한 쿼터 설정방법은 잘 알고 있는데, Sendmail
을 제공시 메일 용량 쿼터에 대한 설정은 잘 모르는 경우가 많이 있다. 매일
쿼터에 대한 설정은 다소 복잡하기는 하지만 설정은 가능하다.  기본적으로
각 유저의 메일은 /var/spool/mail/ 디렉토리에 자신의 계정 소유로 저장이 되
게 되는데 바로 이 특성을 이용하여 쿼터 설정이을 하면 된다.   쿼터는 각 파
일 시스템별로 각각 설정이 가능하므로 각 유저의 홈디렉토리외에 /var 파티션
에도 추가적으로 쿼터를 설정하면 되는 것이다.
쿼터를 설정하는 방법은 일반적인 방법과 동일하다.
먼저 /etc/fstab 파일을  열어 /var 파티션이 별도로 설정되어 있다면 /var 파
티션에,  별도로 없으면 / 파티션에 유저쿼터나 또는 그룹쿼터 설정을 하면 된
다.

/dev/sda1             /home       ext2    defaults,usrquota=/home/.quota
/dev/sda8             /var         ext2   
defaults,usrquota=/var/.mailquota

위에서는 /home 파티션에도 쿼터 설정을 하고 /var 파티션에도 쿼터 설정을
한 것을 볼 수 있다.  이후 touch /home/.quota 및 touch /var/.mailquota 로
사이즈가 0인 파일을 생성한 후  quotacheck –a 를 실행하면 파일 시스템을
스캔하여  디스크 사용량을 체크하여 해당 파일에 정보를 저장한다.

edquota user 를 실행하면

/dev/sda1: blocks in use: 0, limits (soft = 99980, hard = 99980)
       inodes in use: 0, limits (soft = 0, hard = 0)
/dev/sda8: blocks in use: 0, limits (soft = 29980, hard = 29980)
       inodes in use: 0, limits (soft = 0, hard = 0)

위와 같이 쿼터 설정이 나오는데,  여기에서 /dev/sda1 은 /home/ 디렉토리에
대한 쿼터 설정이고, /dev/sda8 은 /var/ 디렉토리에 대한 쿼터 설정이다. 위
설정으로 각각 /home 디렉토리에는 100메가로, 메일 용량은 30메가로 총 130메
가를 할당하여 쿼터를 설정한 것을 알 수 있다. 만약 별도의 /var 파티션이 없
이 / 파티션만 있는 상황에서 100 메가로 쿼터 설정을 했다면 이 용량은 홈페
이지의 용량과 메일 용량을 합쳐서 100메가로 적용이 되므로 주의하기 바란다.

##################### 참고.  Quota 의 설정에 대해
위와 같이 edquota 사용시 관련된 라인이 아래와 같이 보이는 부분이 있다.
이 중
"blocks in use:" 는 유저가 현재 파티션에서 사용중인 총 블럭의 수를 킬로
바이트로,
"inodes in use:" 는 유저가 현재 파티션에서 사용중인 총 파일의 개수를 보
여준다.
이 두개의 "blocks in use:" 와 "inodes in use:" 는 시스템에 의해 자동으
로 설정되고
제어되므로 이 값을 임의로 변경할 필요는 없다.
그리고 quota 설정시 soft 제한(soft = 5000)은 유저가 사용할 수 있는 최대
용량을 뜻하며  (이 예제에서는 약 5M 이다.) hard 제한(hard = 6000)은 유저
가 초과할 수 없는  절대적인 디스크 사용량을 뜻한다.  "hard limit"
는 "grace period" 옵션이 설정되었을 때에만 적용된다.
grace period 는 쿼터가 설정된 유저나 그룹이 soft limit 을 초과한 이후에
도 사용 가능한 시간의 한계이다. 예를 들어서 여러분이 관리하는 시스템
에 "해당 유저의 홈디렉토리를 50MB 로 쿼터 제한하고  초과시 7일간의 유예기
간을 준다"는 정책을 세울 수도 있다. 각자 유예 기간의 설정에 대해서는 나름
대로 적당하다고 생각하는 기간을 정의할 수 있다. grace period 는
edquota –t 로  확인 및 설정할 수 있으며 아래의 경우에는 grace period 가
7일로 설정되어 있는 것을 알 수 있다.

/dev/sd1: block grace period: 7 days, file grace period: 7 days
/dev/sda8: block grace period: 7 days, file grace period: 7 days

그리고 한 유저에게 적용된 쿼터 설정을 다른 유저에게도 그대로 적용하려
면 –p 옵션을 사용하면 되는데, 아래와 같이 실행하면 edquota 프로그램
은 /etc/passwd 에 정의된 유저중 UID 가 499 이후의 모든 유저에 대
해 "user" 의 쿼터 설정을 그대로 복사하게 된다.

edquota -p user `awk -F: '$3 > 499 {print $1}' /etc/passwd`

####################################################################


만약 쿼터가 초과된 계정에 메일을 발송하게 되면 아래와 같은 에러 메시지가
나며 더 이상 메일을 수신하지 못하게 된다.







sendmail 이 정상적으로 작동하는지 여부를 아는 방법

sendmail 이  현재 작동중인지 확인하는 방법은 아래 두 가지 방법으로 가능하
다.

(1) # ps auxw|grep sendmail 로 확인
위와 같이 확인시 
root      0.0  0.0  2684 1460         S    Aug24 sendmail: accepting
connections on port 25

와 같이 sendmail: accepting connections on port 25 로 보이면 정상적으로
작동하는 것이다. 만약 sendmail 이 다운되어 작동하지 않을 때는 sendmail:
rejecting connections 라는 메시지가 보이게 된다.

(2) sendmail 이 반응하는 25번 포트로 접속.

# telnet tt.co.kr 25
Trying 211.47.66.50...
Connected to tt.co.kr.
Escape character is '^]'.
220 www10.tt.co.kr ESMTP Today and Tomorrow (http://tt.co.kr/)

와 같이 sendmail 이 바인딩하는 25번 포트로 telnet 을 접속하면 sendmail
이 반응을 하게 되는데, 위와 같이 접속을 하여 응답이 있을 경우에는 접속을
받아들일 준비가 되어 있는 상태이며 반응하지 않을 때는
Trying  tt.co.kr...
telnet: Unable to connect to remote host: Connection refused
와 같이 접근이 거부되었다는 것을 알 수 있다.


갑자기 sendmail 이 작동하지 않을 때

sendmail 이 작동하지 않는 경우는 주로 2가지이다.

첫번째는, 시스템의 부하율인 Load Average 가 높아져 sendmail 이 작동하지
않는 경우이고 두번째는 sendmail 에서 받는 메일이 저장되는 /var 파티션이
100%가 되었을 경우이다.
Sendmail 은 기본적으로 시스템의 Load Average 수치가 12를 초과하였을 경우
에는 자동으로 작동하지 않게 되는데 이는 sendmail이 서비스 거부 공격등으
로 시스템의 부하가 높아졌을 때 sendmail 로 인하여 시스템이 다운되는 것을
막기 위한 조처이다.
이 값을 수정하려면 sendmail.cf의
# load average at which we refuse connections
O RefuseLA=12
에서 수정한 후 killall –HUP sendmail 로 재실행해 주면 되고, 이 값은 각각
의 시스템에 따라 적절히 조정하면 된다.  만약 현 시스템의 특성상 늘 부하
가 높아 로드가 자주 12를 초과한다면 이 값을 각자의 시스템 환경에 맞게 적
절히 조절하여야 외부에서 오는 메일을 받을 수 있게 된다.(서버에서 25번 포
트로 바인딩하고 있어야 외부에서 오는 메일을 수신할 수 있다.) 그리고 메일
이 저장되는 /var/spool/mail 파티션이 가득 찼을 경우(파티션 100%) 에도
sendmail 이 작동하지 않으므로 파티션이 가득 찼을 경우에는 /var/log/ 등에
서 불필요한 데이터를 삭제하여 /var/spool/mail 이 포함된 파티션이 100% 를
넘지 않도록 하여야 한다. 용량 정리를 하여 파티션이 100%가 넘지 않으면
sendmail 이 자동으로 살아나는 것을 알 수 있다.
또한 시스템의 Load Average 가 8을 넘으면 서버를 통해 메일을 발송해도 메일
을 통해 바로 전송되지 않고 일단 서버의 메일 큐에 저장이 된 후에 발송이 되
게 된다. 이 역시 같은 이유 때문인데 이 수치는 sendmail.cf 의

# load average at which we just queue messages
O QueueLA=8
에서 적절히 설정하면 된다.

참고로 현재 시스템의 Load Average는 w 명령어를 이용하여 확인 가능하다.
w 를 이용시 시스템의 Load Average 는 0.25, 0.40, 0.43  와 같이 보이는데
이는 각각 현재를 기준으로 지난 1분, 5분, 15분간의 평균 시스템 부하율을 나
타낸다.



sendmail 애서 보내는 메일(SMTP) 기능을 차단하고자 할 때

sendmail 에서 Relay 기능을 막아 두었다 하더라도 최근 버전에는 사용자 인증
(SMTP AUTH) 기능이 있어 서버에 계정이 있으면 모든 유저가 메일 서버를 이용
해 SMTP 기능을 이용하여 메일을 발송할 수 있다. 이를 막으려면 최신의
8.11.4 나 8.11.5 와 같이 최신 버전으로 업그레이드 후 /etc/mail/smtpauth
파일에 보내는 메일  기능을 허용할 유저를 입력해 주면 된다. (최근에
8.11.6 이전 버전에 심각한 보안 문제가 확인되었으므로 반드시 8.11.6 버전이
나 8.12 버전으로 업그레이드하여야 한다.)  파일을 생성 후 아무런 유저도 입
력하지 않으면 서버에 계정이 있다 하더라도 어느 누구도 메일을 발송할 수 없
게 된다. 따라서 최신의 8.11.6 버전으로 업그레이드 할 것을 권장한다. 이외
여러 변형된 방법이 존재하는데, ipchains 나 iptables 를 이용해 패킷 필터링
을 하는 방법도 있다.

커널 2.2.X 일 경우
ipchains -A output -p tcp -y -d 0/0 25 -j DENY
커널 2.4.X 일 경우
iptables -A OUTPUT -p tcp --syn --dport 25 -j DROP

위와 같이 설정시 목적지(Target) 포트가 25번 포트로 향하는 초기화(SYN) 패
킷만을 차단하여 메일을 발송할 수 없도록 한다. 물론 초기화(SYN) 패킷에 대
해서만 필터링을 하였으므로 외부에서 오는 메일을 받는 것은 관계 없다.

바이러스 메일 필터링 방법

최근에 Sircam 이나 Nimda 등 일정 주기마다 발생하는 바이러스 메일 때문에
서버 관리자들은 마음 고생이 이만저만이 아니다. Sendmail 에서는 이러한 바
이러스 메일이나 스팸메일에 대해 룰셋(ruleset)을 이용하여 차단하는 기능이
있는데, 이를 사용하는 방법에 대해 알아보도록 하자.
Sendmail 에서는 제목이나 메일러 또는 첨부파일의 화일명등 각종 메일헤더 정
보를 이용하여 필터링을 할 수 있는데, 먼저 발송되는 메일 제목(subject)으
로 필터링을 해 보도록 하자. 아래는 메일 제목에 ILOVEYOU 로 발송하는 멜리
사 바이러스를 차단하는 룰셋을 적용해 본 예이다.

먼저 sendmail.cf 파일을 열어 제일 하단에 아래의 내용을 추가한다.

HSubject: $>Check_Subject
D{WORMmsg}Access Denied - This message may contain a virus.

SCheck_Subject
RILOVEYOU               $#error $: 501 ${WORMmsg}
RRe: ILOVEYOU           $#error $: 501 ${WORMmsg}
RFW: ILOVEYOU           $#error $: 501 ${WORMmsg}

# 주의 :  $#error 앞의 blank는 스페이스가 아니라 반드시 탭으로 띄워주어
야 한다.
Sendmail.cf 의 설정 내용이 다소 어렵고 복잡하기는 한데, 위 설정의 의미를
간단히
살펴보도록 하자.

H -- 위 경우에는 헤더에서 Subject:라는 문자열을 찾아 이 헤더를
Check_Subject로 정의한다.
D -- WORMmsg 라는 매크로를 정의하여 해당 룰셋에 적용되는 제목을 확인시 발
송한
   유저에게 보낼 메시지를 정의한다.
S -- 헤더에서 check_subject로 정의한 부분을 룰셋으로 지정하는 부분이다.
R -- 해당 문자열이 포함된 메일을 발견시 앞에서 정의한 에러 메세지를 첨부
하여
    반송을 시킨다.

위와 같이 룰셋을 적용하였을 경우 "I LOVE YOU" 와 같이 공란이 있을 경우 적
용되지 않으며 "ILOVEYOU from me" 와 같이 특정 단어가 추가시에도 적용되지
않으며 반드시
정확히 일치하여야 한다. 추가적으로 회신시 추가되는 Re: 와 전달(포워딩)시
추가되는 FW: 가 추가된 메일도 거부한다.

다음으로 얼마전 유행했던 Sircam 바이러스 메일을 필터링해 보도록 하자.
Sircam 바이러스의 헤더를 보면 정상적인 메일과는 달리 메일 헤더에
Content-Disposition: Multipart message 와 같은 부분이 추가되어 있으며 이
특징을 이용하여 필터링을 하면 된다.

Sendmail.cf 파일에 아래의 룰셋을 추가하면 된다.

HContent-Disposition: $>check_sircam
D{SIRCAM}"Warning: I  Guess Sircam.worm Virus"
Scheck_sircam
RMultipart message      $#error $: 550 ${SIRCAM}

# 주의 :  $#error 앞의 blank는 스페이스가 아니라 탭으로 띄워주어야 한다.

sendmail.cf의 수정을 끝낸 후 바로 sendmail을 재 시작하지 말고
룰셋이 정상적으로 작동하고 있는지 아래와 같이 테스트를 하는 것이 좋다.

# /usr/lib/sendmail –bt                 # 테스트 모드로 접속
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter 
> check_sircam Multipart message        # Sircam 룰셋 테스트
check_sircam       input: Multipart message
check_sircam     returns: $# error $: 550 553 Warning: I  Guess
Sircam.worm Virus
> ctrl-D                                # 테스트 종료

위와 같이 확인된 후 sendmail을 재시작(killall –HUP sendmail) 하면 바로
적용된다.
아래와 같이 tail –f  /var/log/maillog 로 로그 파일을 지켜보면 아래와 같
이 실제로 Sircam 바이러스가  필터링되고 있음을 확인할 수 있다.

Sep  27 15:09:51 www sendmail[21386]: f8369of21386:
to=<antihong at tt.co.kr>, delay=00:00:01,
pri=241584 Warning: I  Guess
Sircam.worm Virus.

마지막으로 최근에 가장 영향을 많이 주었던 변형된 Nimda Worm 을 필터링하
는 방법에 대해 알아보자. Nimda Worm 은 정상적인 메일 메시지와 달리 헤더에
boundary="====_ABC1234567890DEF_===="       나
boundary="====_ABC123456j7890DEF_===="      라는 부분이 있는데, 이 부분으
로 필터링을 할 수 있다. 즉 메일 헤더에 위와 같은 설정이 되어 있으면 
Nimda Worm 으로 간주하고 필터링 하면 되는 것이다. Sircam 에서와 같은 방법
으로 sendmail.cf 파일의 설정은 아래와 같다.

HContent-Type: $>check_ct

D{NIMDA}"I guess NIMDA.WORM!!!"

Scheck_ct
R$+boundary="====_ABC1234567890DEF_===="       $#error $: 550 ${NIMDA}
R$+boundary="====_ABC123456j7890DEF_===="       $#error $: 550 ${NIMDA}

이외 메일 필터링에 대한 더욱 구체적인 방법에 대해서는 
http://certcc.or.kr/paper/tr2001/tr2001-03/email security by
procmail.html 나
http://quanta.khu.ac.kr/~dacapo/sendmail/rulesets/ 를 참고하기 바란다.
그리고 이외 관련하여 바이러스를 스캔하거나 필터링 할 수 있는 몇몇 프로그
램이 있는데 이에 대해서는 http://www.rav.ro/ , http://www.amavis.org/ ,
http://www.sophos.com/ 등을 참고하기 바란다.


메일이 받아지지 않는 경우

아웃룩 익스프레스에서 “배달” 을 눌러 메일을 수신하려고 할 때 메일이 받
아지지 않는  경우가 있다. 이러한 경우에는 아래와 같이 여러가지 이유가 있
을 수 있으니 아래의 사항에 대해 하나씩 원인을 찾아보기 바란다.
(1) IMAP 패키지가 설치되지 않았을 경우
서버에 배달되어 있는 자신의 계정으로 온 메일을 클라이언트 PC에서 받으려
면 pop3 데몬이 반응하게 된다.  pop3d 는 IMAP 패키지안에 포함되어 있으므
로, IMAP 패키지를 설치하여야 pop3 를 사용할 수 있다. Rpm 으로 설치했다면
rpm –q imap 으로 현재 시스템에 imap 패키지가 설치되어 있는지 확인한다.
또는 /usr/sbin/ipop3d 파일이 있는지 확인해 본다.
(2) Inetd 에 설정되어 있지 않을 경우
pop3d 는 inetd 또는 Xinetd 에서 작동하게 된다.
/etc/inetd.conf 또는 /etc/xinetd.conf 파일을 살펴보아 ipop3 가 주석처리
되어 있거나 pop3 가 disable =  yes 로 되어 있지는 않은지 확인한다.
(3) TCP Wrapper 에 설정되었는지 여부 확인
/etc./hosts.deny 에 pop3d 접근이 차단되지는 않았는지 확인한다.
(4) 계정에 Lock 이 걸리지 않았는지 확인
메일을 받는 과정에서 갑자기 회선이 끊기거나 PC가 다운되는 등 비정상적으
로 종료시 서버의 pop3d 프로세스가 죽지 않고 계속 남아 있는 경우가 있다.
이러한 경우 계정에 “Lock 이 걸렸다” 라고 하며 이러한 경우에는 해당 프로
세스를 찾아 kill 을 하면 된다. 만약 계정에 Lock 이 걸린 상태에서 아웃룩
익스프레스에서 메일을 수신하려고 하면 아래와 같은 에러가 나게 된다.
“메일 서버에 로그온하는 데 문제가 있습니다. 지정한 암호가 거부되었습니
다.
계정: 'temazone.com', 서버: 'tt.co.kr', 프로토콜: POP3, 서버 응답:
'-ERR Can't get lock.  Mailbox in use', 포트: 110, 보안(SSL): 아니오,
서버 오류: 0x800CCC90, 오류 번호: 0x800CCC92”

(5) Pop3 접속이 많은 경우
Pop3d 가 서비스되는 inetd는 기본적으로 60초동안 40회의 접속을 받아들이
도록 (즉, maximum 40회 fork되도록) 설정되어 있다. 따라서 짧은 시간에
pop3d
요구가 많을 경우에는 메일로그에 pop3/tcp server failing (looping) 라는 메
시지가
나면서 pop3d 데몬 자체가 다운되어 버리므로 동시에 처리 가능한 프로세스의
한계
를 적절히 높여주어야 한다.
이를 위해서는 /etc/inetd.conf 를 열어 아래와 같이 수정하면 된다.

이전설정)
pop-3    stream    tcp    nowait    root     /usr/sbin/tcpd    ipop3d

변경 설정)
pop-3    stream    tcp    nowait.200    root    /usr/sbin/tcpd    
ipop3d
(위의 경우 처리 가능한 프로세스를 200회로 늘려주었다.)
이후 killall -HUP inetd 를 하면 된다.

(6) 110 번 포트로 확인
아래와 같이 pop3d 포트인 110번 포트로 직접 접속하여 수작업으로 확인 가능
하다.

# telnet  pop3.tt.co.kr 110           # 110번으로 직접 확인
Trying 210.17.6.5...
Connected to pop3.tt.co.kr.
Escape character is '^]'.
+OK POP3 pop3.tt.co.kr v2001.76 server ready
user abc                              # abc 라는 계정으로 접속
+OK User name accepted, password please
pass xyz                              # abc 의 암호 xyz 입력
+OK Mailbox open, 10 messages
quit                                  # 접속을 끊음.
+OK Sayonara
Connection closed by foreign host.

위의 경우는 정상적인 경우이며 에러가 있을 경우(만약 암호가 다르게 설정되
었을 경우 -ERR Bad login 와 같은 메시지가 나게 된다.) 각각의 경우에 따라
에러 메시지를
각각 확인할 수 있다.

(7) mail –v 로 확인
타 서버에서 mail –v antihong at tt.co.kr 와 같이
메일을 발송하여 정상적으
로 메일이 도착하는지를 확인해 본다. –v 옵션을 이용하여 메일 발송시에는
메일 전송의 경로 및 메일 서버간에 주고받는 메시지를 확인할 수 있으므로 문
제의 원인을 찾는데 도움이 된다.



특정한 곳으로만 메일이 돌아올 때

다른 곳은 문제가 없는데, 해외등 특정한 곳으로만 메일이 전송되지 않고 리턴
되는 경우가 있다. 이러한 경우라면 자신의 메일서버가 mail-abuse.org 의 블
랙 리스트에 등록되어 있지는 않은지 확인해 볼 필요가 있다. 특히 회신된 메
일에 “...refused by blackhole site relays.mail-abuse.org” 와 같은 메시
지가 보인다면 반드시 여부를 확인해 보아야 한다. 적지 않은 메일 서버에서
는 메일 수신시 실시간으로 이 데이터를 참조하므로 mail-abuse.org 에서 스
팸 메일 서버로 등록되면 이 기관에 등록된 도메인으로 메일을 보낼 때 받는
쪽에서는 스팸 메일로 간주하고 수신을 거부하게 된다. 이를 확인하는 방법은
http://mail-abuse.org/cgi-bin/nph-rss 사이트에서
메일 서버의 IP 를 조회
해 보면 된다.  아래는 위 사이트에서 한 IP 에 대해 조회해 본 결과 블랙 리
스트에 등록되어 있는 것을 보여주고 있다. 이러한 경우라면 조회한 메일 서버
의 Relay 가 허용되어 스팸 메일 서버로 사용된 적이 있거나 현재 사용되고 있
다는 뜻이다.  만약 스팸메일 서버로 등록되어 있지 않다면 211.47.65.xxx is
NOT currently on the RSS list 와 같이 보이게 된다. 






자신의 메일 서버를 이 블랙리스트에서 제외하려면 먼저 자신의 메일서버에
Relay 가 허용되어 있는지 확인 후 메일 서버에서 Relay 를 거부 설정한 후 
If you'd like 211.47.65.135 to be removed from our list, please click
here. 를 따라 클릭하여 신청을 하면 된다. 이 링크를 클릭하면 신청폼이 나오
는데, 이 곳에 입력하여 신청을 하면 바로 처리가 된다. Relay 거부 설정을
한 후 신청을 해야 처리가 되므로 반드시 사전에 Relay 거부 설정을 확인하기
바란다. 메일 서버의 Relay 여부를 조회하는 방법에 대해서는 본지 10월호
“철벽 보안을 위한 모니터링 올가이드” 를 참고하기 바란다.


복수 MX 설정시 주의해야 할 점 

DNS 서버에서 설정하는 MX 레코드는 해당 호스트로 수신되는 편지를 다른 호스
트로 라우팅 하도록 한다. 특히 웹서버와 메일 서버를 분리하고자 할 경우 사
용되는데, 원격 호스트에서 아래와 같이 설정된 도메인 tt.co.kr 로 편지를 송
신할 경우에 Sendmail이 어떻게 동작하는지 알아보자.


tt.co.kr.         IN   MX    10     mail1.tt.co.kr.
               IN   MX     20    mail2.tt.co.kr.
               IN   MX     20    mail3.tt.co.kr.

다음은 메일이 수신되는 차례를 보여준다.

(1) Preference 값이 10으로 가장 낮은 mail1 로 먼저 배달을 시도한다.
(2) 만약 mail1.tt.co.kr 이 접근이 불가능하면 mail2 혹은 mail3 으로 배달
을 시도한다.
(3) (2) 에서 시도한 메일서버로도 접근이 되지 않으면 (2)에서 접근 되지 않
은 호스트로
  배달을 시도한다. 즉 mail2 로 전송을 시도했다면 mail3 으로 배달을 시도
한다.
(4) mail2 와 mail3 서버에 접근이 불가능하다면 자체 큐잉 후, 일정 기간동
안 주기적으로      
   1-3의 과정을 반복한다.

흔히 MX 레코드에 대해 잘못 생각하는 것 중 하나는 만약  mail1 이 다운되어
mail2 로 편지가 배달되었을 때, 편지가 mail2 의 메일 박스에 저장 된다고 생
각하는 것이다. 만약  이렇게 된다면 유저 입장에서는 메일 수신시 pop3 서버
를 mail1.tt.co.kr 와 mail2.tt.co.kr 과 같이 여러 개 설정해야 하는 것처럼
보인다. 그러나 일반적으로 mail2.tt.co.kr 이나 mail3.tt.co.kr 처럼
Preference 가 높은(즉 우선도가 낮은) 값을 갖는 메일 서버는 큐잉 서버로 동
작하도록 설정하기 때문에, 결국 메일은 하나의 호스트(mail1)로 모이게 되는
것이다. 위와 같이 mail2와 mail3 서버가 큐잉 메일 서버로 작동하려면 mail1
와 mail2의 sendmail 이 아래와 같이 설정되어야 한다.

(1) 해당 도메인(tt.co.kr)에 대한 인증을 갖지 않아야 한다.
(즉, mail2 나 mail3 메일 서버의 sendmail.cw 또는 local-host-names 파일에
tt.co.kr 이 설정되어 있으면 안 된다.)

(2 )서버는 해당 호스트로의 메일 릴레이(Relay)를 허용하여야 한다.
(즉, /etc/mail/access 에서 아래와 같이 정의되어야 한다.)
mail1.tt.co.kr    relay

인증을 갖지 않아야 한다는 것은 Sendmail의 w 클래스(sendmail.cw(local-
host-names)  혹은 sendmail.cf의 Cw)에 tt.co.kr 도메인이 설정되지 않아야
하는 것을 의미하고, 메일 릴레이란 수신되는 편지의 최종 배달지가 자신이 아
닐 경우, 즉 인증을 갖지 않을 경우 편지를 해당 호스트로 포워딩하는 것을 의
미한다.  최근의 배포판에서는 기본적으로 sendmail이 릴레이를 거부하도록 설
정되어 있으므로 메일 큐잉 서버의 경우는 해당 호스트를 목적지로 하는 메일
에 대해서는 릴레이를 허용하도록 설정하여야 한다는 것을 주의하기 바란다.
mail1 의 다운으로 인해 mail2 로 전달되는 메일은 메일큐에 저장되어 있으면
서, 일정 기간(Sendmail.cf에서 지정된 Timeout.queuereturn=5d 만큼)동안 주
기적(Sendmail 구동시 지정된, 일반적으로 30분 -q30m)으로 mail1 로 배달이
재시도된다.


메일 서버의 버전을 숨기는 법

다른 데몬도 마찬가지이지만 메일 서버 역시 해당 포트로 원격 접속을 해  보
면 메일 서버의 버전 정보등을 확인할 수  있다. 그러나 시스템 관리자 입장에
서 보안상의 문제로 현재 운영중인 메일 서버의 버전등을 숨기거나 속이고 싶
을 때가 있는데. 이러한 경우에는 아래의 방법을 이용하면 된다.

(1) sendmail 의 경우
  sendmail.cf 파일을 보면 아래와 같은 설정이 있다.
# SMTP initial login message (old $e macro)
O SmtpGreetingMessage=$j Sendmail $v/$Z; $b
이 부분을 적절히 삭제하거나 다른 정보로 입력후 sendmail 을 재가동하면 된
다.
필자가 운영하는 메일서버의 경우
O SmtpGreetingMessage=$j Today and Tomorrow(http://tt.co.kr/) 와 같이

정하였고 이때 25번 포트로 접속시 보이는 정보는 아래와 같다.

# telnet tt.co.kr 25
Trying 211.47.66.50...
Connected to tt.co.kr.
Escape character is '^]'.
220 www10.tt.co.kr ESMTP Today and Tomorrow(http://tt.co.kr/)

(2) pop3d 의 경우
pop3d 의 경우 소스에서 직접 수정하여야 하는데, 압축 해제한 디렉토리
의 /src/ipopd 에 보면 ipop3d.c 파일이 있다. 이 파일을 살펴보면 

char *version = "2001.75";   /* server version */
라는 부분이 있는데,  필자가 운영하는 pop3d 의 경우 소스에서
char *version = "xxxxxxxxxx";   /* server version */
와 같이 수정 후 컴파일 하였고 이때 110번 포트로 원격 접속시 보이는 정보
는 아래와 같다.

# telnet tt.co.kr 110
Trying 211.47.66.50...
Connected to tt.co.kr.
Escape character is '^]'.
+OK POP3 www10.tt.co.kr vxxxxxxxxxx server ready

버전외 다른 각종 정보도 수정할 수 있으니 각자 상황에 맞게 적절히 설정하
기 바란다.


sendmail 과 관련된 몇 가지 명령어

>> mail1q
mailq 프로그램의 목적은 큐잉된(/var/spool/mqueue 에 저장된) mail 메시지
의 요약된 정보를 보여준다.  네트워크 다운등 어떤 특정한 이유로 바로 발송
되지 못한 메일은 일차적으로 /var/spool/mqueue 에 큐잉된 상태로 저장된 후
일정 시간마다 발송을 위해 재시도가 되는데,  현재 큐잉된 메일 메시지의 요
약 정보를 보려면 아래와 같이 확인할 수 있다.

# mailq

/var/spool/mqueue/q1 (2 requests)
----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------
------
f7A84oV15068     1446 Fri Aug 10 17:04 nobody
                (Deferred: Connection timed out with kebi.net.)
                                      darling at kebi.net
f775ieF24893   521898 Tue Aug  7 14:44 <shlee at
tt.co.kr
>
                (Deferred: Connection timed out with mail.unitel.net.)
                                      <cf1318 at
unitel.net
>
/var/spool/mqueue/q2 is empty
               /var/spool/mqueue/q3 (1 request)
----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------
------
f775nJF25249   230815 Tue Aug  7 14:49 <shlee at
tt.co.kr
>
                (Deferred: Connection timed out with hanmail.com)
cuwww23 at hanmail.com

위 메시지를 보면 어떠한 이유로 메일이 발송되지 못하고 있는지를 추측할 수
있다.
3 메시지 모두 수신자의 e-mail 주소를 잘못 기입했기 때문인데, 각각
kebi.com 인데, kebi.net 으로 unitel.co.kr 인데, unitel.net 으로 ,
hanmail.net 인데, hanmail.com 으로 도메인 주소를 잘못 기입하여 메일을 발
송하여 서버에서 메일을 발송하지 못하고 큐에 저장되어 있는 것을 확인할 수
있다.
여기에서 주의할 점은 mailq 명령어는 일반 유저로 실행하여 확인이 가능하므
로 퍼미션을 700 등으로 조절하여 일반 유저들은 실행할 수 없도록 하는 것이
좋다.

>> mailstats
mailstats 프로그램은 현재의 메일 송수신과 관련하여 통계를 보여준다.

  * 현재의 메일 통게를 보려면 아래와 같이 확인할 수 있다.

# mailstats
Statistics from Sat Aug 11 04:02:02 2001
M   msgsfr  bytes_from   msgsto    bytes_to  msgsrej msgsdis  Mailer
1        0          0K        3        317K        0       0  *file*
4      690     596691K      824     137070K    68426       0  esmtp
9       63      12212K        0          0K       27       0  local
=============================================================
T      753     608903K      827     137387K    68453       0
C      753                  827                68453

이를 적절히 이용하면 mrtg 를 이용해 일정 시간마다 발송되고 수신되는 메일
의 개수를 통계로 내어 그래프로 볼 수 있다.(본지 10월호, 철벽보안을 위한
모니터링 올가이드 참조)

최근 sendmail 관련 버그에 대해

한동안 문제가 없었던 sendmail 에 최근 들어 몇 가지 보안 문제가 발견되었
다.
이 버그는 매우 치명적인 문제인데, 아직 이를 모르고 그대로 사용중인 유저들
이 많은 것 같다. 각자의 메일 서버에는 해당사항이 없는지 꼭 확인해 보기 바
란다.

첫번째로, 8월말에 발표된 버그는 현재 대부분의 메일 서버 프로그램으로 사용
중인 sendmail 8.11.6 이전 버전에 해당하는 보안버그로서 일반유저가 Local
에서 root 권한을 얻을 수 있는 매우 치명적인 버그인데, 이미 공격 소스가 여
러 사이트에 공개되어 있다.
참고로 이 버그는 8.11.0부터 8.11.5 버전까지만 해당하므로 8.10.x 나 8.9.x
는 해당되지 않는다.  따라서 아래의 사이트를 참고로 sendmail 을 8.11.6 이
나 8.12등 최신버전으로 업그레이드하기 바란다.

8.11.0부터 8.11.5 의 경우 8.11.6 으로 업그레이드하면 되고 8.12.0.Beta 의
경우 8.12.0.Beta19 이상으로 업그레이드하면 된다. 이에 대해서는
http://www.securityfocus.com/bid/3163
http://www.sendmail.org/8.11.html
를 참고하기 바란다.

두번째는, 10월초에 발견된 버그로서  모든 버전에 해당하는 문제인데, 이전에
도 자주 나왔던 문제이다. 바로 shell 접근이 가능한 일반유저가 sendmail
에 -q 옵션을 사용하여 큐에 있는 메시지를 드롭할 수 있는 문제이다. 아래의
설명을 보기 바란다.

[user@net user]$ id
uid=778(user) gid=778(user)
[user@net user]$ mailq
               Mail Queue (1 request)
--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient----------
--
NAA05248       11 Tue Oct  2 13:03 user1
                (Deferred: Connection refused by tt.co.kr.)
                                  test at tt.co.kr

[system@net system]$ /usr/sbin/sendmail -q -h10000
Too many hops 10000 (25 max): from system via localhost, to test
at tt.co.kr

Too many hops 10000 (25 max): from MAILER-DAEMON via localhost, to
postmaster
Too many hops 10000 (25 max): from MAILER-DAEMON via localhost, to
postmaster
MAILER-DAEMON... Saved message in /usr/tmp/dead.letter
[user@net user]$ mailq
Mail queue is empty

위와 같이 hop count 를 크게 설정함으로써 일반 유저가 현재 큐의 내용을 강
제적으로 drop 시킬 수 있다.

세번째는 역시 모든 버전에 해당하는 문제로 일반 유저가 sendmail -q -d0-
xxxx.xxx 와 같이 사용시 (xxx는 디버깅 레벨이다.) 일반 유저가 메일서버의
각종 설정 뿐만 아니라 큐에 저장되어 있는 내용, 메시지 경로나 제목, 메일
소프트웨어등의 정보를 볼 수 있는 문제이다.
두번째,세번째 문제는 sendmail.cf 에서

O PrivacyOptions=authwarnings,novrfy,noexpn,restrictqrun
와 같이 restrictqrun 를 추가함으로써 해결 가능하다.


기타 메일과 관련된 장애가 확인 시

지난달 아파치 웹서버의 장애에 대해 이야기하면서 문제나 장애가 발생시에는
웹서버의 error_log  메시지를 살펴보도록 이야기 했었다.  메일서버도 마찬가
지이다. 메일서버 장애시는 문제의 원인을 찾기 위해 로그 파일을 살펴보는 습
관을 들이는 것이 좋다.
메일 관련 로그는 /var/log/messages 나 /var/log/maillog 파일을 살펴보면 되
며 로그파일을 보면 여기에서 언급하지 않은 문제가 발생했다 하더리도 어렵
지 않게 원인을 찾을 수 있을 것이다.   다시 한번 강조하지만 모든 문제의 원
인과 해결책은 로그에 있다는 것을 명심하기 바란다.
2006/09/08 23:28 2006/09/08 23:28
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 도시의 매연 위 푸른하늘...
원본 http://blog.naver.com/savemyface/120006480613
1. 로케일(Locale)의 의미
세계 여러 나라들은 각자 다른 문화(언어, 날짜, 시간 등)을 갖고 있다. 프로그램의국제화(Internationalization, 줄여서 i18n)는 사용자로 하여금 프로그램 수행시 로케일이란 것에 의해 입맛에 맞는 환경을 선택할 수 있도록 만든 것을 말한다. 예를 들어 어떤 프로그램의 메시지가 여러가지 언어로 주어져 있는 경우 이중에 어떤 언어의 것을 출력할 것인가를 사용자가 결정할 수 있는 것이다. 그것을 가능하게 해 주는 수단이 바로 로케일이다. 이것은 단순히 메시지 뿐만이 아니고 숫자표현법, 날짜 또는 시간표현법 등 여러가지에 사용될 수 있다. 그것 각각을우리는 카테고리(category)라고 부른다. 카테고리에는 LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME 가 있다.
2. 로케일 설정방법
로케일을 지원하는 프로그램의 실행 방식을 선택하기 위해서는 환경 변수 설정을 이용한다. (카테고리 각각에 해당하는 환경변수는 카테고리 이름과 동일하다.)
로케일 환경 변수에 관한 정보는 locale이란 명령으로 간단히 얻을 수 있다.

% locale
LANG=ko_KR.eucKR
LC_CTYPE="ko_KR.eucKR"
LC_NUMERIC="ko_KR.eucKR"
LC_TIME="ko_KR.eucKR"
LC_COLLATE="ko_KR.eucKR"
LC_MONETARY="ko_KR.eucKR"
LC_MESSAGES="ko_KR.eucKR"
LC_ALL=
위에서 ko_KR.eucKR은 로케일 값(locale name)이다. 일반적인 로케일 값의 형식은 ll[_CC[.EEEE]][@dddd] 이다. ll은 언어(language)를 지정하는 소문자 두 글자 ISO 639 language code, CC는 지역(territory)를 지정하는 대문자 두 글자 ISO 3166 country code, EEEE는 코드셋(codeset)을 지정하는 문자셋(character set) 또는 인코딩(encoding), dddd는 방언 등의 변종을 구별하기 위한 것(modifier)이다. []로 표시된 내용은 안 쓸수도 있음을 의미한다. 예를 들면 en_US는 미국 영어권, en_CA는 영어권 카나다, de_DE는 독일의 독일어, fr_FR는 프랑스의 프랑스어를 의미한다.
아무 로케일도 설정하지 않았을 때 glibc에서의 기본 로케일은 C 또는 POSIX (glibc에서는 C 로케일의 alias) 로케일이다.

% locale -a
라는 명령을 이용하면 이외에 사용 가능한 로케일의 이름들을 알 수 있다. 다음은 여러가지 환경변수의 역할(카테고리의 경우에는 동시에 카테고리의 역할)에 관한 설명이다.
☞ LANG : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다. 하지만 LC_* 환경변수보다 우선 순위가 낮다. LC_ALL이 설정이 안 되어 있고 LC_* 값들이 설정이 따로 설정이 않된 경우 LANG을 변화시키면 LC_ALL을 제외한 로케일 카테고리들의 값이 변경되지만 LC_ALL이 설정 되어 있는 경우 LANG의 변화는 로케일 카테고리들의 값에 영향을 주지 않는다.
☞ LC_CTYPE : 문자 분류(알파벳, 숫자, 한글 또는 소문자, 대문자 등등), 변환, 대소문자 비교을 위한 로케일 설정을 의미한다. 이것은 예를 들어 fgetwc(), is*(), isw*(), mblen(), mbtowc(), wcstombs() 등의 함수에 영향을 줄 수 있다.
☞ LC_COLLATE : 스트링(string)의 정렬 순서(sort order 또는 collation)를 위한 로케일 설정을 위해 사용된다. 이것은 예를 들어 strcoll(), wcscoll(), strxfrm() 등의 함수에 영향을 줄 수 있다.
☞ LC_MESSAGES : 메시지 표현을 위한 로케일 설정. 메시지의 국제화를 위한 catopen(), gettext() 등의 함수에 영향을 줄 수 있다.
☞ LC_NUMERIC : 금액이 아닌 숫자 표현(천단위, 소수점, 숫자 그룹핑 등)을 위한 로케일 설정. 예를 들어 strtod(), atof(). 
☞ LC_MONETARY : 금액 표현(천단위 구분 문자, 소수점 문자, 금액 표시 문자, 그 위치 등)을 위한 로케일 설정. 예를 들어 strfmon().
☞ LC_TIME : 시간과 날짜의 표현(년, 월, 일에 대한 명칭 등)을 위한 로케일 설정 예를 들어 strftime(), strptime().
☞ LC_ALL : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다. 위의 LC_* 및 LANG의 어떤 것보다 우선 순위가 높다. 그리고 LC_ALL을 설정하면 다른 로케일 카테고리의 값들이 LC_ALL의 값의 변경되고 LC_ALL설정을 없애면 다른 로케일 카테고리의 값들은 이전값을 유지한다.
☞ LANGUAGE : 로케일의 다중 설정을 위해 gettext에서 사용되는 GNU extension 환경변수로 LC_ALL보다도 우선순위가 높다. 로케일들은 구분문자 : 을 이용하여 우선순위가 높은 순대로 나열된다. 예를 들어 LANGUAGE=en_US:ko_KR
☞ LINGUAS : gettext를 사용하는 프로그램 설치시 지정한 언어들의 메시지만을 설치하기 위한 환경변수. 구분 문자는 스페이스이다. 예를 들어 LINGUAS="ko ja"
로케일을 지원하기 위한 방법 및
3. 작동 원리
로케일을 제대로 지원하는 프로그램을 작성하기 위해서는 setlocale()함수를 이용하여 로케일을 설정하고 확인하여야 한다. setlocale()함수는 헤더 파일 locale.h 에 정의되어 있으며 그 프로토타입은 다음과 같다.
char *setlocale (int category, const char *locale);
이 함수의 역할은 카테고리 category에 대해 로케일 locale을 설정하고 (물론, 사용 가능한 로케일인 경우), 설정된 로케일값을 리턴하는 것이다.
locale 부분에 ""을 넣은 다음과 같은 예는
setlocale (LC_ALL, "");
적당한 환경변수를 참조하여 로케일을 설정하고 그 값을 리턴한다. 환경변수를 참조하는 우선순위는 위에서 설명한대로 LC_ALL, 그외 카테고리, LANG변수 순이고, 변수값을 알아내면 locale.alias(예를 들어, /usr/share/locale/)를 참조한 후 뒤에서부터 @ . _ 을 단위로 순서대로 잘라가며 사용가능한 로케일을 찾아낸다.
인수 locale 부분에 NULL을 넣은 다음예는
locale = setlocale (LC_ALL, NULL);
로케일 값을 변경시키지 않고 단지 카테고리에 관한 현재 로케일값을 알아내고자 하기 위해 그 리턴값을 사용하는 예이다.
다음은 함수 setlocale()을 사용하여 임시로 로케일로 변경하는 예이다. (glibc manual에 있는 예)
    #include <stddef.h>
    #include <locale.h>
    #include <stdlib.h>
    #include <string.h>
   
    void
    with_other_locale (char *new_locale,
                       void (*subroutine) (int),
                       int argument)
    {
      char *old_locale, *saved_locale;
   
      /* 현재 로케일명을 알아낸다. */
      old_locale = setlocale (LC_ALL, NULL);
   
      /* setlocale()의 재호출 의해 변경될 것을 대비해 로케일 이름을 미리 복사해 둔다. */
      saved_locale = strdup (old_locale);
      if (saved_locale == NULL)
        fatal ("Out of memory");
   
      /* 로케일을 변경하고 subroutine을 수행한다. */
      setlocale (LC_ALL, new_locale);
      (*subroutine) (argument);
   
      /* 원래의 로케일로 복귀한다. */
      setlocale (LC_ALL, saved_locale);
      free (saved_locale);
    }

다음은 로케일을 이용하여 날짜/시간을 출력하는 프로그램의 예이다.
#include <stdio.h>
#include <locale.h>
#include <time.h>

int main(void)
{
time_t now;
struct tm *l_time;
char string[256];

/* 환경변수로부터 시간 관련 로케일을 결정한다. */
setlocale(LC_TIME, "");

/* calendar 시간을 now라는 변수에 저장.
* 그 값은 1970년 1월 1일 이후부터 지금까지의 초단위 시간 */
now = time((time_t *)NULL);

/* calendar 시간의 다른 유용한 형태를 l_time변수에 저장 */
l_time = localtime(&now);

/* 우리가 원하는 포맷의 시간 포맷을 string이라는 변수에 저장 */
strftime(string, sizeof string, "%c", l_time);

/* 출력 */
printf("%s\n", string);

return 0;
}
다음은 위의 파일을 time_test.c라고 저장하고 컴파일하여 c쉘에서 시험하는
예이다.
% gcc -o time_test time_test.c
% setenv LANG ko_KR.eucKR
% ./time_test
2000년 01월 12일 수요일 오후 10시 26분 56초
% setenv LANG C
% ./time_test
Wed Jan 12 22:27:22 2000
2006/09/08 23:28 2006/09/08 23:28
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 무일물(無一物)」
원본 http://blog.naver.com/fr22m1n/140003752561

이 글은 KELP의 조형기님 글을 가져와서 수정한 것입니다.

- 들어가기 -
리눅스를 잘 알지 못할 당시 나는 리눅스에는 왜 Visual C++가 없는지에 대해 불평하였다. 그런 편리한 IDE환경이 없는지에 대해서 참으로 불만이었다. 어쩔 수 없이 이상한 에디터 vi를 배우기 시작했고, 명령 라인에서 gcc 를 구동하기 시작했었다. 그러다 명령 라인에서 gcc 를 계속 두들기니까... 뭐 편한 거 없나 ? 하고 살펴보고, 즉시 make 를 공부했다. 지금까지 이런 과정을 거치면서 리눅스의 전통적인 아니 유닉스의 전통적인 개발 환경과 개발 방법이 아주 매력적이라는 사실을 알게 되었다.
사실 알고 보면 Visual C++의 느낌표를 누르면 이러한 과정이 내부에서 일어나는 것이다. 우리 눈 앞에 안 보일 뿐이다. 나는 이 사실을 깨달았을때 Visual C++/MFC에 정이 뚝 떨어졌다. 지금도 어쩔 수 없는 초보이지만, 그러기에 나름대로 유닉스의 개발환경에 대하여 알아 본다.

- 개요도 -
이번에는 리눅스의 개발 환경이 전체적으로 어떻게 구성되어 있나 살펴보는 것이다. 우선 분류를 하여 나열해 보겠다.

[1] GNU Toolkit
  1) Binutils
  2) GCC
  3) GDB
  4) C, C++ library

[2] 디버깅 도구
  1) GDB
  2) DDD
  3) kdbg
  4) ldd
  5) strace
  6) ltrace
  7) checker

[3] 시간측정, 성능평가도구
  1) time
  2) gprof
  3) calls

[4] 자동 컴파일링 도구
  1) make
  2) m4
  3) Automake
  4) Autoconf

[5] 인터페이스 만들기 도구
  1) Xt
  2) Motif/Lesstif
  3) Xaw3D
  4) Tcl/Tk
  5) QT
  6) GTK+

[6] 버전 관리 도구
  1) CVS
  2) RCS
  3) SCCS

[7] 파일 패치 & 들여쓰기
  1) patch
  2) diff
  3) indent

한눈에 들어오니까 참 좋다. 이것을 보고 있으면 마음이 편안해진다. 빠진 내용이 있으면 피드 백을 해 주기 바란다. 여기에 나열되어 있는 모든 것들을 어느 정도 안다면 글쎄 유닉스/리눅스 초보는 분명 아닐 것이다. 위에서 [1] 항목은 분류항목으로 있기에 좀 그렇지만 대표적이라서 그냥 넣어 두었다.

- 본론 -
그럼 이제 하나하나 항목에 대해서 대충 알아보자. 이 내용들은 필자의 기반 지시과 '러닝 리눅스' 라는 책을 참고하였다. 이 책을 지은 '메트 웰시'라는 작자는 보통 사람은 아닌 것 같다. (www.linuxdoc.org 의 핵심 관리자이다.)

 [1] GNU toolkit
  1) Binutils - 여기에는 어셈블러(as), 링커(ld) 를 비롯하여 많은 바이너리 도구들이 포함되어 있다.
   ld - GNU 링커.
   as - GNU 어셈블러. ( 임베디드 리눅스를 하면서 어셈블리어는 필수겠죠?)
   addr2line - 주소를 파일명과 라인 수로 변경.
   ar - 정적 라이브러리를 만드는 유틸리티. (예 $ ar rs libxxx.a a.o b.o s옵션을 넣으면 ranlib 를 실행하지 않아도 된다.)
   c++filt - Filter to demangle encoded C++ symbols.
   gprof - 프로파일 정보 출력(프로파일러)
   nlmconv - 오브젝트 코드를 NLM으로 변경
   nm - 오브젝트 파일의 심볼들을 나열.
   objcopy - 오브젝트 파일을 복사 및 변환
   objdump - 오브젝트 파일을 덤프하여 여러가지 정보를 보여줌. 어셈블리어도 보여줌
   ranlib - 정정 라이브러리를 만들고 나서 인덱스 파일을 라이브러리 처음에 생성 시켜줌
   readelf - ELF 포맷의 오브젝트 파일의 정보 출력
   size - 오브젝트 또는 문서 파일의 정보 출력, text , data , bss, dec 등의 섹션 크기를 출력 (예 $ size any_program)
   strings - 파일로부터 출력 가능한 스트링 나열
   strip - 심볼 제거, 프로그램의 사이즈를 조금이라도 줄일려고 임베디드에선 많이 사용.
   windres - 윈도우즈용 파일을 위한 컴파일러
    ** 이런 바이너리 유틸리티를 능숙하게 다루는 것이 임베디드 리눅스 프로그래머에겐 필수이다.
    ** 그래서 나도 시간나는 데로 틈틈히,열심히 매뉴얼들을 읽고 있다. 시스템 프로그래밍의 기본이다.
  2) GCC - gcc에 대한 안내를 보라.
  3) GDB - 나는 명령라인에서 디버깅하는 프로그램. DDD라는 프로그램도 있다.
  4) c, c++ library - glibc 가 표준 C언어 라이브러이다.
   현재 나의 리눅스 머신에는 /lib/libc-2.2.2.so 라는 공유라이브러리로 존재한다.
   c++ 표준 라이브러리는 /usr/lib/libstdc++-3-libc6.2-2-2.10.0.so 라는 공유라이브러리로 존재한다.
   c library는 시스템 유틸리티들이 다 사용하기 때문에, c++ library 는 그렇지 않으니까, /usr/lib에 존재한다.
   물론 위의 두 개다 /usr/lib에 정적 라이브러리들로도 다 있다.
   표준 라이브러리의 소스는 www.gnu.org의 GNU Software 란에 다 있다.

 [2] 디버깅 도구
  1) gdb - 진짜 디버깅 툴
  2) ddd - GDB의 윈도우용 프론트 엔드
  3) kdbg - GDB의 윈도우용 프론트 엔드
   막강한 기능들을 많이 가지고 있다. 위의 프로그램 중에서는 ddd를 가장 많이 사용하는 것 같다.
   kdbg는 kde기반에서 나온것 같은데, kdevelop이라는 QT용 IDE툴의 기본 디버거로 들어가 있다.
  4) ldd - 공유 라이브러리 의존성을 출력해 준다. 불필요한 라이브러리는 제거하는 것이 좋다.
  5) strace / ltrace - 뭔가 추적하는 것이다.
   strace는 사용하는 시스템 콜을 추적하여 주는 것이고,
   ltrace는 라이브러리 호출을 추적하여 주는 것이다.
   지금 당장, hello world c언어 소스를 컴파일하여 실행하여 보라.
   그리고 strace/ltrace 를 실행하고 유심히 살펴보라. 감이 올 것이다!
    $ strace ./hello
   $ ltrace ./hello

  6) checker - 프로그램 코딩중 메모리 할당 루틴에서 문제가 있는 것 같으면, 사용하는 것이다.
   컴파일하기 전에 -lchecker 라는 옵션을 주는 것을 잊지 말자.
   그리면 문제가 있는 메모리 할당 루틴을 checker 가 검사하여 원인을 보고 하여 줄 것이다.

 [3] 시간 측정, 성능 평가 도구
  1) time - 프로그램의 수행 시간을 측정해 준다. 시스템 유틸리티이지만, 같은 이름의 라이브러리 함수가 있다.(man 2 time)
  2) gprof - 바이너리 유틸리티에 포함되어 있다. 이것은 프로파일러이다.
   즉, 코드 안에서 병목 현상을 일으키는 곳을 파악할 수 있다.
   각 함수가 얼마나 자주 호출되는지, 각 함수에서 소요된 시간 등 실행한 프로그램의 목록을 보여주는 도구이다.
   컴파일 할때 -pg 옵션을 주고 해야 한다. 컴파일 후 실행하라.
   정상적으로 종료하면, 현재 디렉토리에 gmon.out 이라는 파일을 내어 놓는다.
   이 파일안에 실행 프로파일 정보가 들어 있으며 gprof를 사용하여 통계값을 볼 수 있다.
    $ gprof 프로그램명 gmon.out
  3) calls - c 소스 코드 안에서의 호출 관계를 계층 구조로 보여 준다.
   호출된 모든 함수의 인덱스를 만들거나 프로그램 구조에 대한 계층 구조 보고서를 작성할 때 좋다.
    $ calls hello.c

 [4] 자동 컴파일링 도구
  1) make - 조금이라도 덩치 있는 프로그램을 작성해 보았다면 필요성을 절실히 느낄 것이다.
   make를 사용할 줄 모른다면, 남이 작성한 파일을 보고 수정할 수 있으면 된다.
   그러다 보면 자신만의 makefile을 만들수 있을 것이다.
  2) m4 / automake / autoconf - 플랫폼에 독립적인 프로그램을 배포할 때 필요한 것들이다.
   make 파일을 작성하는 것이 또 지루한 작업이기 때문에 그것을 자동으로 해주는 툴이 automake이다.
   autoconf는 configure 라는 스크립트를 자동으로 작성해 주는 툴이다.
   우리가 프로그램을 설치할때 리눅스에서, 가장 먼저, ./configre 하지 않는가?
   그 configure 스트립트를 만들어 주는 것이 autoconf 이다.
   configure 라는 스트립트는 여러가지를 시스템에서 찾아보고, 알맞은 makefile을 만들어 주는 것이다.
   그후에 make 명령을 이용해서 컴파일을 시키는 것이다.
   m4는 매크로 프리 프로세서라는 것이다. aotoconf에서 내부적으로 사용하는 것이다.

 [5] 인터페이스 만들기 도구
  1) Xt - X library의 기본 툴킷이다.
  2) Motif / Lesstif - 유닉스상에서 전통적으로 인기있는 윈도우 툴킷이지만 상용이다.
   오픈소스의 다음 세대(QT, GTK+)들에게 대세를 빼았기었다. 그리고 Lesstif 가 나왔지만 대세는 홀러간 뒤었다.
  3) Xaw3D - 표준 아데나(Athena)위젯의 변형 버전으로써 마치 모티프와 같은 스타일의 3D 효과를 준다.
  4) Tcl/Tk - 창, 버튼, 스크롤바 등 기존의 프로그램에서 사용하고 있는 X 기반의 완전한 인터페이스를 만들 수 있다.
  5) Qt - 트롤 테크(Troll Tech)가 만든 C++ GUI 툴킷이다.
   나는 QT로 윈도우 프로그래밍을 즐긴다. 왜냐면, 예쁘기 때문이다. 나는 뭐니뭐니 해도 예쁜게 좋다.
   gtk기반의 어플리케이션은 알고리즘이나 성능을 좋더라도, 보기에 좋지는 않다.
  6) GTK+ - 원래 김프라는 이미지 처리 프로그램을 위해 만든 C GUI 툴킷이다.

 [6] 버전 관리 도구
  1) CVS - (Concurrent Versioning system) 거의 표준으로 자리 잡고 있다. 인터넷으로 전세계 개발자들이
   함께 개발할 수 있게끔 해주는 멋진 도구이다. 거의 모든 오픈 소스 프로젝트들이 CVS로 개발되고 있다.
  2) RCS - (Revision control system) CVS와 비슷하다. RCS로는 한 그룹내에서 개발할때 사용한다.
  3) SCCS - (Source Code Control System) 카네기 멜론 대학에서 개발된 것이다.

 [7] 파일 패치 & 들여 쓰기
  1) patch - 정기적으로 갱신되는 프로그램이 있고 프로그램이 매우 많은 소스 파일로 이루어져 있으며
   한 버전에서 다음 버전으로 갱신하려고 상황에 맞게 파일을 변환시켜주는 프로그램이다.
   매번 전체 소스 배포 파일을 내놓는 것이 적절치 않을 때에 주로 사용한다.
   방법은 각 버전마다 변경된 부분만을 patch로 갱신하는 것이다.
  2) diff - patch보다 작은 규모의 업그레이드에 유용하게 사용된다.

  <사용법>
    $ patch -pNUM〈 patchfile
   $ diff [option] from-file to-file


  < 예제1. 소스가 단순 파일 하나일 때 >
  hello1.c 가 있고, 다음 버전인 hello2.c 가 있다고 하자.
  우선 hello.patch 라는 패치 파일을 만들어 내려면 다음과 같이 한다.
    $ diff -c hello1.c hello2.c > hello.patch
  이렇게 만든 패치 파일을 배포하며, 이 패치 파일을 다운 받은 사용자는 다음과 같이 하여 hello1.c 소스에 패치를 가한다.
    $ patch〈 hello.patch

  < 예제2. 소스가 디렉토리 구조일 때 >
  hello1 라는 디렉토리가 있고, 다음 버전인 hello2라는 디렉토리가 있다고 하자.
  우선 hello.patch 라는 패치 파일을 만들기 위해서는 다음과 같이 한다.
    $ diff -cr hello1 hello2 > hello.patch ( 옵션 -r 은 recursive를 의미 )
  이렇게 만든 패치 파일을 배포하며, 이 패치 파일을 다운 받은 사용자는 다음과 같이 hello1 디렉토리 구조에 패치를 가한다.
    $ patch -p0〈 hello.patch (-pNUM 에 대한 옵션은 맨페이지 참고)

  3) indent - 코드를 예쁘게 들여쓰기를 해준다. 다음과 같이 사용할 수 있다.
    $ indent hello.c

출처 : 엠파스블로그 > 입으로 하는 행동, 손으로 하는 생각.

> 테마 : Programming?

2006/09/08 23:27 2006/09/08 23:27
이 글에는 트랙백을 보낼 수 없습니다
Linux/SHELL  2006/09/08 23:25
grep 계열 명령어

grep 명령어

grep의 의미

grep : 파일 전체를 뒤져 정규표현식에 대응하는 모든 행들을 출력한다.
egrep : grep의 확장판으로, 추가 정규표현식 메타문자들을 지원한다.
fgrep : fixed grep 이나 fast grep으로 불리며, 모든 문자를 문자 그래도 취급한다. 즉, 정         규표현식의 메타문자도 일반 문자로 취급한다.

3.1.2 grep의 동작 방법

grep에서 사용하는 정규표현식 메타문자
메타문자
기    능
사용 예
사용 예 설명
^
행의 시작 지시자
'^love'
love로 시작하는 모든 행과 대응
$
행의 끝 지시자
'love$'
love로 끝나는 모든 행과 대응
.
하나의 문자와 대응
'l..e'
l 다음에 두 글자가 나오고 e로 끝나는 문자열을 포함하는 행과 대응
*
선행문자와 같은 문자의 0개 혹은 임의개수와 대응
' *love'
0개 혹은 임의 개수의 공백 문자 후에 love로 끝나는 문자열을 포함한 행과 대응
[]
[] 사이의 문자 집합중 하나와 대응
'[Ll]ove'
love나 Love를 포함하는 행과 대응
[^ ]
문자집합에 속하지 않는 한 문자와 대응
'[^A-K]love'
A와 K 사이의 범위에 포함되지 않는 한 문자와 ove가 붙어있는 문자열과 대응
\<
단어의 시작 지시자
'\<love'
love로 시작하는 단어를 포함하는 행과 대응(vi,grep에서 지원)
\>
단어의 끝 지시자
'love\>'
love로 끝나는 단어를 포함하는 행과 대응
(vi,grep에서 지원)
\(..\)
다음 사용을 위해 태그를 붙인다.
'\(lov\)ing'
지정된 부분을 태크1에 저장한다. 나중에 태그값을 참고하려면 \1을 쓴다. 맨 왼쪽부터 시작해 태그를 9개가지 쓸 수 있다. 왼쪽 예에서는 lov가 레지스터1에 저장되고 나중에 \1로 참고할 수 있다.
x\{m\}
문자 x를 m번 반복한다.
'o\{5\}'
문자 o가 5회 연속적으로 나오는 모든 행과 대응
x\{m,\}
적어도 m번 반복한다.
'o\{5,\}'
문자 o가 최소한 5회 반복되는 모든 행과 대응
x\{m,n\}
m회 이상 n회 이하 반복한다.
o\{5,10\}'
문자 o가 5회에서 10회 사이의 횟수로 연속적으로 나타나는 문자열과 대응

grep의 옵션
옵션
동작 설명
-b
검색 결과의 각 행 앞에 검색된 위치의 블록 번호를 표시한다. 검색 내용이 디스크의 어디쯤 있는지 위치를 알아내는데 유용하다.
-c
검색 결과를 출력하는 대신, 찾아낸 행의 총수를 출력한다.
-h
파일 이름을 출력하지 않는다.
-i
대소문자를 구분 하지 않는다.(대문자와 소문자를 동일하게 취급).
-l
패턴이 존재하는 파일의 이름만 출력한다.(개행문자로 구분)
-n
파일 내에서 행 번호를 함께 출력한다.
-s
에러 메시지 외에는 출력하지 않는다. 종료상태를 검사할 때 유용하게 쓸 수 있다.
-v
패턴이 존재하지 않는 행만 출력한다.
-w
패턴 표현식을 하나의 단어로 취급하여 검색한다.

# grep -n '^jack:' /etc/passwd
(/etc/passwd 파일에서 jack을 찾는다. jack이 행의 맨 앞에 있으면 행 번호를 화면으로 출력한다.)

3.1.3 grep과 종료 상태
grep은 파일 검색의 성공 여부를 종료 상태값으로 되돌려준다.
패턴을 찾으면 0, 패턴을 찾을 수 없으면 1, 팡리이 존재하지 않을 경우 2
sed,a자 등은 검색의 성공 여부에 대한 종료 상태값을 반환하지 않는다. 다만 구문 에러가 있을 경우에만 에러를 보고한다.

3.2 정규표현식을 사용하는 grep의 예제
# grep NW datafile
# grep NW d*
(d로 시작하는 모든 파일에서 NW를 포함하는 모든 행을 찾는다.)
# grep '^n' datafile
(n으로 시작하는 모든 행을 출력한다.)
# grep '4$' datafile
(4로 끝나는 모든 행을 출력한다.)
# grep TB Savage datafile
(TB만 인자이고 Savage와 datafile은 파일 이름이다.)
# grep 'TB Savage' datafile
(TB Savage를 포함하는 모든 행을 출력한다.)
# grep '5\.' datafile
(숫자 5, 마침표, 임의의 한 문자가 순서대로 나타나는 문자열이 포함된 행을 출력한다.)
# grep '\.5' datafile
(.5가 나오는 모든 행을 출력한다.)
# grep '^[we]' datafile
(w나 e로 시작하는 모든 행을 출력한다.)
# grep '[^0-9]' datafile
(숫자가 아닌 문자를 하나라도 포함하는 모든 행을 출력한다.)
# grep '[A-Z][A-Z] [A-Z]' datafile
(대문자 2개와 공백 1개, 그리고 대문자 하나가 연이어 나오는 문자열이 포함된 행을 출력한다.)
# grep 'ss* ' datafile
(s가 한 번 나오고, 다시 s가 0번 또는 여러번 나온 후에 공백이 연이어 등장하는 문자열을 포함한 모든 행을 출력한다.)
# grep '[a-z]\{9\}' datafile
(소문자가 9번 이상 반복되는 문자열을 포함하는 모든 행을 출력한다.)
# grep '\(3\)\.[0-9].*\1 *\1' datafile
(숫자 3,마침표,임의의 한 숫자,임의 개수의 문자,숫자 3(태그),임의 개수의 탭 문자,숫자 3의 순서를 갖는 문자열이 포한된 모든 행을 출력한다.)
# grep '\<north' datafile
(north로 시작하는 단어가 포함된 모든 행을 출력한다.)
# grep '\<north\>' datafile
(north라는 단어가 포함된 모든 행을 출력한다.)
# grep '\<[a-z].*n\>' datafile
(소문자 하나로 시작하고, 이어서 임의 개수의 여러 문자가 나오며, n으로 끝나는 단어가 포함된 모든 행을 출력한다. 여기서 .*는 공백을 포함한 임의의 문자들을 의미한다.)

3.3 grep에 옵션 사용
# grep -n '^south' datafile
(행번호를 함께 출력한다.)
# grep -i 'pat' datafile
(대소문자를 구별하지 않게 한다.)
# grep -v 'Suan Chin' datafile
(문자열 Suan Chin이 포함되지 않은 모든 행을 출력하게 한다. 이 옵션은 입력 파일에서 특정 내용의 입력을 삭제하는데 쓰인다.
# grep -v 'Suan Chin' datafile > black
# mv black datafile
)
# grep -l 'SE' *
(패턴이 찾아진 파일의 행 번호 대신 단지 파일이름만 출력한다.)
# grep -w 'north' datafile
(패턴이 다른 단어의 일부가 아닌 하나의 단어가 되는 경우만 찾는다. northwest나 northeast 등의 단어가 아니라, north라는 단어가 포함된 행만 출력한다.)
# grep -i "$LOGNAME" datafile
(환경변수인 LOGNAME의 값을 가진 모든 행을 출력한다. 변수가 큰따옴표로 둘러싸여 있는 경우, 쉘은 변수의 값으로 치환한다. 작은따옴표로 둘러싸여 있으면 변수 치환이 일어나지 않고 그냥 $LOGNAME 이라는 문자로 출력된다.)

3.4 egrep
egrep(extended grep) : grep에서 제공하지 않는 확장된 정규표현식 메타문자를 지원  한다.
                                    grep와 동일한 명령행 옵션을 지원한다.
egrep에서 지원하는 확장 메타문자
메타문자
기능
사용 예
사용 예 설명
+
선행문자와 같은 문자의 1개 혹은 임의 개수와 대응
'[a-z]+ove'
1개 이상의 소문자 뒤에 ove가 붙어있는 문자열과 대응. move,approve,love,behoove 등이 해당된다.
?
선행문자와 같은 문자의0개 혹은 1개와 대응
'lo?ve'
l 다음에 0개의 문자 혹은 하나의 문자가 o가 나오는 문자열과 대응. love,lve 등이 해당된다.
a|b
a 혹은 b와 대응
'love|hate'
love 혹은 hate와 대응.
()
정규표현식을 묶어준다
'love(able|ly)'
lovable 혹은 lovely와 대응.
'(ov)+'
ov가 한 번 이상 등장하는 문자열과 일치.

3.4.1 egrep 예제
# egrep 'NW|EA' datafile
(NW나 EA가 포함된 행을 출력한다.)
# egrep '3+' datafile
(숫자 3이 한 번 이상 등장하는 행을 출력한다.)
# egrep '2\.?[0-9]' datafile
(숫자 2 다음에 마침표가 없거나 한 번 나오고, 다시 숫자가 오는 행을 출력한다.)
# egrep ' (no)+' datafile
(패턴 no가 한 번 이상 연속해서 나오는 행을 출력한다.)
# egrep 'S(h|u)' datafile
(문자 S 다음에 h나 u가 나오는 행을 출력한다.)
# egrep 'Sh|u' datafile
(패턴 Sh나 u를 포함한 행을 출력한다.)

3.5 고정 grep 과 빠른 grep
fgrep : grep 명령어와 동일하게 동작한다. 다만 정규표현식 메타문자들을 특별하게 취급하지
         않는다.
# fgrep '[A-Z]****[0-9]..$5.00' file
([A-Z]****[0-9]..$5.00 이 포함된 행을 출력한다. 모든 문자들을 문자 자체로만
2006/09/08 23:25 2006/09/08 23:25
이 글에는 트랙백을 보낼 수 없습니다
Linux/SHELL  2006/09/08 23:12
출처 블로그 > 수진오빠 개그소매상
원본 http://blog.naver.com/soojin001/140005615267
- 본 쉘 프로그래밍 -

2001년 1월 13일
written by 허정수(wertyu@nownuri.net)

1. 왜 쉘 프로그래밍을 배워야 하는가?
이 글을 읽는 사람들 중에서는 왜 쉘 프로그래밍을 배워야 하는지 아는 사람도 있고, 모르는 사람도 있을 것이다. 21 세기, 리눅스를 사용하기도 많이 편리해지고, X 윈도를 실행해서 버튼 몇 개만 클릭하면 편하게 사용할 수 있는데 왜 어려운 쉘 프로그래밍을 배워야 하는지 모르는 사람도 있을 것이다.

하지만, 리눅스를 어느 정도 사용해 본 사람이라면, 리눅스를 편하게 사용하기 위해서 쉘의 사용법과 쉘 프로그래밍을 꼭 알아야 하는 것을 알고 있을 것이다. 어느 책에서는 MS Windows와 유닉스/리눅스의 가장 큰 차이점을 바이너리와 텍스트로 설명하고 있다. 즉, MS Windows는 바이너리 유닉스는 텍스트이다. MS Windows는 모든 설정을 바이너리로 관리하여 사용자가 직접 프로그램의 설정을 변경할 수 없고, 설정을 변경하기 위해서는 꼭 설정을 변경하는 프로그램을 통해야만 한다.(regedit 처럼) 하지만 유닉스는 모든 설정을 텍스트 파일로 관리한다. (요즘 MS Windows도 Script를 이용하여 설정을 바꿀 수 있도록 변하고 있는 추세이다. 즉 유닉스의 장점을 MS Windows도 이해하고 따라가고 있다.)

이 극명한 차이가 쉘 프로그래밍을 배워야 하는 이유이다. 예를 들어 설명해 보자. 시스템 교체를 위해 MS Windows와 유닉스의 사용자 1만 명을 다른 시스템으로 옮긴다고 생각해 보자. MS Windows에서는 분명 사용자 추가하는 프로그램을 실행하여 각 1만 명의 아이디와 암호 및 프로필을 손수 입력해야 할 것이다. 아무리 클릭을 빠르게 하고, 타이핑이 아무 빨라고 많은 시간이 필요하다. 하지만, 유닉스에서는 간단하게 스크립트를 짜서 실행하면 된다.

다른 예도 있다. 다음과 같이 현재 디렉터리에 확장자가 gif인 파일이 많이 있다고 하자.

13:28[wertyu@inos test]$ ls
a.gif b.gif c.gif d.gif mmv.sh*

그런데, 여기 있는 gif 파일의 확장자를 모두 jpg로 바꾸려고 한다. 앞의 예에서는 파일이 4개 밖에 안 되지만 만약, 파일이 1000개 라면 당신은 어떻게 할 것인가. 이 때 간단히 스크립트를 짜서 실행하면 쉽게 확장자를 고칠 수 있다. 다음의 스크립트는 확장자가 gif인 파일의 확장자를 jpg로 바꾸는 스크립트이다.(프롬프트 앞의 13:13은 필자의 프롬프트에서 시간을 나타낸다.)

13:31[wertyu@inos test]$ cat mmv.sh
#! /bin/sh

X=`ls *.gif`
for B in $X
do
temp=`basename $B .gif`
mv $B $temp.jpg
done

13:31[wertyu@inos test]$ ls
a.gif b.gif c.gif d.gif mmv.sh*
13:31[wertyu@inos test]$ ./mmv.sh
13:31[wertyu@inos test]$ ls
a.jpg b.jpg c.jpg d.jpg mmv.sh*

어떤가 쉽지 않은가?

2. How the Shell Interpret What You Typed

이번 절에서는 아주 간단히 쉘이 어떻게 작동하는지 알아 보려 한다. 이번 절의 제목을 해석해 보면, "쉘은 당신이 입력한 것을 어떻게 해석하는가"(How the Shell Interpret What You Typed)이다. 쉘이 작동하는 방법을 조금이나마 이해하기 바란다. 다들 알고 있겠지만, 쉘은 리눅스에서 명령을 내리는데 가장 중요한 프로그램이다.(MS Windows에서의 Shell은 Internet Explorer이다. 알고 있었나?). 쉘은 명령을 내리기 위해서는 어쩔 수 없이 거쳐야 하는 프로그램이기 때문에 쉘이 작동 원리를 이해하면 명령을 쉽고 빠르고 간단하게 입력할 수 있다. 또한 쉘이 작동하는 원리를 정확히 이해해야만 쉘 프로그램도 잘 짤 수 있다.

다음의 예를 보자. 다음과 같이 간단한 C로 작성한 프로그램이 있다.

13:42[wertyu@inos test]$ cat how.c
#include <stdio.h>

void main(int argc, char* argv[])
{
int cnt ;

for( cnt = 1 ; cnt < argc ; ++cnt )
{
printf("arguement %d = %s
", cnt , argv[cnt] ) ;
}
}

이 프로그램을 how라는 실행 파일로 컴파일 해 놓자.

문제 1.
다음의 실행 결과는 무었인가?

$ how $HOME

을 실행 시키면 출력 결과는 무었일까? 이 문제는 쉬울 것이다.

답 1.

13:47[wertyu@inos test]$ ./how $HOME
arguement 1 = /home/wertyu
13:47[wertyu@inos test]$

문제 2.

디렉터리에 다음과 같은 파일들이 있다.

13:48[wertyu@inos test]$ ls
a.jpg b.jpg c.jpg d.jpg how* how.c mmv.sh*

다음을 실행하면 무엇이 출력 될까.

13:48[wertyu@inos test]$ ./how *

이건 조금 어렵다. 쉽게 맞출 수 있는 사람도 있겠지만, 대부분의 사람들은 '*'가 출력된다고 답할 것이다. 그러나 답은....

답 2.

13:48[wertyu@inos test]$ ./how *
arguement 1 = a.jpg
arguement 2 = b.jpg
arguement 3 = c.jpg
arguement 4 = d.jpg
arguement 5 = how
arguement 6 = how.c
arguement 7 = mmv.sh
13:49[wertyu@inos test]$

위의 두 문제를 풀어 봄으로서 대충이나마 쉘의 작동 방법을 이해할 수 있었을 것이다.

3. 쉘 스크립트를 작성해 보자.

이제 기본적인 설명은 끝났으므로 실제 쉘 스크립트를 작성해 보자. 쉘 스크립트의 첫 줄은 항상 다음과 같이 시작을 해야 한다.

#! /bin/sh

이 첫 줄은 인터프리터를 지정하는 줄이다. 앞으로 나올 여러 명령들을 인터프리트할 프로그램을 지정한다. 마찬가지로 awk로 스크립트를 작성하기 위해서는 스크립트의 첫 줄은 #! /bin/awk로 시작해야 할 것이다.

쉘 스크립트를 작성하는 방법은 간단한다. 사용하기 편한 에디터로 명령들을 적은 후에 파일의 모드를 '실행' 모드를 주는 것이다. 다음의 예를 보자


14:01[wertyu@inos test]$ cat > echo.sh
#! /bin/sh
echo $1

14:02[wertyu@inos test]$ chmod 775 echo.sh
14:02[wertyu@inos test]$ ./echo.sh Parameter
Parameter
14:02[wertyu@inos test]$

위의 예를 보면 알 수 있듯이 각자 사용하기 편리한 에디터로 스크립트를 작성한 후 chmod 명령으로 파일에 실행 권한을 주어 실행 할 수 있다. 참고로 앞에 나온 echo.sh은 입력받은 parameter 중 첫 번째 parameter를 출력하는 쉘 스크립트이다.

3.1 변수의 선언 및 사용법

쉘 프로그램에서 변수를 선언하는 방법을 알아 보자. 변수는 간단히

변수명=변수값

과 같이 선언할 수 있다. 여기서 중요한 것은 '변수명'과 '=', '변수값' 사이에 공백이 있으면 안 된다는 것이다. 따라서 다음과 같은 쉘 프로그램은 잘못된 것이다.

14:07[wertyu@inos test]$ cat wrong.sh
#! /bin/sh
x = 123
echo $x
14:07[wertyu@inos test]$ ./wrong.sh
./wrong.sh: x: command not found

'x = 123' 부분을 'x=123'과 같이 수정한 후 실행 시키면 123이 출력되는 것을 볼 수 있다.

선언한 변수를 사용하기 위해서는 앞의 예와 같이 변수명 앞에 $를 붙여주면 된다.

3.2 Flow of Control
Flow of Control이란 한글 책에서 흔히 '흐름 제어'로 번역되는 단어로서 '조건 분기문' '루프' 등을 나타낸다. 어떠한 프로그램이든 그 프로그램을 구성하는 프로그램 logic 중 80%는 Flow of Control일 정도로 어떤 language를 배우든 Flow of Control을 익히는 것은 매우 중요하다.

3.2.1 if 문

본 쉘 프로그래밍에서 if문은 다음과 같이 사용된다.

if test_statement_A
then
statement_B
statement_C
else
statement_D
fi

다음의 예를 보자

14:36[wertyu@inos test]$ cat test.sh
#! /bin/sh

if [ $# -eq 0 ]
then
echo "No arguement"
else
echo "There are $# arguement(s)"
fi
14:36[wertyu@inos test]$ ./test.sh
No arguement
14:36[wertyu@inos test]$ ./test.sh a b c d e
There are 5 arguement(s)

여기서도 중요한 것은 '[' 와 조건을 검사하는 부분과 ']' 사이에 공백이 있어서는 안 된다는 것이다.
'$#' 변수는 본쉘 스크립트의 특수 변수로서 인자의 수를 나타내는 변수이고, -eq는 equal의 약자로서 두 수가 같은지 비교하는 연산자 이다.

if [ $# -eq 0 ] 은 다음과 같이 바꾸어 사용해도 된다.

if test $# -eq 0

즉, 앞의 test.sh 스크립트는 다음의 스크립트와 동일하게 동작한다.

14:42[wertyu@inos test]$ cat test.sh
#! /bin/sh

if test $# -eq 0
then
echo "No arguement"
else
echo "There are $# arguement(s)"
fi

test는 외부 명령으로서 주어진 expression을 검사하여 true or false를 return하는 명령이다. 여기서 test를 예로 든 것은 if 의 조건에는 외부 명령이 함께 쓰일 수 있기 때문이다. 즉, 다음 스크립트와 같이 작동하는 스크립트를 작성할 수 있다.

if ls plot.ps
then
lpr plot.ps
else
echo ":::: ERROR FILE DOESN'T EXIST ::::"
fi

앞의 예제 스크립트는 plot.ps라는 파일이 있을 경우에 프린트를 하고, plot.ps라는 파일이 없을 경우에는 에러 메시지를 출력하는 스크립트이다.


3.2.2 숫자의 비교

앞의 예에서 -eq로 두 수의 값이 같은지 비교하는 것을 보았다. -eq 외에도 많은 연산자가 있다.

-eq : equal, 두 수가 같냐?
-ne : not equal, 두 수가 같지 않냐?
-gt : greater than, 왼쪽 변수가 오른쪽 변수보다 크냐?
-lt : less than, 왼쪽 변수가 오른쪽 변수보다 작냐?
-ge : greater than or equal, 왼쪽 변수가 오른쪽 변수보다 크거나 같냐?
-le : less than or equal, 왼쪽 변수가 오른쪽 변수보다 작거나 같냐?

3.2.3 문자열의 비교

문자열을 비교하기 위한 연산자는 다음과 같다.

[ "String1" = "String2" ] : 두 문자열이 같은지
[ "String1" != "String2" ] : 두 문자열이 다른지
[ -z $X ] : $X라는 문자열 변수의 길이가 0이면 참
[ -n $X ] : $X라는 문자열 변수의 길이가 0이 아닐 경우 참

또한 '!'는 NOT을 나타낸다. 따라서 다음의 두 expression은 같은 것이다.

[ -z $X ]
[ ! -n $X ]

3.2.4 File 검사

이번 절에서는 File과 관련된 test를 알아보기로 한다. 파일이 존재하는지 검사하는 스크립트는 프로그램의 설정 파일을 검사할 때 많이 쓰인다. 예를 들어 $HOME/.vimrc가 있을 경우 $HOME/.vimrc 설정 파일을 읽어 들이고 없을 경우 default 설정 파일을 읽어 들이도록 하는데 사용될 수 있다.

[ -b file ] : file이 존재하고 file이 block special file인 경우 참
[ -c file ] : file이 존재하고 file이 character special file인 경우 참
[ -d file ] : file이 존재하고 file이 directory인 경우 참
[ -f file ] : file이 존재하고 file이 일반적인 file인 경우 참
[ -g file ] : file이 존재하고 file에 Set-Group-Id가 set 되어 있는 경우 참
[ -h file ] : file이 존재하고 file이 symbolic link인 경우 참
[ -H file ] : file이 존재하고 file이 hidden directory인 경우 참
[ -k file ] : file이 존재하고 file에 sticky bit가 set되어 있는 경우 참
[ -p file ] : file이 존재하고 file이 named pipe인 경우 참
[ -r file ] : file이 존재하고 file에 읽기 권한이 있는 경우 참
[ -s file ] : file이 존재하고 file의 size가 0이 아닌 경우 참
[ -u file ] : file이 존재하고 file에 Set-User-Id가 set되어 있는 경우 참
[ -x file ] : file이 존재하고 file에 실행 권한이 있는 경우 참
[ -w file ] : file이 존재하고 file에 쓰기 권한이 있는 경우 참

위의 모든 것을 외울 필요는 없지만 쉘 스크립트에서 file과 관련하여 어떤 것을 검사할 수 있는지 정도는 알아두는 것이 좋다.

3.2.5 AND/OR 연산자

C 언어에서는 &&가 logical AND 연산자, ||가 logical OR 연산자인데, 본 쉘 프로그래밍에서는 AND는 -a, OR는 -o 이다.

3.2.6 Loop

본 쉘 프로그래밍에서는 C 언어와 비슷하게 3 개의 Loop 관련 문을 제공한다.

3.2.6.1 for

for문의 문법은 다음과 같다

for VARIABLE in LIST
do
STATEMENT1
STATEMENT2
done

1절에서 잠시 살펴 본 여러 file의 확장자를 동시에 바꾸는 스크립트를 다시 한 번 살펴보자

#! /bin/sh

X=`ls *.gif`
for B in $X
do
temp=`basename $B .gif`
mv $B $temp.jpg
done

X에 ls *.gif의 값이 저장된다. 이 값은 LIST의 형태로 생각하면 된다. 즉, 차례로 확장자가 gif인 파일이 저장된다고 생각하라.
for B in $X를 살펴 보면, 앞의 ls *.gif의 결과 값 각각에 대해서 for 이하의 문을 실행하라는 것이 된다. 그리고 그 각각의 값은 임시로 B에 저장이 된다.

temp=`basename $B .gif`

basename은 $B에서 .gif 부분을 제외한 부분을 리턴하는 프로그램이다. 직접 프롬프트에서 명령을 내려서 결과를 확인할 수도 있다.

23:17[wertyu@inos test]$ basename wertyu.gif .gif
wertyu

여기서 중요한 것은 '가 아니라 `이라는 점이다. 쉘 스크립트에서 변수의 값에 외부 명령을 실행 시킨 결과 값을 저장하기 위해서는 ` command `를 이용하면 된다. 즉

temp=`basename $B .gif`

는 $B에서 .gif 부분을 떼어버리고 남은 문자열을 temp에 저장하는 것이 된다. 나머지는 쉽게 이해할 수 있을 것이라 생각된다.

다음의 스크립트는 grep과 비슷한 스크립트이다. (출처:http://pneuma.phys.ualberta.ca/~gingrich/research/shells/shells.html, 이 글에서 설명한 본 쉘 스크립트의 문법은 앞의 사이트에서 가져온 것도 몇 개 있으니 참고하기 바란다.)

#! /bin/sh
#
# A script to look for the occurence of a string in a file
# Usage: match [string] [file]
#
for word in `cat $2`
do
if [ ``$word'' = ``$1'' ]
then
echo ``Found $1 in file $2''
else
:
fi
done

각자 이해해 보시길.... 근데, ``$word'' = ``$1'' 의 의미는 필자도 잘 모르겠다. 그냥 $word = $1으로 바꿔도 잘 돌아가던데....

3.2.6.2 while

for 문에 대해서는 이해가 되었을테니 이제 while 문을 볼까?

문법)

while condition
do
commands
done

예) 10, 9, 8,...,1을 출력하는 스크립트이다.

number=10
while [ $number -ge 1 ]
do
echo $number
number=`expr $number - 1`
done

while은 condition이 참일 동안 loop를 돈다.

3.2.6.3 until

until은 while과 거의 비슷하다.

문법)

until condition
do
commands
done

단, while과 한 가지 차이점이 있는 것은 while은 condition이 참일 동안 loop를 돌지만, until은 condition이 거짓일 동안 loop를 돈다는 것이다.

다음의 예는 while에서의 예와 같은 일을 하는 스크립트를 until을 이용하여 작성한 것이다.

예)

number=10
until [ $number -lt 1 ]
do
echo $number
number=`expr $number - 1`
done

3.2.7 case 문

이 번 절에서는 case 문에 대해서 알아 보겠다. C 언의 case와 아주 유사하므로 쉽게 이해할 수 있을 것이다. 단, C 에서는 if-elseif를 쉽게 case 문으로 바꿀 수 있지만, 본 쉘 스크립트에서의 case는 if 보다 훨 씬 많은 기능을 제공한다.

다음의 예를 보자.

#!/bin/sh
case $# in
0)
echo ""no parameters"";;
1)
echo "only one parameter." ;;
*)
echo "more than one parameter." ;;
esac

설명 안 해도 이제 이해되겟지? case 다음의 $#의 값에 따라서, 0)이냐 1)이냐에 따라서, 원하는 것을 실행 시킬 수 있다.
위의 예에서는 case의 장점을 살펴 볼 수 없었다. 그러나 다음의 예를 보면, case의 유용함에 대해서 쉽게 알 수 있을 것이다. case의 유용함은 Regular Expression을 사용할 수 있다는 것이다. Regular Expression 까지 설명하려면 글이 길어 지므로, Regular Expression은 필자가 번역한 http://nnr.or.kr/linux/regular.htm을 참고하거나 다른 참고 자료를 살펴 보기 바란다.
그럼 다음의 예를 보자

while :
do
echo "Would you like to continue? c"
read ANS
case $ANS in
[yY] | [yY][eE][sS]) echo "Fine, then we'll continue."
break
;;
[nN] | [nN][oO]) echo "We shall now stop."
exit
;;
*) echo "You must enter a yes or no verdict!"
esac
done
echo "
We are now out of the while loop."

일단 저장해 놓고 실행 해 보자. 돌려 보면 알겠지만, Yes를 입력하든 Y를 입력하든 YES를 입력하든 yEs를 입력하든, [yY] | [yY][eE][sS])는 true가 된다.
참 하나 설명을 안 하고 넘어간 부분이 있다.

while :

은 항상 참을 나타낸다.

아. 또 read도 설명 안 했군. read ANS는 사용자로부터 문자열을 입력받아 ANS에 저장하는 명령이다.

이 정도면 설명이 다 되었을 것이다.

4. 마치면서

아주 간단하게나마 본 쉘 프로그래밍에 대해서 알아 보았다. 너무나 간단하여 복잡한 일은 하기 힘들 것이다. 남은 것은 여러분의 노력 뿐... 아주 간단하게 본 쉘 스크립트를 알아 보았으므로, 다음 시간에는 TIP을 중심으로 본 쉘 스크립트에 대해서 알아 보겠다. 단, 필자도 아직 위의 내용 이외에는 아는 것이 별로 없으므로 공부를 한 후에 나머지 내용을 쓰도록 하겠다.

* 참고 자료 :

http://www.sao.nrc.ca/imsb/rcsg/documents/bourne/bourne.html
http://pneuma.phys.ualberta.ca/~gingrich/research/shells/shells.html

ps. 검색 엔진에서 shell programming이라고 입력하면 수 많은 결과가 나올테니 열심히 공부하기 바란다~~~


-------------------------------------------------------------------------------------------


출처 블로그 > Jay's
원본 http://blog.naver.com/cocktail74/40004597832

특수문자

Match

사용 예

Match

.

임의의 한 문자

*

한 번도 없거나 한번 이상 반복

abcd*

abc, abcd, abcdd 등과 match

.*

모든 문자

^

행의 처음

^X

행의 첫머리의 X

X^

행의 임의의 위치의 X

^/^ or ^^

행의 첫머리의 ^

$

행의 마지막

X$

행의 끝의 X

$X

행의 임의의 위치의 X

\$$ or $$

행의 끝의 $

[]

[,] 안의 아무 문자

c[aeiou]t

cat, cet... 와 match

-를 사용하여 범위 설정 가능

c[a-z0-9]t

두 번째 문자의 임의의 소문자나 숫자

-와의 match를 위해선 [-나 -] 이용

c[-ai]

c-, ca, ci

]와의 match를 위해선 []와 같이 나타냄

c[]ai]

c], ca, ci

^를 [다음에 사용하면 [, ]안의 문자를 제외한 문자들과 match

[A^-Z]

대문자를 제외한 문자

\{n,m\} (ed, sed, grep 에서만 사용 가능)

\{n\}은 바로 앞의 expression이 n번 반복 된 것

[0-9]\{3\}

세 개의 숫자

\{n,\}은 바로 앞의 expression이 n번 또는 그 이상 반복된 것

0\{4,\}

4개 이상의 0

\{n,m\}는 바로 앞의 expression이 n번에서 m번 반복된 것

1\{4,9\}

4개에서 5개의 1

\

특수 문자들의 기능을 수행하지 않고 문자 그대로 받아들임

\*\**

한 개 또는 그 이상의 *

^[ ^I]*$

공백행과 space나 TAB을 포함한 행(겉보기 공백행). 여기서 ^I는 ctrl+I로써 TAB과 같다

^.*$

임의의 행 전체

modifier를 이용하여 변수 값이나 history에 저장된 명령어의 내용을 변환시킬 수 있다.

(단, set A = (/home/user/temp.c), set B = (a.c b.c c.c d.c))

Modifier

기능

사용 예

결과

:h

pathname에서 마지막 부분을 제어하고 앞부분만 남김

echo $A:h

/home/user

:t

pathname에서 마지막 부분만 남기고 pathname을 제거함

echo $A:t

temp.c

:r

pathname에서 끝 부분의 .xxx만 제거

echo $A:r

/home/user/temp

:e

.xxx만 남기고 앞부분 제거

echo $A:e

c

:g

:gh, :gr, :gt, :ge의 형태로 사용되며, array변수에 저장된 모든 값들에 h,r,t,e를 적용시킨다.

echo $B:r

a b c d

:p

명령어를 실행시키지 않고 출력만 시킨다.

!:p

:q

특수 문자들의 기능을 수행하지 않고 단순히 출력만 시킨다.

%echo *
%!:q

*

특수문자

의미

비고

!

history 기능을 시작하기 위한 특수문자

!n

n번째로 사용된 명령 실행

!-n

현재부터 n번째 앞에 사용된 명령 실행

!!

바로 전에 실행되었던 명령 실행

!-1

!string

가장 최근에 string으로 시작되는 명령 실행

!?string[?]

가장 최근에 string을 포함하고 있는 명령 실행

^aa^bb

마지막으로 실행된 명령어에서 aa를 bb로 치환하여 명령 실행

!*

마지막으로 실행된 명령에 사용된 모든 argument

!$ or !!$

마지막 명령의 마지막 argument

!^

마지막 명령의 첫 argument

event:s^aa^bb

event는 앞에서 !로 시작하는 history 명령이다. aa를 bb로 치환한다. 단, ^대신 다른 특수 문자를 사용하여도 된다.

ex) !23:s/aa/bb

!:n or !!:n

마지막 명령의 n번째 argument

!:n*

마지막 명령의 n번째부터 그 이후의 argument

!:n-$

!:0

마지막 명령의 명령어만 나타냄

!:n-m

마지막 명령의 n번째부터 m번째까지의 argument

!:-n

마지막 명령의 명령어부터 n번째 argument까지

!:n-

마지막 명령의 n번째부터 마지막 argument를 제외한 argument

!?string?%

가장 최근에 string을 포함하고 있는 단어를 나타냄

색코드

의미

0

기본 화면색. 흰 글자색. 검정 배경색

1

bold intensity

4

흑백 모드에서는 밑줄

5

반짝임

7

역상

30

검정 (회색) 글자색

31

빨강 (옅은 빨강) 글자색

32

녹색 (옅은 녹색) 글자색

33

갈색 (노랑) 글자색

34

파랑 (옅은 파랑) 글자색

35

보라 (옅은 보라) 글자색

36

cyan (옅은 cyan) 글자색

37

흰색 (밝은 흰색) 글자색

40

검정 (회색) 배경색

41

빨강 (옅은 빨강) 배경색

42

녹색 (옅은 녹색) 배경색

43

갈색 (노랑) 배경색

44

파랑 (옅은 파랑) 배경색

45

보라 (옅은 보라) 배경색

46

cyan (옅은 cyan) 배경색

47

흰색 (밝은 흰색) 배경색

10

기본 font 선택

38

밑줄 사용 가능

39

밑줄 사용 불가능

Escape Sequence

기능

ESCc

화면을 지우고 커서를 1행 1열로 이동시킴

ESC[nA

커서를 현위치에서 위로 n칸 이동

ESC[nB

커서를 현위치에서 아래로 n칸 이동

ESC[nC

커서를 현위치에서 오른쪽으로 n칸 이동

ESC[nD

커서를 현위치에서 왼족으로 n칸 이동

ESC[n;mH 또는 ESC[n;mf

커서를 m열 n행으로 이동시킴

ESC[nJ

n = 0 이면 현위치에서 화면의 끝까지 지움
n = 1 이면 화면의 처음에서 현위치까지 지움
n = 2 이면 화면 전체를 지움

ESC[nK

n = 0 이면 현재 커서의 위치에서 행의 끝까지 지움
n = 1 이면 행의 처음에서 현재의 커서 위치까지 지움
n = 2 이면 현재 커서가 있는 행을 모두 지움

ESC[nL

n 행을 현재 커서 위치에 삽입

ESC[nM

현재 커서 위치에서부터 n행 삭제

ESC[nP

현재 커서 위치의 행의 처음부터 n개 문자 삭제

ESC[nX

현재 커서 위치에서부터 n개 문자 삭제

ESC[nM

화면의 색지정. 여러 가지 색을 지정할 때는 ;를 사용하여 구분한다.

2006/09/08 23:12 2006/09/08 23:12
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 막강 파워 스킬만이 살길이다~
원본 http://blog.naver.com/norther80/80010287760


작성자 : 김칠봉
작성일 : 2001.03.12

목차
1. 가장 일반적인 find 명령어

2. find 명령어 일반적인 옵션
2-1. 사용법 개요
2-2. 일반적으로 표현식 옵션 구분
3-3. 자주 사용되는 표현식 옵션
3-4. path(find 명령어 다음의 path)
3-5. 표현식-연산자

3. 예제
3-1. 다른 명령어와 결합형태(ls,xargs)
3-2. 퍼미션 관련 예제
3-3. 유저와 관련된 예제
3-4. 팁
- 최근 하루(1) 동안(-)에 변경(change)된 파일을 찾을려면(-ctime)?
- 오래된 파일을 찾을려면(30일 이상 수정(modify))되지 않은)?
- 최근 30일(30) 안에(-) 접근(access)하지 않은 파일과 디렉토리를 리스트로 만들려면(-atime)?
- 자신의 홈디렉토리에서 만 검색하려면?
- 서브 디렉토리로 내려가지 않고 현재 디렉토리에서만 검색하려면?
- 특정 유저(foobar) 소유의 파일을 찾을려면?
- 퍼미션이 777인 파일을 찾을려면 ?
- others에게 쓰기 권한이 있는 파일을 찾을려면?
- others에게 쓰기 권한이 있는 파일을 찾아 쓰기 권한을 없애려면?
- 유저이름과 그룹이름이 없는 파일을 찾을려면?
- 빈 파일을 찾을려면?
- 파일크기가 100M 이상된 파일을 찾을려면?
- *.bak 파일을 찾아 지울려면?
- *.bak 파일을 찾아 특정 디렉토리로 옮길려면?
- 디렉토리 만 찾을려면?
- root권한으로 실행되는 파일을 찾을려면?
- 다른 파일시스템을 검색하지 않을려면?
- 파일이름에 공백이 들어간 파일을 찾을려면?
- 숨겨진(hidden) 파일을 찾을려면?
- 같은 이름을 가진 디렉토리를 찾을려면?
- 잘못된 링크를 찾을려면?

4. find 명령어에 대해서 좀더 알아보려면?

------------------------------------------------------------

1. 가장 일반적인 find 명령어

# find /path -name "foobar" -print

제일 먼저(?) 배우는 형식이 아닌가 쉽군요.


2. find 명령어 일반적인 옵션

2-1. 사용법 개요

find 명령어 사용법 보기 :

# find --help
# man find (직접 입력해 보세요. 내용이 너무 많아서..)

사용법 : find [path...] [expression]
기본값 : default path는 현재 디렉토리; default expression은 -print

표현식(expression) 구성 :
operators (decreasing precedence; -and is implicit where no others are given):
( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2
EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2
options (always true): -daystart -depth -follow --help
-maxdepth LEVELS -mindepth LEVELS -mount -noleaf --version -xdev
tests (N can be +N or -N or N):
-amin N -anewer FILE -atime N -cmin N
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME
-ilname PATTERN -iname PATTERN -inum N -ipath PATTERN -iregex PATTERN
-links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN
-size N[bckw] -true -type [bcdpfls] -uid N -used N -user NAME
-xtype [bcdpfls]
actions:
-exec COMMAND ; -fprint FILE -fprint0 FILE -fprintf FILE FORMAT
-ok COMMAND ; -print -print0 -printf FORMAT -prune -ls

간단하게 몇가지만 알아보죠...
(자세한 사용설명은 꼭 man 페이지를 읽어보세요....한글은 없군요..T.T)


2-2. 일반적으로 표현식 옵션 구분

-a'xxxx'
'xxxx'에 대한 Access(접근)
-c'xxxx'
'xxxx'에 대한 Changes(변경), 마지막으로 Access한 경우 변경됨
-m'xxxx'
'xxxx'에 대한 Modify(수정), 파일내용 자체 수정한 경우
-i'xxxx'
'xxxx'(inum 제외)에 대한 Insensitive(대소문자 구분없이)

3-3. 자주 사용되는 표현식 옵션

N
정확하게 N과 일치
+N
N 보다 큰 경우
-N
N 보다 작은 경우
-name PATTERN
PATTERN에 일치하는 파일 찾기, 와일드카드 문자 사용가능
-iname PATTERN
PATTERN에 일치하지 않은(insensitive) 파일 찾기
-perm [+-]mode
PERMission('mode')에 해당되는 파일 찾기, ls와 결합 가능
-type [bcdpfls]
b(블럭파일), c(특정 문자), d(디렉토리), p(파이프),
f(정규표현 일반파일), l(링크), s(소켓) 유형의 파일 찾기
-size N[bckw]
파일 크기가 N 인 파일 찾기
b(블럭-기본값), c(bytes), k(kbytes),
w(2바이트 단어)
-user NAME
NAME은 유저이름이거나 UID
-atime N
N*24 시간 동안에 Access 한 파일
-ctime N
N*24 시간 동안에 Changes 한 파일(내용수정이 아니고 읽기모드도 Changes됨)
-mtime N
N*24 시간 동안에 Modify 한 파일
-empty
파일이 비어 있고(0 bytes), 정규식 파일이거나 디렉토리
-newer FILE
FILE 보다 최근에 갱신된 파일
-path PATTERN
path가 PATTERN과 일치하는 path에 대해서 검색
-regex PATTERN
파일이름이 PATTERN에 일치하는 정규식에 대해서 검색
-inum N
inode N을 갖는 파일
-nouser,-nogroup
USER나 GROUP에 이름이 없는 파일 검색(UID,GID만 있는 파일)
-exec COMMAND
검색된 파일을 찾으면 COMMAND 명령을 실행한다.
COMMAND 인자(검색된 파일)는 {}으로 사용하며,
이때 COMMAND 끝은 ;(;이 아님)을 사용해야 한다. 즉 명령구분
문자인 ';'을 탈출()시켜줘야 한다.
-ok COMMAND
-exec COMMAND와 같지만 COMMAND를 실행하기 전에 확인을 요청한다.

3-4. path(find 명령어 다음의 path)
.
현재 디렉토리(기본값이므로 생략해도 됨)
`pwd`
현재 디렉토리와 결합(?) `은 ~문자가 있는 자판
$(pwd)
위의 `pwd`와 같거나 비슷함
/
최상위 루트 디렉토리에서 하위 모든 디렉토리
/home
특정 /home 디렉토리에서 하위 모든 디렉토리
/{usr,home/{aaa,san2},var}
/usr, /usr/home/aaa /usr/home/san2 /var

3-5. 표현식-연산자

( 표현식 )
'표현식'을 우선적으로 먼저 수행
(와 )앞에 를 넣어야 하며, '표현식'과 공백을 각각 둔다.
( A + B ) * ( C + D ) 와 같이 (, )안을 우선적으로 수행
! 표현식 , -not 표현식
'표현식'을 부정
표현식1 -a 표현식2, 표현식1 -and 표현식2
표현식1과 표현식2의 AND 연산
표현식1 -o 표현식2, 표현식1 -or 표현식2
표현식1과 표현식2의 OR 연산


3. 예제

3-1. 다른 명령어와 결합 형태(ls,xargs)

찾는 것 그 차체 만으로 만족(?) 할 수 도 있지만 그 결과에 대해서
어떤 행동(Actions)을 취할 필요가 있습니다.

형태1. -exec 이용시

# find ..... -exec COMMAND {} ;

형태2. xargs 명령어로 표준 입력받아 COMMAND 수행

# find ..... | xargs COMMAND

형태3. ls 명령어로 최종 결과 출력

# ls -l `find .....[COMMAND]`
또는
# find .... ls
(ls는 ls -dils와 같음)

xargs
xargs rpm 정보보기
# rpm -qi `rpm -qf $(which xargs)`
또는
# rpm -qf `which xargs` | xargs rpm -qi

즉, find 결과에 대해서,

형태1은 -exec를 사용하여 그 인자를 {}로 사용하고,

형태2는 xargs 명령어로 find에서 넘어온 결과(표준출력)에 대해서 COMMAND를 실행하고,

형태3은 오른쪽의 find 결과물에 대해서 ls 명령어를 실행합니다.
간혹 '/bin/ls Argument list too long'이라는 에러를 낸 경우도 있습니다.
이는 검색조건에 너무 많은 와일드카드 문자로 찾을 경우에 그렇습니다.
이를 테면 /*/*/*.*/.*,

`은 ~문자가 있는 자판(역인용부호).

ls -l 명령어를 사용할 경우, 찾는 결과가 없다면 모두 출력됩니다.
(ls -l와 같기 때문에)
ls 명령어와 마찬가지로 다른 명령어(chmod, chmod)를 결합하여 사용할 경우 그 찾는
결과가 없다면 명령어에 대한 에러를 내겠죠.
(chmod 'null')과 같은 예..........

# find /{home,usr/{src,local/src}} -nouser -o -nogroup -exec ls -l {} ; -print | more
# find /{home,usr/{src,local/src}} -nouser -o -nogroup -print | xargs ls -l | more

위의 2개의 명령어 대해서 직접 테스트 해보세요...

전자의 경우, 아마 아무것도 출력되지 않을 겁니다.

# find /{home,usr/{src,local/src}} ( -nouser -o -nogroup ) -exec ls -l {} ; -print | more

위와 같이 해야 맞겠죠...(우선순위)

후자의 경우도 마찬가지로 다음과 같이 우선순위를 정해놓아야 겠지요..
아마 원하는 출력이 이 경우일 것 같군요.

# find /{home,usr/{src,local/src}} ( -nouser -o -nogroup ) -print | xargs ls -l | more


3-2. 퍼미션 관련 예제

othesrs에 쓰기(w:2) 권한이 있는 모든(-기호를 붙임) 파일 리스트를 찾을려면?

# find `pwd` -perm -2 -print | xargs ls -l

여기에서 2는
퍼미션이 -------w- 와 일치하는 파일이며 -의 의미는 rwx-중 하나.

왜 2인가요?
만약 퍼미션이 755 이라면,

700 : rwx------ : user
50 : ---r-x--- : group
5 : ------r-x : others
------------------------
755 : rwxr-xr-x : others는 읽기와 실행 권한

따라서 others의 권한은 8진수로 5(r+x)이다.

그렇다면, others가 쓰기(w:2) 권한은 당연히 -------w-

그룹이나 others에게 쓰기 권한이 있는 파일일 경우

-perm -20 -o -perm -2

그룹과 others에게 모두 쓰기 권한이 있는 파일일 경우

-perm -22

[others에게 w 권한이 있는 파일에 w 권한 없애기]

방법1)
1. others에게 w 권한이 있는 파일 리스트 출력

# find `pwd` -perm -2 -print | xargs ls -l | more
(만약 매치되는 리스트가 없다면 전부 출력함)

2. others에게 w 권한을 없애기

# find `pwd` -perm -2 -print | xargs chmod o-w
(만약 매치되는 리스트가 없다면 chmod에 에러를 냄)

방법2) 방법1)의 과정을 한꺼번에 할 경우

# find `pwd` -perm -2 -exec chmod o-w {} ; -print | xargs ls -l
또는
# ls -l `find $(pwd) -perm -2 -print | xargs chmod o-rwx` | more

이 경우는 퍼미션이 조정된 결과를 출력함.


3-3. 유저와 관련된 예제

UID와 GID에 대한 유저가 없는 파일을 root.root로 바꾸어 보죠.

1) 먼저 리스트를 출력해 보자.(확인해야하니깐)

# find . ( -nouser -o -nogroup ) -print | xargs ls -l | more

2) 확인했으면, chown root.root 명령을 내리자.

# find . ( -nouser -o -nogroup ) -print | xargs chown root.root | more
또는
# find . ( -nouser -o -nogroup ) -exec chown root.root {} ; -print | xargs ls -l
(chown root.root 의 결과를 ls -l)


3-4. 유용한 팁

*주의) ***********************************************
-a'xxxx'
'xxxx'에 대한 Access(접근), 읽기
-c'xxxx'
'xxxx'에 대한 Changes(변경), 마지막으로 Access한 경우에도 변경됨
-m'xxxx'
'xxxx'에 대한 Modify(수정), 파일내용 자체 수정한 경우
*****************************************************

- 최근 하루(1) 동안(-)에 변경(change)된 파일을 찾을려면(-ctime)?

# find / -ctime -1 -a -type f | xargs ls -l | more

- 오래된 파일을 찾을려면(30일 이상 수정(modify))되지 않은)?

# find / -mtime +30 -print | more

- 최근 30일(30) 안에(-) 접근(access)하지 않은 파일과 디렉토리를 리스트로 만들려면(-atime)?

# find / ! ( -atime -30 -a ( -type d -o -type f ) ) | xargs ls -l > not_access.list

- 자신의 홈디렉토리에서 만 검색하려면?

# find $HOM ...
또는
# find ~root ...

- 서브 디렉토리로 내려가지 않고 현재 디렉토리에서만 검색하려면?

# find . -prune ...

- 특정 유저(foobar) 소유의 파일을 찾을려면?

# find / -user foobar -print | more

- 퍼미션이 777인 파일을 찾을려면 ?

# find / -perm 777 -print | xargs ls -l | more

- others에게 쓰기 권한이 있는 파일을 찾을려면?

# find / -perm -2 -print | xargs ls -l | more

- others에게 쓰기 권한이 있는 파일을 찾아 쓰기 권한을 없애려면?

# find / -perm -2 -print | xargs chmod o-w
또는
# find / -perm -2 -exec chmod o-w {} ; -print | xargs ls -l | more

- 유저이름과 그룹이름이 없는 파일을 찾을려면?

# find / ( -nouser -o -nogroup ) -print | more

- 빈 파일을 찾을려면?

# find / -empty -print | more
또는
# find / -size 0 -print | more

- 파일크기가 100M 이상된 파일을 찾을려면?

# find / -size +102400k -print | xargs ls -hl

- *.bak 파일을 찾아 지울려면?

# find / -name "*.bak" -exec rm -rf {} ;

- *.bak 파일을 찾아 특정 디렉토리로 옮길려면?

# mv `find . -name "*.bak"` /home/bak/

- 디렉토리 만 찾을려면?

# find . -type d ...

- root권한으로 실행되는 파일을 찾을려면?

# find / ( -user root -a -perm +4000 ) -print | xargs ls -l | more

- 다른 파일시스템을 검색하지 않을려면?

# find / -xdev ...

- 파일이름에 공백이 들어간 파일을 찾을려면?

# find / -name "* *" -print

- 숨겨진(hidden) 파일을 찾을려면?

# find / -name ".*" -print | more

- 같은 이름을 가진 디렉토리를 찾을려면?

# find / -type d -print | awk -F/ '{printf("%st%sn",$NF,$0);}' | sort| more
*주)'O'Reilly Unix Power Tools' 참고

- 잘못된 링크를 찾을려면?

# find . -type l -print | perl -nle '-e || print' | xargs ls -l
*주)'O'Reilly Unix Power Tools' 참고
2006/09/08 23:11 2006/09/08 23:11
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 일기와 개발백서입니다.
원본 http://blog.naver.com/baltasar/100002719983

2년 전에 작성해놨던 문서인데 내용이 워낙 부실해 공유를 할까말까 하다가 제 블로그에 공유하게 되는군요.


----------------------------------------------------------------------------------------


리눅스상에 Postgres 설치해서 JDBC 셋팅하기

* 준비사항
jdk1.3.X(postgres 7.2.2에서는 jdk1.4를 사용할 경우 컴파일 에러가 납니다.)
jakarta ant
j2sdkee
postres 7.2.2 소스버전


1. http://www.postgresql.org에서 postgres를 소스 버전으로 다운 받는다.
  요즘 유행하는 패키지(RPM)를 구하긴 했었는데 의존성 문제로 포기했음.
  예전에 의존성 문제로 죽는줄 알아서 -_-

2. 루트계정으로 접속해 소스 압축을 풀어준다.
  /usr/local/tar xzvf postgresql-7.2.1.tar.gz

3. 설치 하기 전에 환경 설정해주기
  위치는 /usr/local/pgsql로 odbc와 jdbc 드라이버를 함께 설치해야 함.
  그리고 jdbc드라이버의 컴파일을 ant로 하기 때문에 ant가 깔려있어야 합니다.
  ./configure --prefix=/usr/local/pgsql --enable-locale --enable-multibyte --enable-nls --enable-odbc --with-java
  (enable-multibyte 안하시면 UTF-8 개발 쫑~ 입니다.)

4. 컴파일
  gmake

5. 컴파일 검사. (본인은 DB 초기화시에 에러가 났으나 문제는 없음)
  gmake check

6. 설치
  gmake install

여기서 끝난게 아닙니다.
관리 계정을 추가하고 공유라이브러리를 셋팅하고 DB스페이스(거대한 통짜DB)와 사용자별DB를 생성해야 합니다.
7. 관리 계정 추가하기
  adduser postgres

8. 공유라이브러리 셋팅하기
  bash의 경우 .bash_profile에 다음과 같이 설정합니다.
  LD_LIBRARY_PATH=/usr/local/pgsql/lib
  export LD_LIBRARY_PATH
  쉘 상에서 여러명이 DB를 사용할테니 /etc/profile에 설정하는게 좋겠죠?

9. DB스페이스 생성하기
  DB스페이스가 설치될 디렉토리를 만들고
  mkdir /usr/local/pgsql/data
 
  DB스페이스 디렉토리의 소유자를 관리 계정으로 바꾸고
  chown postgres /usr/local/pgsql/data

  계정을 관리 계정으로 바꿔서
  su -l postgres

  DB스페이스를 생성합니다.
  /usr/local/pgsql/bin/initdb -E EUC_KR -D /usr/local/pgsql/data
-E옵션은 한글 정렬을 위해 반드시 넣어야 합니다.


제대로 설치했다면 다음과 같은 메세지가 뜰 겁니다.
[zodiac:postgres]~ # /usr/local/pgsql/bin/initdb -E EUC_KR -D /usr/local/pgsql/data
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

Fixing permissions on existing directory /usr/local/pgsql/data... ok
creating directory /usr/local/pgsql/data/base... ok
creating directory /usr/local/pgsql/data/global... ok
creating directory /usr/local/pgsql/data/pg_xlog... ok
creating directory /usr/local/pgsql/data/pg_clog... ok
creating template1 database in /usr/local/pgsql/data/base/1... ok
creating configuration files... ok
initializing pg_shadow... ok
enabling unlimited row size for system tables... ok
creating system views... ok
loading pg_description... ok
vacuuming database template1... ok
copying template1 to template0... ok

Success. You can now start the database server using:

   /usr/local/pgsql/bin/postmaster -D /usr/local/pgsql/data
or
   /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start

만약 사용자를 바꾸는걸 깜빡 했다면
[zodiac:postgres]/usr/local # /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

creating directory /usr/local/pgsql/data... mkdir: cannot create directory `/usr/local/pgsql/data': 허가 거부됨

initdb failed.
아마도 이런 메세지가 뜨겠지요.

자 그럼 DB를 시작시켜 봅시다.
DB를

* 시작하기
/usr/local/pgsql/bin/postmaster -i -D /usr/local/pgsql/data
-i옵션은 TCP/IP접속을 허용합니다. 외부에서 접속한다면 당연히 해야겠죠?

매번 하기 귀찮으면 관리 계정의 .bash_profile에 다음과 같이 설정합니다.
export PGDATA=/usr/local/pgsql/data
그러면 다음부터는
/usr/local/pgsql/bin/postmaster -i
이것만 하셔도 DB가 시작됩니다.

* 중지하기
pgsql/bin/pg_ctl stop
이전 버전에 따라서는 그냥 kill 시켜야 되는 것도 있습니다.

10. 인제 진짜 마지막입니다.
물리DB를 계정별로 쪼개 쓸 논리공간을 할당을 해야 합니다.
관리 계정으로 /usr/local/pgsql/bin으로 이동해서 사용자 DB를 만듭시다.
/usr/local/pgsql/bin/createdb postgres
만약 DB를 시작하지 않고 사용자 DB를 만들었다면 다음과 같은 메세지가 뜹니다.
[zodiac:postgres]/usr/local/pgsql/bin # createdb postgres
psql: could not connect to server: Connection refused
       Is the server running locally and accepting
       connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
createdb: database creation failed

그리고 이전에 postgres를 설치하셨던 분들이 자주 부딪치는 에러는..
[zodiac:postgres]/usr/local/pgsql/bin # ./postmaster
FATAL 1:  Can't read lock file /tmp/.s.PGSQL.5432.lock: Permission denied

루트로 접속 후 /tmp에 가서 .s.PGSQL로 시작되는 파일을 전부 제거해 주시면 해결됩니다.

그다음에 JDBC 드라이버 사용을 위해 /etc/profile에 classpath를 추가합니다.
추가항목: /usr/local/pgsql/share/java/postgresql.jar

11. 연습으로 쓰실거라면 이게 전부지만..
서비스를 한다면 접속부분을 정의해야 되겠죠?
그러기에 앞서 pgsql을 실행하고 관리계정의 암호를 지정해 줍니다.

alter user postgres with password '패스워드';

그리고 psql터미널을 종료한 후
pgsql/data/pg_hba.conf의 접속옵션 부분을 다음과 같이 변경합니다.
(postgres는 초기설정상 패스워드 입력으로는 터미널 접속을 불허하도록 되어 있습니다.)

local        all          all                                            password
host         all          all          0.0.0.0       0.0.0.0             password

그다음에 pgsql/bin/pg_ctl reload를 수행해 갱신합니다.
그러면 그다음 부터는 접속시 패스워드를 넣어야 접속이 가능해집니다.

이상으로 설치를 마칩니다.




위의 설정에서 내부 로케일 변환 문제가 발생되었습니다.

설치시 다음과 같이 변경하세요.

// 현재 시스템의 한글 설정상태 확인

[server1:main]~ # echo $LANG
ko_KR


//db 초기화에 다국어 셋팅하기

[server1:main]~ # initdb -no-locale --lc-collate=C -E utf-8


[server1:main]~ # createdb -E utf-8 testdb


이렇게 하면 클라이언트 터미널에서 문제가 생길겁니다.

다음과 같이 셋팅하여 UTF-8을 클라이언트에서 지원하도록 합시다.

set client_encoding = 'uhc';

2006/09/08 22:43 2006/09/08 22:43
이 글에는 트랙백을 보낼 수 없습니다
Hacking  2006/09/08 22:43
출처 블로그 > ♡ 나의 라임 오렌지 나무 ♡━˚
원본 http://blog.naver.com/joan7636/120012356815

네트워크 통신의 비밀 ARP
웹브라우저를 띄운 후 아무 생각없이 접속하는 도메인 예 이지만 실제로 이 ( :www.tt.co.kr)
도메인 네임은 내부적으로 에 의해 주소로 바뀌어 로 접속이 되는 것이다 과연 DNS IP IP .
그것이 다인가 그렇지 않다 실제로 요청은 다시 라는 프로토콜에 의해 주 ? . IP ARP MAC
소라는 하드웨어 주소로 변경된 후 접속이 되는 것이다 이 과정은 그리 복잡하지는 않지만 .
이 과정을 제대로 이해하지 않고서는 네트워크 보안 을 이야기 할 수 없을 정도로 많은 것 “ ”
들을 놓치게 된다 실제로 를 이용한 해킹은 그리 낯선 방법도 어려운 방법도 아니다 . ARP .
이번 호에서는 많은 사람들이 그 중요성을 놓치고 있는 구간에서의 통신 프로토콜인 LAN
와 이와 관련하여 숨겨져 있는 재미있는 사실들에 대해 알아보도록 하자 ARP .
오늘과내일 넷센터 홍석범(antihong@tt.co.kr)
과 WAN LAN
흔히들 일상적인 네트워크 구간을 크게 구간과 WAN(Wide Area Network) LAN(Local
구간으로 나눈다 흔히 이러한 과 구간을 나누는 장비로는 게이 Area Network) . WAN LAN
트웨이 역할을 하는 라우터가 담당하는데 혹시 라우터라는 장비를 보신 분들도 있을지 모 ,
르겠지만 라우터라는 장비를 보면 적게는 두 개에서 많게는 몇 십개까지의 많은 인터페이스
랜카드 로 이루어져 있는 것을 볼 수 있을 것이다 이 인터페이스들은 담당하는 역할에 따 ( ) .
라 구간을 담당하는 시리얼 인터페이스와 구간을 담당하는 이더넷 WAN (Serial) LAN
인터페이스로 나눌 수 있다 따라서 흔히들 구간을 시리얼 구간 (Ethernet) . WAN , LAN
구간을 이더넷 구간이라 부르기도 한다 구간에서는 라우터와 라우터간에 서로 약속 . WAN
한 라우팅 프로토콜을 이용해 통신을 하게 되는데 이를테면 전세계적으로 간에 연동시 ,( ISP
에는 라는 프로토콜을 이용하여 연동한다 이에 대해서는 홈페이지등 라우팅 BGP . CISCO
관련 서적을 참고하기 바란다 그렇다면 구간에서는 어떤 프로토콜을 이용하여 서로 .) LAN
통신하게 될까 그렇다 바로 이다 ? . ARP . “ ”
ARP
는 의 약자로서 마치 가 도메인 주소를 주소 ARP Address Resolution Protocol DNS IP
로 바꾸어주는 것처럼 주소를 주소로 변환해 주는 프로토 IP MAC(Media Access Control)
콜이다 그렇다면 주소는 또 무엇인가 주소는 각 이더넷 카드마다 유일한 하드 . MAC ? MAC
웨어 주소로서 이 정보는 리눅스의 경우 로 윈도우즈의 경우 로 확 ifconfig , ipconfig /all
인할 수 있다.
는 일반 유저들에게는 그리 친숙하지 않은 단어이지만 이 프로토콜은 로컬 네트워크의 ARP
매우 중요한 규약이며 를 이해하여야만이 네트워크의 보안을 설명할 수 있을 정도로 ARP
반드시 숙지하여야 할 중요한 프로토콜이다.
와 DNS ARP
를 쉽게 이해하기 위해 아래 그림과 같이 자신의 에서 인터넷을 접속하는 경로를 생 ARP PC
각해 보자 자신의 에서 브라우저를 실행하여 을 입력한 후 엔터를 치면 . PC www.tt.co.kr
해당 도메인의 웹 페이지가 접속이 된다 너무 당연한 것 같은 이 절차는 실제로 어떠한 경 .
로를 통해 접속이 되는 것일까 다소 지루할 지 모르겠지만 전체 네트워크를 이해하기 위해 ?
처음 과정부터 거슬러 올라가 보도록 하자.
자신의 브라우저에서 도메인명을 입력하면 이 요구는 제일 먼저 자신의 에서 설정한 PC
서버 이 서버를 편의상 라 하자 로 가게 된다 서버는 DNS ( DNS Client DNS .) . Client DNS
의 요구 도메인을 주소로 변환 를 받아 자신 스스로가 위임 권 www.tt.co.kr Resolving ( IP )
한이 있는지 즉 자신의 파일에 질의한 도메인이 정의되어 있는지 여부를 ( , /etc/named.conf )
확인하여 없을 경우에는 질의한 도메인에 대한 캐싱이 있는지 여부를 확인하고 있을 경우 ,
바로 해당 정보를 넘겨주지만 없을 경우에는 소위 서버라는 최상위 서버에 질의 root DNS
를 하게 된다 일반적으로 웹 접속시 이라고 입력하지만 실제로 엄격히 . http://www.tt.co.kr
이야기한다면 와 같이 주소의 제일 끝에 을 붙이는 것이 맞는 것이 http://www.tt.co.kr. .
다 여기에서 주소 제일 끝에 있는 을 서버로 부른다 서버는 전 세계적으로 . . root . root 13
개가 있으며 만약 서버에 장애가 생기면 전 세계의 인터넷은 마비가 되고 말 것이다 root .
여하튼 질의를 받은 서버는 질의한 도메인의 주소가 인 것을 보고 을 관장하는 root .kr .kr
서버는 한국 전산원의 서버라는 답을 해 주고 이 답을 받은 서버는 DNS DNS Client DNS
한국 전산원의 서버에 다시 을 질의하게 된다 이 질의를 받은 한국 전 DNS www.tt.co.kr .
산원의 서버는 질의한 도메인이 인 것을 보고 이번에는 을 관장하는 DNS .co.kr co.kr
서버에 다시 질의하라고 응답하고 이 응답을 받은 서버는 다시 을 DNS , Client DNS co.kr
관장하는 서버에 을 질의하게 된다 이 질의를 받은 서버는 DNS www.tt.co.kr . DNS
을 보고 이 도메인을 관장하는 서버는 이라는 것을 알려주게 되고 tt.co.kr DNS ns1.tt.co.kr
이 응답을 받은 서버는 최종적으로 에게 을 질의하여 Client DNS ns1.tt.co.kr www.tt.co.kr
이라는 주소를 알게 되어 이 주소를 요청한 에게 알려주게 된다 211.47.65.1 IP PC .
참고로 이와 같이 서버부터 시작해서 위임 권한이 있는 각 서버로 내려오면서 root DNS
반복적인 질의를 하는 방법을 이라 한다 recursion .
그림 의 예 < 1> DNS recursion
서버로부터 주소를 받은 는 자신의 라우팅 정보에 따라 이 요구를 에 Client DNS IP PC PC
설정되어 있는 게이트웨이 즉 라우터로 넘긴다 이 요청을 받은 라우터는 라우터 자신의 , .
라우팅 프로토콜에 따라 가장 최적화된 비용이 적은 여러 라우터를 경유하여 접속하려는 ( )
서버가 위치한 최종 라우터까지 다다르게 된다 이 경로는 자신의 윈도우즈 의 경우 도 . PC
스 프럼프트에서 목적지 나 리눅스등의 유닉스 계열의 서버일 경우 tracert -d “ ”
목적지 로 확인할 수 있다 "traceroute -n " .
내부 네트워크에서의 통신원리
이제 해당 서버가 있는 라우터에서부터는 구간이므로 앞에서 이야기한대로 가 LAN ARP
작동하게 된다 이 부분을 아래와 같이 간단히 도식화하였고 라우터 하단에는 아래와 같이 .
각각의 주소에 해당하는 주소가 각각 IP MAC 192.168.1.1(AA:AA), 192.168.1.2(BB:BB),
인 시스템이 있다고 약식으로 가정하였다 192.168.1.3(CC:CC) .
그림 내부 네트워크 구성도 < 2>
만약 라우터를 통해 접속하려는 요구가 서버인 이라면 여기에서부터 가 A 211.47.65.1 ARP
작동하게 된다 그런데 구간에서는 서버의 주소를 알아야 통신을 할 수 있는데 . , LAN MAC ,
라우터는 의 주소를 아직 모르기 때문에 라우터에서는 밑단의 네트워크에 211.47.65.1 MAC
대해 인 서버는 주소를 알려 달라는 패킷 이 패킷에는 라 211.47.65.1 MAC Broadcasting (
우터의 소스 주소와 소스 정보를 포함하고 있다 을 보내게 된다 이 패킷은 라우터 IP MAC .) .
하단의 모든 서버들이 받게 되며 이 패킷의 목적지 가 자신이 아닌 나 서버는 이 요 IP B C
청에 대해 응답하지 않으며 이 요청을 받은 서버 가 는 자신의 주소 A (IP 211.47.65.1) MAC
를 적은 패킷을 라우터에게 즉 요청을 한 라우터에게만 로 응답하게 된다 이 Unicast( , arp ) .
렇게 해서 라우터와 서버는 서로의 정보를 알게 되었으므로 드디어 통신을 할 수 A MAC
있게 되었다 아래는 실제 로컬 랜상의 가 실시간으로 하고 있음을 . arp broadcasting
로 캡처한 예이다 아래에서 보는 것처럼 요청 은 tcpdump . arp (arp who-has)
을 하지만 응답 은 즉 를 요청한 에게만 응답 Broadcasting arp (arp reply) Unicast( arp IP )
하는 것을 알 수 있다 참고로 아래 그림에서 를 하는 패킷이 하나가 아니라 몇 . arp reply
개 있는 것은 이 시스템의 환경이 이기 때문이다 이에 대해서는 아래에서 다시 설 dummy .
명하기로 한다.
그림 를 로 잡은 모습 < 3> arp broadcast tcpdump
와 ARP CACHE Gratuitous ARP
그런데 이렇게 한 번 접속할 때마다 매번 을 하고 를 해야 한다면 , arp broadcasting reply
그만큼 불필요한 프로세스가 발생하게 되고 많은 오버헤드가 유발될 것이다 따라서 라우터 .
및 서버등 각 장비에서는 와 를 한 후에는 이 정보를 바로 폐기하지 않 arp broadcast reply
고 일정 시간동안 캐시를 하게 된다 기종과 계열에 따라 다소의 차이는 있지만 많은 데이 .
터의 교환이 있는 라우터는 통상 시간 서버는 초 동안 캐시를 하게 된다 리눅스의 경 4 , 60 .
우 현재 시스템에서의 캐시는 아래와 같이 확인 결과 초로 설정되었다는 것을 알 수 있 60
으며 튜닝 으로 이 값을 적절히 조절할 Soft Kernel (sysctl -w kernel_parameter=value)
수 있다.
# sysctl -a|grep gc_stale_time
net.ipv4.neigh.eth0.gc_stale_time = 60
net.ipv4.neigh.lo.gc_stale_time = 60
net.ipv4.neigh.default.gc_stale_time = 60
현재 리눅스 시스템의 캐시정보는 아래와 같이 를 입력하면 된다 arp arp -a .
그림 캐시 정보 확인 < 4> arp
아래와 같이 라우터에서도 를 캐시하고 있는 것을 확인할 수 있다 arp .
그림 라우터의 캐시 < 5 > arp
여기에서 주의할 점은 는 내부 에서만 의미가 있으므로 라우터를 벗어난 , arp LAN WAN
구간에서는 의미가 없으며 구간에서도 브로드 캐스팅 도메인 영역에서만 의미가 있다 LAN
는 것이다 따라서 캐시는 해당 서버에 접근하는 모든 클라이언트나 서버에 대해서 캐 . arp
시하는 것이 아니라 로 되어 있을 경우 해당 영역 위의 경우 C Class netmask (
대역 만 캐시하는 것을 볼 수 있다 가끔 여러분의 서버나 의 이더넷 카드 211.47.65.0 ) . PC
를 변경하였을 때 바로 인식이 되지 않고 빠르면 몇 분 길게는 몇 시간까지 기다린 후에야 ,
네트워크가 다시 작동하는 것을 경험해 보았을 것이다 이를테면 이더넷 카드를 기존의 .
에서 계열로 바꾸었고 커널에서도 잘 인식이 되었다 모듈도도 해 보 RealTek 8139 3com , .
고 커널에 정적으로 포함시켜 보기도 하고 분명 시스템에서는 정상적으로 이더넷 카드를 ,
인식하고 설정도 전혀 문제가 없는데 네트워크가 작동하지 않는 경우가 있다 왜 그럴까 , . ?
이제 여러분은 이 이유를 알 수 있을 것이다 그렇다 바로 캐시 때문이다 앞에서 라우 . . arp .
터는 평균 시간정도 를 캐시한다고 말했다 따라서 이더넷 카드를 변경했다면 해당하 4 arp .
는 에 대한 주소가 변경되었는데 라우터에서는 이전의 정보를 캐시하고 있는 것 IP MAC ,
이다 즉 의 주소를 이 아닌 이전의 으로 인식하고 있는 . , 211.47.65.1 MAC 3com RealTek
것이다 따라서 외부에서 라우터를 통해 로 접속 요구가 들어왔을 때 라우터는 . 211.47.65.1
이전의 정보인 주소를 가지고 있는 서버를 찾는데 이미 은 AA:AA MAC , 211.47.65.1
의 주소인 로 변경되었고 기존의 주소는 존재하지 않기 3com MAC HH:HH AA:AA MAC
때문에 접속할 수 없게 되는 것이다 만약 이더넷 카드를 변경 후 바로 네트워크가 되었다 .
면 다행히 캐시가 작동하지 않았거나 캐시 시간이 짧았기 때문이었을 것이다 그런데 arp .
캐시 때문에 캐시가 업데이트 될 때까지 무작정 기다리기만 해야 한다면 너무 불합리 arp
하지 않은가 당장 서비스도 중지없이 해야 하는데 말이다 ? .
이를 위해서는 라는 것을 사용하면 된다 는 로컬 랜상의 Gratuitous arp . gratuitous arp
캐시 정보를 업데이트하는 로서 이를 실행하면 모든 캐시 정보를 바로 업데이트 arp arp
할 수 있다 리눅스에서는 라는 실행파일을 이용하면 되며 이 실행 파일은 클러 . send_arp
스터링 패키지인 라는 패키지에 포함되어 있다 piranha .
사용 방법은 인데 만약 send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr ,
디렉토리에 실행 파일이 있고 의 정보를 기존의 /usr/sbin send_arp 211.47.65.1 MAC
에서 로 변경하여 이 정보를 업데이트하려면 아래와 같이 실행하면 될 것이 AA:AA HH:HH
다.
# /usr/sbin/send_arp 211.47.65.1 HHHH 211.47.65.255 ffffffffffff
위와 같이 실행하면 즉 대역의 서버중 에 대한 211.47.65.255 211.47.65.0 211.47.65.1
캐시를 가지고 있는 모든 서버에 대해 의 주소는 로 업데이 arp 211.47.65.1 MAC HH:HH
트하라고 브로드 캐스트하는 것이다 이를 실행하면 라우터를 포함하여 모든 네트워크 장비 .
가 캐시를 업데이트하며 네트워크가 다시 작동하는 것을 확인할 수 있을 것이다 참고 arp .
로 자신의 정보는 아래와 같이 를 실행하면 확인할 수 있다 MAC ifconfig .
그림 주소의 확인 < 6> MAC
실제로 를 이용하면 한 서버가 다운시 다른 서버가 대신 서비스하는 클러스 gratuitous arp
터링의 용도로도 사용되며 매우 유용한 프로그램이라 할 수 있다 이외 와 관련하여 . ARP
라는 것도 있는데 이는 가 기존의 캐시를 다른 정보로 업데이 Unarp , Gratuitous arp arp
트하는 것이라면 는 기존의 캐시가 있는 시스템이 있다면 단지 캐시를 삭제 Unarp arp arp
만 하는 것이다 따라서 접속할 때마다 가 변하는 등의 의 경우는 접속을 끊 . IP ADSL DHCP
을 때 를 하고 를 할당받아 네트워크를 시작할 때에는 Unarp Broadcasting , IP Gratuitous
를 실행하면 캐시로 인하여 접속이 되지 않는 문제는 해결이 될 것이다 arp arp .
이렇듯 는 매우 유용하지만 다른 한편으로 악용될 경우에는 쉽게 다른 시스 gratuitous arp
템을 무력화시킬 수 있는 무서운 공격 프로그램이 될 수 도 있다는 점을 양지하기 바란다.
와 허브 Switch Dummy
이번에는 로컬구간에서의 통신에 대해 알아보도록 하자.
많은 사람들은 네트워크의 보안을 위해 더미 허브대신 스위치를 사용하라고 권장한다 LAN .
과연 그런가 실제로 스위치는 애초에 디자인시 보안을 고려했기 보다는 를 ? Performance
염두해 두고 개발된 것인데 어떻게 하다보니 우연히 더미 허브에 비해 보안에 좋 , (Dummy)
은 것 뿐이지 반드시 그러한 것은 아니다 그럼 여기서 잠깐 더미허브와 스위치의 차이에 . ,
대해 알아보도록 하자 더미 허브와 스위치는 일반적으로 차선의 개념과 연관지어 생각하면 .
쉽다.
그림 의 개념 < 7> Switch
스위치의 경우 위와 같이 이 차선이면 도 차선인 개념이다 반면에 더미 허브 input 4 output 4 .
는 은 차선이지만 은 차선인 개념이므로 당연히 에서 병목현상이 발 input 4 output 1 output
생할 수밖에 없게 된다 이때 병목 현상으로 인하여 동시에 에 도달하려면 필연적으 . output
로 충돌 이 생기게 되어 결국 속도 저하가 발생하게 된다 리눅스에서 특정 인터 collision( ) .(
페이스의 여부는 로 확인할 수 있다 그런데 이러한 속도 저하보다는 collision ifconfig .) ,
좀 더 중요한 차이점이 있다 즉 스위치는 지정된 로 패킷을 바로 포워딩해 주지만 더미 . , IP
허브는 모든 패킷을 모든 포트에 한다는 것이다 그럼 여기에서 각각 더미허브 broadcast .
및 스위치 환경에서 데이터가 통신하는 경로에 대해 다시 생각해 보자.
# Dummy
더미 환경에서 서버와 서버가 과 같은 통신을 한다면 서버에 (dummy) A C telnet TCP , A
서는 제일 먼저 을 하게 된다 이때 이 요청은 이므로 ARP Broadcasting . Broadcasting B,
모두에게 전달된다 이중 서버는 목적지 가 자신의 가 아니므로 이 요청에 C . B ARP IP IP
응답하지 않고 서버는 목적지가 자신의 이므로 이 요청에 대하여 요청을 한 서버에 C IP A
게 를 한다 그러나 환경에서는 모든 패킷이 하므로 서 ARP reply . dummy broadcast B
버에서도 서버의 응답을 캡처할 수 있다 이는 위의 그림에서 확인하였 C unicast .( tcpdump
다 와 간에 와 를 한 후에는 통신을 하려고 하므로 본격적 .) A C ARP broadcast reply TCP
인 데이터 교환을 하기 전에 과정을 선행하게 된다 TCP 3 Way handshake .
그림 < 8> TCP 3 way handshake
과정은 위 그림에서와 같이 서버와 클라이언트간에 위 가지 절차 tcp 3 way handshake 3
를 거친 후에야 연결이 성립되어 데이터가 교환된다는 것을 익히 알고 있을 것이다 그런 .
데 에서는 위 뿐만이 아니라 이후의 모든 데이터 , dummy 3 way handshake Connection
교환 역시 하게 된다 아래에서는 서버에서 서 broadcast . 211.47.65.106 www35.tt.co.kr
버로 접속시 반응하는 패킷을 서버에서 로 잡은 예이다 telnet www35.tt.co.kr tcpdump .
에서 보는 것처럼 먼저 통신이 되어 서버의 정보를 교환한 후에야 비로 tcpdump arp MAC
서 가 이루어지는 것을 확인할 수 있을 것이다 만약 한번 시도를 한 3 way handshake .
후에는 캐시가 있으므로 캐시가 있는 상태에서 재시도를 하면 요청과 절차 arp arp reply
가 없이 바로 가 이루어지는 것을 그림 에서 확인해 볼 수 있다 3 way handshake < 10> .
그림 가 없을때의 < 9> arp cache tcpdump
그림 가 있을때의 < 10> arp cache tcpdump
# switch
환경에서 서버와 서버가 과 같은 통신을 한다면 서버에서는 switch A C telnet TCP A C
서버의 주소를 알기 위해 먼저 을 한다 이때 이 요청은 MAC ARP Broadcasting .
이므로 모두에게 전달된다 이중 서버는 목적지 가 자신이 아 Broadcasting B, C . B ARP IP
니므로 이 요청에 응답하지 않고 서버는 목적지가 자신의 이므로 이 요청에 대하여 , C IP
요청을 한 서버에 를 한다 여기까지는 스위치나 환경이 동일하다 그 A ARP reply . dummy .
러나 환경에서는 이외의 모든 패킷이 하지 않으므로 switch arp broadcast broadcast B
서버에서는 서버의 응답을 캡처할 수 없다 와 간에 와 C unicast . A C ARP broadcast
를 한 후에는 통신을 하려고 하므로 본격적인 데이터 교환을 하기 전에 reply TCP TCP 3
과정을 거치게 된다 와 간에 서로의 정보를 교환한 후에는 서 Way handshake . A C MAC
로의 주소를 알기 때문에 뿐만이 아니라 이후의 모든 MAC 3 way handshake connection
데이터 교환 역시 하지 않고 와 간에만 통신을 하게 되며 에서는 와 broadcast A C B A C
간의 통신을 엿볼 수 없게 된다.
즉 환경에서는 요청과 응답 , dummy (1) arp
(2) tcp 3 way handshake
데이터 교환 (3)
이 모든 과정이 되어 에서도 와 간의 통신을 엿볼 수 있으나 broadcasting B A C
환경에서는 요청만이 하며 switch (1) arp broadcasting
응답 (2) arp
(3) tcp 3 way handshake
데이터 교환 모두 와 간에 로 작동하기 때문에 (4) A C unicast
에서는 와 간의 통신을 엿볼 수 없게 된다 B A C .
여기에서 처럼 자신을 출발지 또는 목적지로 하지 않은 와 간의 통신을 엿보는 일 B A C (?)
련의 행위을 스니핑 한다고 한다 (Sniffing) .
스니핑(Sniffing)
그렇다면 스니핑은 어떻게 가능한가?
크게 두 가지 이유로 가능하다 첫 번째는 위에서 본 것처럼 환경에서는 모든 패킷 . dummy
을 하여 직접적인 통신과는 관계없는 다른 나 서버에서도 다른 시스템의 패 broadcast PC
킷을 캡처할 수 있다는 특성을 이용한 것이고 두 번째는 인터넷의 표준 프로토콜로 사용중 ,
인 의 전송 방식이 암호화하지 않은 평문 를 사용한다는 점을 이용한 것 TCP/IP Plain text( )
이다 그렇다고 해서 방식으로 한다고 바로 모든 패킷을 스니핑 . Plain text broadcasting
할 수 있는 것은 아니다 왜냐하면 기본적으로 목적지 가 자신의 가 아닌 패킷은 이더 . IP IP
넷에서 패킷을 드롭 하는 특성이 있기 때문이다 이처럼 스니핑을 하려면 자신의 목적 (drop) .
지가 아닌 패킷도 받아들여야 하는데 그렇게 하려면 인터페이스가 또는 , promiscuous (
모드로 작동하도록 설정하여야 한다 모드는 우리말로 무차별 모드 라 promisc) . promisc “ ”
고도 하는데 모드로 설정되면 이더넷에서 패킷을 드롭하지 않고 모든 패킷을 다 , promisc
받아들이게 되어 스니핑이 가능하게 된다 리눅스에서 인터페이스가 모드인지 여 . promisc
부를 알 수 있는 명령어는 앞에서 본 것처럼 라는 명령어로 확인 가능하다 이때 ifconfig .
아래와 같이 라는 문자열이 보이면 인터페이스는 모드로 되어 있는 것 PROMISC promisc
인데 모드를 수동으로 설정하려면 , promisc
와 같이 하면 되고 설정을 해제하려면 # ifconfig eth0 promisc ,
로 실행하면 된다 # ifconfig eth0 -promisc .
그림 설정 여부 확인 < 11> promisc
특별한 이유가 없다면 평상시에는 모드로 설정되어 있을 필요가 거의 없으므로 만 promisc
약 자신의 시스템이 모드로 설정되어 있다면 스니핑 여부를 주의깊게 검토해 보아 promisc
야 할 것이다 그러나 시스템에 따라 자동으로 로 설정하는 경우도 있으니 . promisc
로 설정되어 있다고 해서 반드시 스니핑이 작동하고 있는 것은 아니라는 것을 참고 promisc
하기 바란다.
스니핑에 대한 대책
그렇다면 이에 대한 대책은 무엇인가 가지 정도의 방법을 대안으로 제시할 수 있겠다 ? 3 .
첫 번째는 로 전송되는 대신 암호화 전송 프로토콜을 사용하는 것이다 , Plain text TCP/IP .
이의 대표적인 예가 대신 대신 웹서버 등을 사용하는 것이 그 telnet SSH, http https(SSL )
예이다 여기서 잠깐 에 대해 이야기하고자 한다 적지 않은 사람들이 보안 웹서 . SSL . SSL
버를 설치하면 마치 방화벽처럼 모든 보안에 완벽해 지는 것으로 오해하는 경우가 있는데,
은 번 포트를 사용하는 프로토콜 역시 에 속하므로 평문으로 전송되어 SSL 80 http TCP/IP
스니핑 될 수 있기 때문에 기존의 대신 암호화 전송 프로토콜인 을 사용하는 것 http SSL
뿐이지 다른 것은 아닌 것이다 아마도 보안 웹서버라는 이름 때문에 다소 혼동하는 것이 .
아닌가 한다.
두 번째는 앞에서 본 것처럼 을 하는 대신 스위치를 사용하는 것이다 broadcasting dummy .
세 번째는 기업간 통신시 암호화된 통신을 하는 가상 사설망인 VPN(Virtual Provate
을 사용하는 것이다 Network) .
이 중 가장 근본적인 방법은 첫번째로 제시한 암호화 전송 프로토콜을 사용하는 것이다.
여기에서 잠깐 두 번째 방법으로 제시한 대신 스위치에 대해 알아보도록 하자 앞 dummy .
에서 본 대로 스위치를 사용할 경우 초기 요청시에만 하고 이후 arp broadcast broadcast
에는 모두 로 통신하므로 상대적으로 스니핑에 안전하다는 것을 이해했을 것이다 unicast .
하지만 과연 스위치를 사용한다면 스니핑에 안전할까 답은 결코 그렇지 않다 이다 왜냐 ? . . “ ”
하면 쉽지는 않지만 스위칭 환경에서도 스니핑을 할 수 있는 방법이 있기 때문이다 바로 .
의 특성을 이용하여 아래와 같은 몇 가지 방법이 가능하다 arp .
스위치 환경에서도 가능한 스니핑 기법
(1) MAC Flooding
스위치에서는 각각의 포트에 해당하는 물리적인 주소를 기억하고 있는데 이 메모리에 MAC
는 어느 정도의 한계치가 있다 이러한 스위치의 특성을 이용하여 위조된 을 지속적으 . MAC
로 발생시켜 스위치의 테이블을 시키는 방법으로 정보가 되면 스 ARP Flood MAC Flood
위치는 마치 처럼 모든 포트에 하게 된다 보안적인 용어로 이러한 것을 dummy broadcast .
이라 한다 fail open . “ “
(2) ARP Spoofing
은 스니핑하고자 하는 서버인 것처럼 을 위조한 패킷을 하여 ARP Spoofing MAC Broadcast
트래픽을 포워딩하는 것을 말하는데 앞의 그림 와 같은 스위치 환경에서 서버가 와 , 2 B A C
서버간의 통신을 스니핑 할 수 있는 방법으로 아래와 같이 의 원리만 알면 아주 쉽게 ARP
스니핑 할 수 있다 서버에서 서버에게 의 주소가 가 아니라 . B A 211.47.65.3 MAC CC:CC
서버의 주소인 라는 패킷을 발송하고 서버에는 의 주 B MAC BB:BB , C 211.47.65.1 MAC
소가 가 아니라 서버의 주소인 라는 패킷을 발송하는 것이다 그렇 AA:AA B MAC BB:BB .
게 되면 서버와 서버는 이 정보를 의심없이 받아들여 정보를 갱신한 후 와 간 통신 A C A C
시 모든 패킷은 서버로 보내지게 되며 서버는 모든 패킷을 받은 후 원래의 서버로 포 B B
워딩만 해 주면 되는 것이다 이때 서버의 로 설정되어 있어야 원 . B net.ipv4.ip_forward=1
래의 서버로 패킷을 포워딩하게 되며 와 서버는 정상적인 데이터 전송이 되므로 패킷이 A C
를 거쳐간다는 사실을 알 수 없게 되는 것이다 B .
(3) ARP Redirect
역시 과 비슷한 방법인데 자신이 마치 인 것처럼 ARP Redirect ARP Spoofing , Gateway
위조된 을 하여 모든 트래픽이 자신을 통과하게 하는 방법이다 즉 와 MAC Broadcast . , A C
서버에게 주소인 의 주소가 라우터의 주소인 Gateway 211.47.65.254 MAC MAC RR:RR
이 아니라 서버의 주소인 라는 패킷을 하는 것이다 그렇게 되 B MAC BB:BB broadcast .
면 로컬 랜상에 있는 서버들은 이 정보를 아무런 의심없이 받아들여 캐시 정보를 갱신한 후
게이트웨이로 보내는 모든 패킷을 가 아니라 서버인 로 보내게 211.47.65.254 B 211.47.65.2
되며 서버는 모든 패킷을 받은 후 원래의 게이트웨이인 로 포워딩만 해 , B 211.47.65.254
주면 되는 것이다 이때 서버의 로 설정되어 있어야 원래의 게이 . B net.ipv4.ip_forward=1
트웨이로 패킷을 포워딩하게 되며 와 서버는 정상적인 데이터 전송이 되므로 패킷이 A C B
를 거쳐간다는 사실을 알 수 없게 되는 것이다.
(4) MAC Duplicating
만약 서버에서 서버의 트래픽을 스니핑하고 싶다면 서버에서 서버의 주소와 B A B A MAC
같은 정보로 설정을 하는 방법이 바로 이다 를 이용하면 이 MAC MAC Duplicating . ifconfig
는 어렵지 않게 설정할 수 있는데 이를테면 의 주소가 인 , eth0 MAC 00:50:8B:9A:1B:1B
경우 이를 와 같이 설정하고자 한다면 먼저 으 AA:AA:AA:AA:AA:AA ifconfig eth0 down
로 인터페이스를 다운시킨 후 와 eth0 ifconfig eth0 hw ether AA;AA:AA:AA:AA:AA up
같이 실행하면 인터페이스의 정보를 변경할 수 있다 이러할 경우 스위치를 혼 eth0 MAC .
란시켜 두 포트 모두 같은 주소를 가진 것처럼 인식하게 되며 스위치는 서버로 보 MAC A
낼 트래픽을 와 모두에게 발송하게 되는 것이다 데이터는 두 포트 모두에게 보내어지 A B .
므로 서버에서는 포워딩을 설정할 필요가 없다 B IP .
실제로 위와 같이 스위치 환경에서 스니핑하는 것은 그리 어렵지 않으며
나 등과 같은 관련 툴을 이용하면 어 hunt dsniff(http://www.monkey.org/~dugsong/dsniff/)
렵지 않게 구현할 수 있다.
스니핑 차단하기
이제 스위치 환경도 결코 스니핑에 안전하지 않다는 사실을 알았을 것이다 그렇다면 스위 .
치 또는 환경에서 어떻게 보안을 강화할 수 있을까 아래의 몇 가지 방법을 대안으 dummy ?
로 제시할 수 있다.
(1) IP Flitering
스위치에서 제공하는 기능을 사용함으로써 각각의 포트에서 오가는 트래픽을 IP Filtering
필터링 할 수 있다 그러나 이 기능을 제공하는 스위치에서만 가능하며 매번 포트가 바뀔 .
때마다 수작업으로 설정해 주어야 하므로 많은 수고가 따르게 된다.
(2) Port security
만약 스위치에서 기능을 지원할 경우 나 을 예방 Port security MAC Flood MAC Spoofing
할 수 있는 방법으로 각각의 포트에 물리적인 주소를 정적 으로 설정하는 것이 MAC (Static)
다 각종 기반의 스니핑에 가장 확실한 방법이라 할 수 있지만 과연 이렇게 하는 곳이 . ARP
얼마나 될까는 의문이다.
원격지 서버의 스니핑 모니터링 프로그램
특정 서버에서 스니핑이 작동하고 있는지 리눅스의 경우 를 실행시 가 설 ifconfig PROMISC
정 되었는지 여부로 확인할 수 있다고 하였다 그런데 관리하는 서버가 여러 대라면 매번 . ,
로그인하여 로 설정 여부를 확인하겠는가 거기다가 만약 실행 ifconfig PROMISC ? ifconfig
파일 자체가 변조되어 결과를 신뢰할 수 없다면 이는 아무런 의미가 없게 되는 ifconfig ?
것이다 이를 위해 원격에서도 특정 서버의 스니핑 작동여부를 체크할 수 있는 과 . Sentinel
라는 프로그램을 소개하고자 한다 을 설치하려면 미리 패킷 캡처 라 AntiSniff . Sentinel
이브러리인 과 가 설치되어야 하는데 각각 Libnet 1.0 libpcap ,
와 (http://www.packetfactory.net/Projects/libnet) (ftp://ftp.ee.lbl.gov/libpcap-0.4.tar.Z)
에서 다운로드 받아 압축 해제 후 압축이 풀린 디렉토리에서 ./configure; make ; make
로 설치하면 된다 그리고 은 install . Sentinel
에서 다운로드 할 수 있으며 다운로드후 http://www.packetfactory.net/Projects/sentinel/
압축 해제를 하고 압축이 풀린 디렉토리에서 로 컴파일하여 설치하면 된다 현재 make all .
이 원격지 시스템에서 스니핑 여부를 감지하는 방법은 가지가 있는데 이 방법은 Sentinel 3 ,
각각 등이다 참고로 이 방법은 를 이용한 방 DNS test, Etherping test, ARP test . ARP
법이므로 같은 네트워크 세그먼트에 속해 있어야만 탐지의 의미가 있다는 점을 양지하기 바
란다.
먼저 각각의 방법이 가능한 원리에 대해 간단히 살펴보면 우선 의 경우 목적지 , DNS test
서버에 위조된 연결 요청을 보내어 일반적인 스니핑 프로그램이 요청한 시스템의 주소 , IP
를 역리졸브 한다는 특징을 이용하여 트래픽을 감시하여 스니 (Inverse DNS lookup) DNS
핑 여부를 감지하는 방법이다 는 목적지에 패킷을 보낼 때 목적지의 . Etherping test ping
는 맞지만 목적지의 주소는 존재하지 않는 정보로 위조하여 IP MAC Icmp Echo Packet
을 보내어 응답이 오는지 여부를 감시하는 방법으로 대부분의 정상적인 시스템에서는 존재
하지 않는 정보이기 때문에 패킷에 대해 응답하지 않지만 가 설정된 MAC promisc mode
시스템에서는 이와 관계없이 응답을 한다는 특징을 이용하여 감시하는 방법이다 마찬가지 .
로 역시 는 목적지의 로 설정하지만 목적지의 주소를 다르게 하여 ARP test IP IP MAC
대신 요구를 보내는 방법으로 모드가 아닌 경우에는 패킷이 목적지까 icmp ARP Promisc
지 갈 수 없으므로 목적지에서는 응답하지 않지만 모드인 경우에는 모든 패킷을 Promisc
받아들이므로 결국 응답한다는 특징을 이용하여 스니핑 여부를 감시하는 방법이다 각각의 .
방식에 대한 실행 예는 아래와 같다.
테스트 ./sentinel -a -t 211.47.65.4 # ARP
테스트 ./sentinel -d -f 1.1.1.1 -t 211.47.65.4 # DNS
테스트 ./sentinel -e -t 211.47.65.4 # Etherping
개의 테스트를 동시에 수행 ./sentinel -t 211.47.65.4 -f 1.1.1.1 -d -a e # 3 –
위와 같이 실행시
Results: 211.47.65.4 tested positive to etherping test.
와 같이 탐지 결과가 가 나오면 모드로 설정되었다는 의미이므로 해당 positive Promisc
인터페이스의 여부를 조사하여야 한다 그런데 한 시스템에 대해 각각의 테스트 PROMISC . ,
를 동시에 실행했을 때 결과가 각기 다르게 나오는 경우가 있는데 이는 리눅스의 커널 버 ,
전에 따라 종종 발생하는 현상으로 세 가지 방법중에 어느 하나라도 라는 결과가 positive
나온다면 반드시 스니핑 작동 여부를 확인하기 바란다.
아울러 의 경우 에서 다운로드 Antisniff http://www.securitysoftwaretech.com/antisniff/
가능하며 리눅스 버전과 윈도우 버전의 프로그램도 사용할 수 있는데 테스트 하는 원리는 ,
위의 과 비슷하며 추가적으로 라는 재미있는 방법이 있는데 이 방 Sentinel Latency test ,
법은 스니핑이 작동시 모드로 설정되어 있을 경우에는 로컬 네트워크상의 모든 트 promisc
래픽을 받아들이느라 시스템의 로드가 전반적으로 높아진다는 점을 이용해 불필요한 쓰레기
트래픽을 전송하여 시스템의 응답 시간이 길어지는지 여부를 조회하는 방법으로 아직까지는
신뢰할 수는 없는 방법이며 계속적으로 개선중인 기능이다 100% .
윈도우 버전의 의 경우 모니터링하고자 하는 대역을 지정하여 한꺼번에 검사 Antisniff IP
가 가능하고 검사 결과에 대해 각종 통계도 볼 수 있으며 얼마의 주기로 테스트를 할 것 , ,
인지를 시간대별 날짜별 주별로 정할 수 있는 예약 기능 및 검사 결과가 변경시 메일로 , ,
발송하거나 음악이 나오게 하는 등의 알람 기능도 있어 편리하게 사용이 가능하다.
아울러 와 관련된 프로그램으로 작지만 강력한 프로그램인 라는 프로그램을 arp ARPWatch
소개하고자 한다 앞에서 를 실행하였을때 실시간으로 주소와 . tcpdump -e arp IP MAC “ ”
정보가 되는 것을 확인하였을 것이다 broadcast . 이 프로그램은 이러한 ARP 트래픽을 실시
간으로 모니터링하여 MAC 주소와 IP 간의 매칭을 감시하는 프로그램으로서 만약 현재
의 ARP 정보가 데이터베이스에 저장되어 있는 정보와 다르 ARP 거나 새로운 MAC 주소가
추가/확인시에는 해당하는 내용을 지정된 관리자에게 메일로 통보하게 된다 프 . arpwatch
로그램을 이용하면 MAC 주소나 ARP를 이용하는 공격에 대한 대응 및 네트워크 관리에
매우 유용하다.
암호화 전송 프로토콜 사용하기
앞에서 가 얼마나 취약한지 그리고 이를 위한 대책이 어떤 것이 있는지 알아보았 TCP/IP
다 물론 의 취약점을 개선하기 위해 등 새로운 개발이 가시화되고 있지만 현 . TCP/IP ipv6
재의 상태에서 가장 확실한 방법은 암호화 전송 프로토콜을 사용하는 것에는 모두 동의할
것이다 이는 대신 를 대신 를 사용한다고 말했었다 그렇다면 . telnet ssh , http https . ftp,
등 다른 프로토콜은 어떻게 할 것인가 만약 만 사용한다면 그냥 를 smtp, pop3 ? telnet ssh
사용하기만 하면 되겠지만 한 서버에서 과 등을 함께 사용한다면 어느 하 telnet ftp, pop3
나의 서비스만 암호화하는 것은 그리 큰 의미가 없다 어차피 자체가 취약한 것이 . TCP/IP
므로 암호화 전송 프로토콜을 사용하려면 모든 서비스에 대해 암호화 전송 프로토콜을 사용
해야 하기 때문이다 그래서 이를 위해 기존 기반의 서비스에 암호화 전송 프로토 . TCP/IP
콜을 사용하려면 아래와 같은 두 가지 방법이 가능하다.
를 이용한 암호화 (1) sslwrap
의 포트전송 기능을 이용한 암호화 (2) SSH
를 이용한 암호화 (1) sslwrap
는 나 등의 서비스를 감싸 을 이용하여 모든 sslwrap pop3 imap, smtp TCP TSL/SSL
데이터 전송을 암호화하는 간단한 유닉스 서비스로서 기존의 서비스를 다시 설치할 TCP
필요없이 어렵지 않게 사용이 가능하다 를 이용하려면 이나 를 설 . sslwrap openssl ssleay
치하여야 하는데 여기에서는 을 사용하는 방법을 알아보도록 하자 , openssl .
먼저 에 접속하여 최신의 을 다운로드하여 설치할 서버에 http://www.openssl.org/ openssl
업로드한다.
또는 설치할 서버에서 직접 lynx http://www.openssl.org/source/openssl-0.9.6b.tar.gz “ ”
나 로 다운로드 받아도 된 wget http://www.openssl.org/source/openssl-0.9.6b.tar.gz “ ”
다 다운로드 후 압축 해제하여 압축이 풀린 디렉토리에서 아래와 같이 실행하여 컴파일하 .
여 설치를 한다.
[root@www ~/openssl-0.9.6b]# ./config ; make; make test; make install
이번에는 을 설치할 차례이다 sslwrap .
역시 나 "lynx http://www.rickk.com/sslwrap/sslwrap.tar.gz"
으로 다운로드한 후 압축 해제하여 "wget http://www.rickk.com/sslwrap/sslwrap.tar.gz"
만 실행하여 컴파일하면 된다 컴파일후 생성된 파일을 디렉토리 make . sslwrap /usr/sbin/
레 복사한다 혹 컴파일이 잘 안되는 경우에는 에서 자신의 버전에 맞 . http://rpmfind.net/
는 적당한 파일을 다운로드하여 설치해도 된다 rpm .
이번에는 인증서를 생성할 차례이다 물론 베리사인이나 등 공인된 . Thawte CA(Certificate
Authority) 기관에서 일정정도 비용을 지불하고 를 생성후 인증서를 구입하는 방법도 , CSR
있지만 여기에서는 자기 자신이 사인한 인증서를 발급하는 방법에 대해 알아보도록 하자.
인증서를 발급하는 명령어는 아래와 같다.
# openssl req -new -x509 -nodes -out /usr/local/include/sslwrap.pem -keyout
/usr/local/include/sslwrap.pem -days 365
이 명령어를 한줄에 이어서 입력하기 바란다 아래는 위와 같이 실행시 보이는 화면이다 . .
Using configuration from /usr/share/ssl/openssl.cnf
Generating a 1024 bit RSA private key
.....++++++
..++++++
writing new private key to '/usr/local/include/sslwrap.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Today & Tomorrow
Organizational Unit Name (eg, section) []:Net-Center
Common Name (eg, your name or your server's hostname) []:test1.tt.co.kr
Email Address []:antihong@tt.co.kr
위에서 굵게 표시된 부분은 각자의 상황에 맞게 적절히 입력하여야 하는 내용이다.
각각에 대해 잠깐 알아보도록 하자.
Country Name (2 letter code) [AU]:KR
국가 이름을 코드로 입력한다 한국은 이라 입력한다 --> . KR .
State or Province Name (full name) [Some-State]:
주는 존재하지 않으므로 적당히 입력하거나 그냥 엔터를 입력한다 --> .
Locality Name (eg, city) []:Seoul
--> 도시이름을 입력한다.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Today & Tomorrow
회사나 조직 기관의 이름을 입력한다 --> , .
Organizational Unit Name (eg, section) []:Net-Center
부서이름을 적절히 입력한다 --> .
Common Name (eg, your name or your server's hostname) []:test1.tt.co.kr
인증서가 설치되는 서버의 받는 메일서버 주소를 입력한다 --> .
만약 여기에서처럼 에 대해 암호화 프로토콜을 사용하려면 이 주소는 아 pop3, smtp
웃룩 익스프레스등의 메일 프로그램에서 보내는 메일서버 또는 받는 메일서버로
입력할 주소이다 등과 같이 자신의 이름을 입력하지 않도록 . Kildong, Hong
주의하기 바란다.
Email Address []:antihong@tt.co.kr
자신의 주소를 입력한다 --> e-mail .
이제 인증서 생성을 끝났으므로 를 나 에 설정할 차례이다 sslwrap inetd xinetd .
먼저 파일을 열어 /etc/services
pop3s 995/tcp
smtps 465/tcp
와 같이 설정되어 있는지 확인하고 없으면 위와 같이 추가한다.
그리고 의 경우 설정 파일에 아래와 같이 추가한다 xinetd xinetd.conf .
service smpts
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = nobody
server = /usr/sbin/sslwrap
server_args = -cert /usr/local/include/sslwrap.pem -quiet -port 25
log_on_failure += USERID
}
service pop3s
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = nobody
server = /usr/sbin/sslwrap
server_args = -cert /usr/local/include/sslwrap.pem -quiet -port 110
log_on_failure += USERID
}
의 경우라면 서비스에 대해 파일에 아래와 같이 설정할 수 있다 inetd pop3s inetd.conf .
pop3s stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/sslwrap
-cert /usr/local/include/sslwrap.pem -port 110
이와 같은 방식으로 다른 서비스도 아래와 같이 설정할 수 있다.
https stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/sslwrap
-cert /usr/local/include/sslwrap.pem -port 80
imaps stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/sslwrap
-cert /usr/local/include/sslwrap.pem -port 143
telnets stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/sslwrap
-cert /usr/local/include/sslwrap.pem -port 23
위와 같이 설정 후 또는 를 재시작하면 변경한 내용이 적용될 것이다 inetd xinetd .
설정한 포트가 열렸는지 아래와 같이 확인한다.
# telnet localhost pop3s
# tenlet localhost smtps
이제 서버에서의 설정은 끝났으므로 메일 클라이언트 프로그램에서 설정할 차례이다.
메일 프로그램에서 받는메일서버 보내는메일서버 를 위에서 설정한 서버이름으 (pop3), (smtp)
로 입력하고 고급 탭에서 보내는 메일서버와 받는 메일서버에 아래 그림과 같이 보안연결 , “
필요 를 선택하면 와 번 포트가 설정되는 것을 확인할 수 있다 (SSL) 465 995 . ”
그림 아웃룩 익스프레스 설정 < >
이제 드디어 모든 설정이 끝났다 메일 송수신이 되는지 테스트해 보기 바란다 그런데 메 . . ,
일 프로그램에서 보내고 받기를 클릭하면 아래와 같이 처음 프로그램을 시작할 때마다 경고
메시지가 뜨게 되어 여간 불편하지 않을 수 없다.
그림 공인된 인증서가 아닌 경우 경고 화면 < >
이는 공인된 인증서가 아니라 자기 자신이 사인한 인증서를 발급하였기 때문이며 이러한 경
우에는 다음과 같이 추가적인 작업을 해주면 이 메시지가 나타나지 않도록 할 수 있다.
먼저 인증서 파일인 파일을 열면 /usr/local/include/sslwrap.pem
로 시작해서 -----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE
로 끝나는 부분과 로 시작해서 KEY----- , -----BEGIN CERTIFICATE-----
로 끝나는 부분이 있는데 이 중에서 -----END CERTIFICATE----- , "-----BEGIN
부분만 복사해서 등의 클라이 CERTIFICATE ...... END CERTIFICATE-----" Windows
언트 에 라는 파일로 복사를 한다 그리고 이 파일에서 오른쪽 마우스를 클릭 PC server.crt .
하면 인증서 설치 라는 메뉴가 보이는데 여기에서 인증서 설치 를 실행한다 이후 나오 , . “ ” “ ”
는 화면에서 모두 다음 다음 을 선택 후 마침을 선택하면 에서의 설치가 완료된 --> PC “ “ ” “
다 다음부터는 자체적으로 사인한 인증서를 사용하더라도 경고 화면이 나오지 않는 것을 .
확인할 수 있을 것이다 그럼 실제로 를 사용할 때 실제로 암호화가 되어 스니핑 할 . . pop3s
수 없는지 실제로 테스트해 보도록 하자 각종 리눅스 스니퍼 프로그램을 이용해도 되지만 .
여기에서는 를 이용해 테스트 해 보았다 tcpdump .
먼저 아래와 같이 서버에서 설정하여 연결을 캡처할 수 있도록 준비하고 로 메일을 pop3
받아보도록 하자.
# tcpdump -x host 211.1.1.1 > pop3.txt
이번에는 암호화 전송 프로토콜인 로 패킷을 캡쳐할 수 있도록 준비하고 로 pop3s pop3s
받아보도록 하자.
# tcpdump -x host 211.1.1.1 > pop3s.txt
이 명령어는 메일 클라이언트 프로그램을 실행하는 로부터의 패킷을 진수로 211.1.1.1 16
캡처하여 각각 와 라는 파일로 저장을 한다는 의미이다 이후 캡처한 데 pop3.txt pop3s.txt .
이터를 진수로 표기하는 아스키 코드표로 해석을 하면 된다 진수로 표기하는 아스키 16 . 16
표는 를 참고하기 바란다 http://www.asciitable.com/ .
또는 아래처럼 진수를 아스키로 변환해 주는 프로그램을 이용해서 변환할 수도 16 trans.pl
있다.
#!/usr/bin/perl
while(<>){
s/ //g;
s/([a-fA-F0-9][a-fA-F0-9])/pack("c",hex($1))/eg;
print $_;
}
위와 같이 작성 후 또는 를 하면 아래와 같이 덤프받은 데 perl trans.pl pop3.txt pop3s.txt
이터를 아스키로 변환할 수 있다 물론 아래처럼 깨끗하게 변환은 되지 않지만 파 . pop3.txt
일의 내용을 읽을 수 있다는 것을 확인할 수 있을 것이다 반면에 파일을 변환해 . pop3s.txt
보면 암호화가 되어 거의 어떤 문자인지 알아볼 수 없다는 것을 알 수 있을 것이다.
를 스니핑한 예 # pop3
+OK POP3 test1.tt.co.kr v2001.77 server ready
user user1
+OK User name accepted, password please
pass dkssud
+OK Mailbox open, 2 messages
를 스니핑한 예 #pop3s
E[u@@??Aj
?@.? D57? 霑
뿔 P a?u?8?? ?
ᇹ ? 4?Ti 欠夫
EFv@@??Aj
?@.? w57? 霑
를 이용한 방법에 대해서는 를 참고하기 sslwrap http://www.quiltaholic.com/rickk/sslwrap/
바란다.
의 포트 포워딩 기능을 이용한 암호화 (2) SSH
클라이언트와 서버 연결 구간에는 암호화 통신을 한다는 것을 알고 있다 이 특성을 활 ssh .
용하여 에서 제공하는 포트 포워딩 기능을 이용하면 암호화가 제공되지 않는 프로토콜 ssh
도 쉽게 암호화 전송할 수 있다 쉽게 이야기하면 에서 기존의 서비스를 캡슐로 싸서 . ssh
서비스한다고 생각해도 된다.
포트 포워딩 기능을 이용해 클라이언트와 서버 사이에 암호화를 위한 터널을 구성 ssh ssh
할 수 있는데 이를 구성하기 위한 방법은 로컬포트 포워딩 과 원격포트 포워딩 두 가지 , “ “ ” “
방법이 있다 두 방법 모두 거의 유사한 방법이므로 여기에서는 로컬포트 포워딩 방법에 대 .
해 알아보도록 하자.
클라이언트와 서버간에는 암호화 전송이 되기 때문에 일단 연결을 할 기존의 ssh ssh tcp
서버외에 연결을 할 클라이언트로 사용할 추가적인 한 대의 서버가 더 필요하다 ssh .
아래와 같이 두 대의 서버가 있다고 하자.
서버는 클라이언트 연결을 하여 클라이언트의 연결을 받아 를 이용하여 forward ssh ssh
연결을 포워딩 할 서버이고 서버가 포워딩을 받아 실제로 서비스를 제공할 서 TCP www
버이다.
그림 포트 포워딩서버 구성도 < > ssh
위와 같은 환경에서 하여야 할 일은 먼저 암호화를 할 포트에 대해 터널을 구성하는 ssh
것이다 이는 클라이언트 즉 서버에서 다음과 같은 형식으로 연결을 하면 된 . ( forward) ssh
다.
로컬포트 원격호스트 원격포트 서버호스트 ssh -L : : :SSH
위와 같은 환경에서는 원격 호스트와 서버 호스트가 같으므로 서버에서 단지 SSH forward
와 같이 접속을 하면 된다 아래는 실제 접속 예이다 ssh -L 10110:www:110:www . .
[root@forward /root]# ssh -L 10110:www:110 www
root@www's password:xxxxxx 암호 입력 <---
[root@www /root]#
이 상태에서 와 서버에서 각각 을 해 보면 forward www netstat
서버의 경우 forward
0 *:10110 *:* LISTEN
foirward:47883 www:22 ESTABLISHED
와 같이 번 포트가 리슨하고 있으며 서버에 번 포트로 접속해 있는 상 10110 www 22 ssh
황을 발견할 수 있을 것이다.
그리고 서버의 경우 아래와 같이 서버의 연결이 성립되어 있는 것을 확 www forward ssh
인할 수 있다.
www:22 forward:47883 ESTABLISHED
이 상태에서 외부에서 서버에 연결을 하려면 바로 서버에 번으로 연 www pop3d www 110
결하는 것이 아니라 서버에 번으로 접속을 하면 된다 아래와 같이 forward 10110 .
서버에 번 포트로 접속을 하면 서버가 아니라 서버의 번 forward 10110 forward www 110
포트가 반응하는 것을 확인할 수 있다.
# telnet forward 10110
Trying 211.1.1.2...
Connected to forward.
Escape character is '^]'.
+OK POP3 www v2001.75 server ready
실제로 아웃룩 익스프레스등 메일 프로그램에서도 받는 메일 서버 에 기존의 대 (pop3) www
신 로 입력하고 고급 탭에서도 아래와 같이 기존의 번 포트 대신에 forward 110 10110 “ ”
을 입력한다 그리고 이와 같은 의 포트 포워딩 방식으로 나 서비스도 . ssh smtp telnet, ftp
암호화 전송할 수 있는데 만약 서비스에 대해 기존의 번 대신 와 같이 포워 , smtp 25 10125
딩 하였을 경우에는 아래와 같이 포트를 변경하여 설정하면 된다.
그림 포트 포워딩시 설정예 < > .
이 상태에서 앞에서 했던 방법으로 를 이용하여 스니핑을 해서 포트 포워딩된 패 tcpdump
킷을 캡처해 보면 암호화 전송이 되고 있는 것을 확인할 수 있을 것이다.
마치면서
가 디자인 될 당시에는 네트워크는 그리 복잡하지 않았고 상호간에 신뢰할 수 있었 TCP/IP
기 때문에 그다지 보안을 고려하지 않아 는 그 자체적으로 매우 많은 보안적인 결함 TCP/IP
을 가지고 있다 앞에서 밝힌 것 외에도 다른 많은 보안적 결함이 있으며 이를 이용한 많은 .
공격들이 인터넷상에 존재한다 이 글을 계기로 늘 사용하고 있는 프로토콜이 그 . TCP/IP
자체로 얼마나 보안적인 취약점을 안고 있는지 알 수 있는 계기가 되었기를 바라며 아울러
실제적인 방법이나 기법보다는 그 작동 원리에 대해 조금이나마 알게 되었기를 바란다.
이외 더 많은 정보에 대해서는 아래의 사이트가 도움이 될 것이다.
참고사이트 :
http://packetstorm.decepticons.org/sniffers/
http://www.linuxsecurity.com/resource_files/network_security/sniffing-faq.html
http://www.robertgraham.com/pubs/network-intrusion-detection.html
http://www.certcc.or.kr/paper/tr2000/2000-07/tr2000-07.htm
http://www.ietf.org/rfc/rfc0826.txt?number=826






▶ 원문: http://www.tt.co.kr/~antihong/documents/arp_sniffing.pdf


◆ 가우리정보센터 (GBC)

2006/09/08 22:43 2006/09/08 22:43
이 글에는 트랙백을 보낼 수 없습니다
Linux  2006/09/08 22:41
출처 카페 > 운영체제 공부 / 쩡희
원본 http://cafe.naver.com/jeonghee1004/17
stow는 프로그램을 직접 컴파일하여 설치할때, 삭제 제거를 쉽게 할 수 있도록 도와주는 프로그램입니다.

일반적으로 직접 컴파일한 소스는 /usr/local 아래에 설치되며, 이렇게 설치된 프로그램이 늘면 제거하거나 업데이트 하기에 어렵습니다. 그래서 /usr/local/<프로그램명>-<버전> 아래에 설치하기도 하는데, 이것은 삭제와 제거가 쉽지만 프로그램 binary, header, library, man page를 사용하는데에는 불편함이 따릅니다. 이때 stow를 사용하여 프로그램을 /usr/local 아래로 link, unlink 하면 경로로 인한 불편함도 없어지고 프로그램 설치와 제거가 쉬워집니다.

stow가 사용할 디렉토리를 만듭니다.
인용:
mkdir /usr/local/stow

다음과 같이 컴파일하여 설치합니다.
인용:
./configure --prefix=/usr/local/stow/<프로그램이름>
make
make install

/usr/local/stow 아래에 설치된 프로그램을 /usr/local로 링크합니다.
인용:
cd /usr/local/stow
stow <프로그램이름>  

제거할때는 다음과 같이 명령하면, 프로그램이 열심히 링크를 찾아 지워줍니다.
인용:
cd /usr/local/stow
stow -D <프로그램이름>

2006/09/08 22:41 2006/09/08 22:41
이 글에는 트랙백을 보낼 수 없습니다
웅쓰:웅자의 상상플러스
웅자의 상상플러스
전체 (379)
게임 (5)
영화 (2)
기타 (23)
맛집 (5)
영어 (2)
대수학 (3)
형태소 (5)
Hacking (9)
Linux (112)
HTML (48)
Application_developing (48)
Web_developing (102)
Window (11)
«   2006/09   »
          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
  1. 2016/01 (1)
  2. 2015/12 (3)
  3. 2015/10 (3)
  4. 2015/03 (2)
  5. 2015/01 (4)