[펌] 보안 PortSentry

os/Linux 2004. 6. 30. 08:32 |
Psionic PortSentry - 포트 스캔 탐지와 능동적 방어
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

$Id: README.install,v 1.30 2002/04/08 17:24:14 crowland Exp crowland $

E-Mail :
sentrysupport@psionic.com
Date : 04-08-2002
Version: 2.0b1

소 개
=-=-=

이것은 긴 인스톨 매뉴얼이다. 만일 여러분이 뒤에 이어질 모든 것과 프로그램 로직안에 깃든 나의 광기어린 방법을 이해하길 원한다면, 여러분은 이 매뉴얼 파일을 읽어야만 한다.
만일 여러분이 이런 것에 대해 관심이 없다면 아래의 내용들을 뛰어넘어라.

PortSentry는 보안 제품들 중에 Psionic의 TriSentry Suite의 일부분이다.
만약 여러분들이 이 도구가 마음에 들고 여러분들이 정말 우리의 다른 제품들에 관심이 있다면 우리의 웹사이트를 참고하라:

http://www.psionic.com

PortSentry는 포트스캔을 탐지하기 위한 많은 옵션들을 가지고 있다.
포트스캔이 발견되면, PortSentry는 다음과 같은 방식들로 반응한다.

- 사건을 나타내는 log 는 syslog()를 통해 만들어진다.
- 타겟 호스트(포트 스캔 공격을 한 컴퓨터)는 TCP Wrappers를 위해서 자동적으로 /etc/hosts.deny에 기록된다.
- 로컬 호스트에서는 타겟 시스템을 데드 호스트(인터넷상에 없는 컴퓨터)로 간주하여, 타겟 호스트를 경유하는 모든 경로가 자동적으로 재구성된다.
- 로컬 호스트는 로컬패킷필터를 통하여, 타겟 호스트로부터 오는 모든 패킷을 무시하기 위하여 자동적으로 재구성된다.

이러한 의도는 관리자에게 그들의 호스트가 스캔되고 있다는 것을 확신시켜주기 위함이다.
이미 이러한 동작을 하는 유사한 프로그램들이 있다.( klaxon 등등) 나는 단지 전체적인 아이디어에 작은 변화(auto blocking 과 같은)를 더했을 뿐이다. 더하여, 스텔스 스캔 탐지(stealth scan detection)를 위한 포괄적인 지원까지...

PortSentry 2.x는 libpcap을 사용하기 위해서 재구성되었다. 이전에 공격을 감지하기 위해 묶여진 포트들을 사용하던 "고전적인" 모드들은 사라졌다. 만약 그 "고전적인" 모드들을 선호한다면, PortSentry 1.1 버전을 사용하길 바란다.

설치
=-=-=-=

첫 단계:

여러분의 에디터로 portsentry_config.h 파일을 가져와서 다음사항이 여러분이 원하는 바와 맞는지 확인해라:

CONFIG_FILE - PortSentry 구성파일의 경로
WRAPPER_HOSTS_DENY - TCP wrapper의 hosts.deny 파일의 경로와 이름
SYSLOG_FACILITY - PortSentry가 사용할 syslog 프로그램
SYSLOG_LEVEL - 메시지를 보내기 위한 syslog level

나는 여러분이 무엇을 하고 있는지 알지 못한다면 이러한 옵션들을 절대 바꾸지 말 것을 제안한다.

※ 참고

1. 고급사용자들은 SYSLOG_FACILITY를 LOG_DAEMON에서 LOG_LOCAL0로 바꾸고 싶어할 수도 있을 것이다. (아니면, 또 다른 LOCAL log 감시프로그램)
여러분은 syslog.conf 파일을 편집할 수 있으며 이것으로 분리된 모니터링을 위해 PortSentry 메시지를 직접 시스템에 있는 PortSentry 자신만의 파일에 가져다 놓을 수도 있다.

2. [경고] : 절대로 이 파일 내용에서 "#" 표시를 지우지 마시오.

이런 "#" 표시들은 주석표시가 아니라, 헤더들을 예비적으로 처리하기 위해 C 컴파일러를 요구하는 것들입니다.
만약 여러분들이 "#" 표시들을 지워버린다면 여러분들은 컴파일 에러들을 보게 될 것입니다.

3. 참고 2번을 다시 한번 읽어보라. 우리는 "#" 표시를 지우고 그로 인해서 프로그램을 컴파일 할 수 없게 되어 문의를 해오는 수많은 사람들을 보았다. portsentry_config.h 파일은 2.x 버전이 베타 버전으로 있는 한은 계속 같이 존재할 것이다.


두번째 단계:

이어서, portsentry.conf를 여러분의 에디터로 가져와서 다음의 옵션을 체크하고 바꿔라:

INTERFACE - 여러분이 모니터 하기를 원하는 interface(CPU와 단말 장치와의 연결 부분을 이루는 회로) 이름. 대부분의 사람들은 이 부분을 "auto"로 남겨둘 수 있고 이 때 PortSentry는 첫번째 interface를 선택하여 모니터 할 것이다. 다른 분들은 아마도 여러개의 interface들을 가지고 있음에도 오직 하나만 보기를 원할 것이다(말하자면 외부 방화벽 interface). 이런 경우는 여러분들이 interface 이름을 직접 설정해 줄 수도 있다. eth0를 보기 위해서는 "/dev/eth0"과 같이 경로명을 포함시키지 말고, 단순히 interface 이름 "eth0"를 적어 넣는다. 등등.. 이런 식으로... PortSentry는 한 번에 오직 한 개의 interface 만을 볼 수 있기 때문에 여러개의 Interface 이름을 적어 넣으면 안된다.

INTERFACE_ADDRESS - PortSentry는 당신이 감시하려 하는 Interface의 IP 주소를 필요로 한다. 현재 버전의 PortSentry는 자동으로 해당 Interface의 IP주소를 찾아내지 못한다. 하지만 앞으로 곧 지원될 것이다. 만약 여러분이 IP 주소를 적어 넣지 않는다면 PortSentry는 당연히 아무런 일도 하지 않을 것이다. 이것은 DHCP 또는 유동 IP 사용자들에게는 적합하지 못하다(매번 바뀌어지는 IP주소를 적어 넣어주고 재시작 해야하므로...-.-a). 하지만 베타 버전이 버전업 되면서 DHCP나 유동 IP 사용자들도 편리하게 사용할 수 있도록 할 것이다. 현재로서는 매번 IP주소를 적어주거나 아니면 스크립트를 작성하여 매번 시스템을 재시작 할 때마다 자동으로 실행되어 새로이 바뀐 IP주소를 자동으로 지정해 주도록 해줘야 한다.

TCP_PORTS - 콤마(,)로 분리된 PortSentry가 감시하기를 원하는 TCP포트의 문자열. 이 문자열은 그 안에 어떠한 공백문자도 가져서는 안된다. 여러분은 여러분이 원하는 만큼의 소켓을 집어넣을 수 있다. 하지만 아마도 Berkely Packet Filter (BPF) 의 길이가 너무 커져서 문제가 될 수도 있다. 만일 이런 문제가 발생한다면 여러분들은 로그 파일에서 에러 메시지를 볼 수 있을 것이고 문자열의 길이를 더 줄여야만 할 것이다.

UDP_PORTS - 이것은 UDP 포트 라는 것을 제외하고는 위와 동일하다.

IGNORE_FILE - 여러분이 항상 무시하길 바라는 호스트의 IP 주소들의 목록이 기록된 파일의 경로. 이것은 나중에 설명될 것이다.

BLOCKED_FILE - 접속금지(blocked)된 호스트의 IP 주소들의 목록이 기록된 파일의 경로.

RESOLVE_HOST - 이 옵션은 호스트들에 대한 DNS 해석을 꺼버린다. 만약 여러분이 느린 DNS 서버를 가지고 있다면 해석을 끄는 것은 더욱 효과적일 것이다. 또한 만약 여러분이 이것을 켜놓는다면 공격자는 되돌아 오는 DNS 응답을 볼 수 있을 것이고 여러분이 연결상태를 감시하고 있다는 것을 (공격자가) 알게 될 것이다. 기본값으로 이 옵션을 꺼놓는다.

BLOCK_UDP -이 옵션(0)은 UDP탐지에 대한 모든 자동적인 반응을 못하도록 한다. UDP는 쉽게 위조될 수 있기 때문에, 정상적으로 존재해야 할 모든 호스트들을 접근금지 시키는 방식으로, 공격자가 보호받는 호스트에 대해 DOS공격(서비스거부공격)을 할 수 있다. 이 옵션을 "0"으로 하면 연결이 여전히 log된 상태라도, 모든 자동적인 반응을 못하게 할 것이다. 이 옵션(0)은 주로 인터넷에 노출되어 있는 호스트에 유용하다. 내부 호스트에 대해서는 여러분은 이 옵션을 (자동적인 반응이) 가능 하도록 놔둬야 할 것이다. 만약 누군가 내부적으로 여러분에게 스푸핑된(spoofed) 패킷을 보낸다면 여러분은 서비스거부보다 더 큰 문제점에 직면하게 될 것이기 때문이다.

BLOCK_TCP - TCP라는 것을 제외하곤 BLOCK_UDP와 같다. (패킷 위조는 그리 큰 문제가 아니다. 왜냐면 PortSentry가 완전한 접속이 이루어지를 기다리고 있고, 이것은 베이직모드에 있어 패킷위조를 하는 것보다 더 힘들기 때문이다. 나는 이것을 인터넷에 연결된 호스트에 대해서도 사용가능하도록 남겨둘 것이다.) 스텔스 스캔 탐지모드에 있어서 UDP 경고는 다음과 같다:

공격자는 패킷 위조를 통하여, 여러분이 막지 않길 원하는 호스트에 대해서 접근금지(block)시킬 수 있다.

(나는 이것이 문제가 될 때까진 걱정하지 않지만 여러분은 이것에 대해 인식하고 있어야 한다.)

수개월간 우리는 이 명백한 문제에 대해서 글을 올리고 말해주는 사람들을 접해왔다. 그렇다. 우리는 패킷 위조, 서비스 거부, 등등에 대해서 알고 있다. 우리는 단지 그 문제의 심각성을 시스템 절충안과 비교하지 않는다. 우리는 이 옵션을 대부분의 호스트([방화벽] 위에서 싸우기 일쑤인 특정 호스트들을 제외하고)들에 대해서 사용 가능하게(막도록) 놔둘 것이다. 여러분이 어떤 설정을 해야 할 지에 대한 좀 더 자세한 답변은 README.stealth를 읽어보라.

KILL_ROUTE - 여기에는 공격이 탐지되었을 때, 공격자가 타고온 경로를 없애기(drop) 위해 실행될 명령을 정의할 수 있다. 정상적인 실행을 위해서는, *절대경로* 전체와 필요한 옵션을 다 붙인 route 명령이 필요하다. $TARGET$ 문자열은 공격하고 있는 호스트 IP주소로 대체될 것이며, 반드시 이 옵션안에서 존재해야 한다. 자신의 gateway는 local subnet상에서 *죽어있는 호스트*가 될 것이다. 어떤 시스템에서는 로컬호스트 주소인 (127.0.0..1)을 넣더라도 아마 작동을 할 것이다. 공격중인 호스트로부터의 모든 패킷은 이 주소로 보내질 것이며, 호스트를 엉망으로 만들지 않을 것이다. 좀 더 현대적인(발전된) route 명령어는 "-blackhole" or "-reject" 옵션을 포함할 것이다. 여러분의 man(1) 페이지를 체크해 보라. 만약 route 명령어가 이런 기능을 지원한다면 이것을 사용할 수 있다.(비록 그럴지라도 나는 그 대신에 패킷필터링을 사용할 것을 권장한다. 아래를 참조하라.)

또한 "asynchronous route"라고 알려진, 기본적으로는 하나의 루트를 통해 여러분의 호스트에 들어가고 다른 (죽은) 루트에 보내져버리는 패킷을 의미하는, 것이 생길 수 있음을 알고 있어야 한다. 이것은 완전한(full) TCP 접속요구에는 잘 동작하지만, UDP나 스텔스 스캔모드에 있어서는 이것은 패킷이 PortSentry를 활성화시키는 것을 여전히 허용하고 여러분은 PortSentry가 보내주는 "already blocked"라는 경고를 계속하여 받게 될 것이다. UDP 스캔에 대해서 이 방법은 ICMP message들이 공격자에게 되돌아가는 것을 막아서 모든 포트가 open 된 상태로 나타나게 된다. 그러나, 만약 공격자가 실제 공격소스 exploit를 실행하고 있다면, 앞의 drop route 방법은 소용이 없다. asynchronous route는 만약 공격자가 대응되는 응답이 어떻게 진행 될지 알고 있으면, 패킷이 시스템에 도달하게 되고, 공격자가 UDP를 이용하여 장님상태의 (blind) 공격을 할 수 있도록 허용할 것이다.

이것을 막는 최선의 방법은 Linux ipfwadm/ipchains 나 *BSD ipfw와 같은 로컬 패킷필터를 사용하는 것이다. 이것은 매우 깔끔한 방법이며 config 파일안에 자세하게 설명되어 있다. $PORT$ 문자열은 공격자에 의해 연결된 포트로 대체될 것이지만, 이 옵션이 항시 요구되는 것은 아니다. $MODE$ 문자열은 (tcp, udp)에서 blocking이 일어난 모드를 나타내는 것이지만, 이 역시 항시 요구되는 것은 아니다.

KILL_HOSTS_DENY - 이것은 TCP wrappers가 사용하는 hosts.deny 파일에 적기 위한 스트링의 포맷이다. 다시말해 $TARGET$ 문자열은 공격자의 IP로 대체되기 위해 확장되며 반드시 요구된다. 여러분은 (%h, twist 등)뿐만 아니라 어떠한 TCP wrapper의 escape 코드들을 넣을 수 있다. $PORT$ 문자열은 공격자에 의해 연결된 포트로 대체될 것이지만, 이 옵션이 항시 요구되는 것은 아니다. $MODE$ 문자열은 (tcp, udp)에서 blocking이 일어난 모드를 나타내는 것이지만, 이 역시 항시 요구되는 것은 아니다.

KILL_RUN_CMD - 이것은 공격자를 향한 route를 제거하기 *이전에* 작동시키기 원하는 명령이다. 공격이 탐지되었을 때, 여러분이 실행하기 원하는 어떠한 program이나 script를 집어넣을 수 있다. 나는 절대 ATTACKING HOST(공격하는 호스트)에 대해서 보복공격 작업을 집어넣지 않길 권고한다. 실제로, 포트스캔을 하고 있는 호스트는 해킹을 당한 임의의 호스트이다. 그러므로, 만약 여러분이 보복을 한다면, 아마도 여러분은 선량한(?) 사람들을 공격하는 것이 될 것이다. 보안의 목적은 쫓아버리는 것이다. 여러분은 그들을 화나게 해서 여러분에게 개인적인 복수를 하게 되기를 원치 않을 것이다. 유념하라. 비록 13살 어린이도 그들의 윈도우 컴퓨터에서 DoS(서비스거부) 공격을 실행하여서, 여러분의 인생을 비참하게 만들 수 있다는 것을...
위에서 보았듯이 $TARGET$, $PORT$, 그리고 $MODE$ 문자열은 유용하지만 이 옵션에 반드시 요구되는 것은 아니다.

KILL_RUN_CMD_FIRST - 이 값을 "0"으로 설정하면 위의 명령이 route가 제거되기 전에 실행되도록 만든다. 이 값을 "1"로 설정하면 위의 명령이 이미 blocking이 된 후에 실행되도록 만든다. (역자 주: portsentry.conf 파일의 해당 설정 부분의 주석 설명을 보면 "0"이 이후에 실행되는 것이고 "1"이 이전에 실행되는 것으로 반대로 설명이 되어 있습니다. 아마도 portsentry.conf 파일에 있는 내용이 맞는 것 같습니다.. README.install 파일 내용이 틀린 듯 하네요.. 쩝.. );P

SCAN_TRIGGER - PortSentry는 자신의 호스트에 접속하였던 호스트를 기억하는 state engine를 가지고 있다. 이 값의 설정은 PortSentry가 반응동작하기 전에 PortSentry에게 감시되는 port의 몇 번까지의 접속을 허용하도록 말해줄 것이다. 이것은 순차인 것과 임의적인 포트스캔을 둘 다 탐지한다. 디폴트값은 0이며, 이는 즉각 반응한다. 그 값을 1 또는 2로 해주면 잘못된 경고를 줄일 것이다. 그리고 이보다 높은 값들은 3회이상 다른 포트들에 접근했을 때와 같은 경우, 아주 수상한 행동을 감지하게 될 것이다. 일반적으로 여러분은 아무런 생각없이, 이 값을 0으로 놔둘 수 있다.


세번째 단계:

여러분의 문서 편집기로 portsentry.ignore 파일을 가져와서 그 안에 감시되고 있는 포트에 접근해도 (보안장치를 작동하지 않고) 무시해 버릴 호스트를 추가하라. 이것은 적어도 localhost(127.0.0.1)와 내부 네트워크의 IP주소를 포함해야만 한다. 우리는 *절대* 여러분과 동일네트워크상에 있는 모든 호스트 IP 주소를 집어넣는 것을 권장하지 않으며, 대신 그렇게 하기 위해서 여러분들은 netmask를 사용할 수 있다. 설정하는 형식은 아래와 같다:

<IP Address>/<Netmask Bits>

192.168.2.0/24
192.168.0.0/16
등등...

우리는 너무 많은 호스트들을 적어 넣는 것을 권장하지 않는다. 아주 "신뢰관계"에 있는(friendly) 호스트일지라도 여러분에게 있어 누가 여러분에게 연결을 하고 있는지를 보는 것은 아주 중요한 일일 것이다. 이것은 여러분이 내부 호스트의 결탁(외부의 해킹에 의한)을 보다 빨리 탐지하는데 도움을 줄 것이다.

자신의 편집증에 충실해라. 그렇다. 이런 일은 일어나며 우리는 *상당수*의 경우 관리자들이 너무 많은 무시해버릴 호스트들을 적어 넣었고 그들 *내부 호스트들의 결탁(외부의 해킹에 의한)*에 의해서 해킹당했다는 사례들을 들었다.


네번째 단계:

컴파일(Compile). make 명령을 내리면, 여러분은 여러분의 시스템타입을 고르고, build하고 인스톨할 수 있게 된다. 원래 default directory는 /usr/local/psionic/portsentry2 이다. 만약 여러분이 이 디렉토리가 마음에 들지 않는다면 Makefile을 수정하고 새로운 경로에 영향을 주는 여러분의 portsentry.conf 와 portsentry_config.h 파일들을 확인하라.

build한 후에 make install 명령을 내리면 여러분이 지정한 인스톨 디렉토리에 복사본 파일들을 만들어 준다.


다섯번째 단계:

PortSentry를 작동시켜라. 설치한 후에 PortSentry를 작동하는데 있어 두 가지 방법이 있다:

1) 설치 디렉토리(/usr/local/psionic/portsentry2, 등등..)로 이동(cd)하여 다음을 실행시켜라:

./portsentry

2) 바로 명령을 실행시켜라:

/usr/local/psionic/portsentry2/portsentry


"Stealth" TCP scan detection mode [BETA] (스텔스 TCP 스캔 탐지 모드 - 베타)

PortSentry는 자신의 호스트로 들어오는 모든 패킷들을 감시할 것이다. 만일 들어오는 패킷이 portsentry.conf 설정 파일에서 TCP_PORTS 변수에 입력되어진 감시 대상 포트 목록의 포트를 향한다면 그에 대응하여 호스트를 막아버릴 것이다.
이 방법은 connect() 스캔, SYN/half-open 스캔, XMAS 스캔, FIN 스캔, NULL 스캔, 등을 감지해 낼 것이다. UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)

"Stealth" UDP scan detection mode [BETA] (스텔스 UDP 스캔 탐지 모드 - 베타)

이것은 위의 TCP stealth mode와 작동방법은 동일하다. UDP 포트들을 나열하면, 그 포트들은 감시된다. 이것은 어떠한 소켓도 묶지 않으며, 실제 스텔스 스캔 탐지 모드가 아닌 중에도 거의 동일하게 동작한다.( 모든 UDP 패킷에 반응한다.) UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)

** Advanced Logic Mode **
-PortSentry는 포트들을 감시하는 방법이 아주 뛰어나다. FTP와 같은 몇몇 프로토콜에 있어서, 클라이언트는 실제적으로 ephemeral range인 1024번에서 65535번까지의 범위에서 포트들을 연다. 그리고 서버는 *역으로* 여러분에게 접속한다. 보통은 이런 방식이 포트스캐너가 동작할 수 있게 해준다. 그러나 PortSentry는 호스트로 들어오는 접속을 감시할 것이고, 이러한 "임의적인" 접속연결(binding)로 향하는 것인지 아닌지를 결정할 것이다. 만약 임의적인 접속연결로 향한다면, 그 한번의 접속이 무시된다. 접속이 끊어지자마자 window는 닫히고 모든 방어체계가 다시 활동한다. 이것은 실제로 초보적인 stateful inspection engine이다. UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)


인스톨을 확인하라:

local log 파일의 마지막부분에 PortSentry의 초기화 메시지가 있어야 한다.

성공적인 PortSentry의 초기화 메시지는 아래와 같이 나타날 것이다:

Mar 5 21:16:00 nemesis portsentry[2286]: adminalert: Monitoring interface eth0 and address: 10.1.1.1
Mar 5 21:16:00 nemesis portsentry[2286]: adminalert: Monitoring TCP ports: 1,11,110,143,635,1080. . .
Mar 5 21:16:00 nemesis portsentry[2286]: adminalert: PortSentry is initialized and monitoring.

********************************************************************
** 마지막 줄은 PortSentry가 적절하게 초기화되었음을 나타낸다...... **
** 만약 여러분이 이런 메시지를 보지 못했다면 무언가가 틀린 것이다. **
********************************************************************

이제 여러분은 다른 호스트로 가서 텔넷으로 은폐된 폭팔물(PortSentry)이 장치된 포트로 접근할 수 있다.

[주의] 절대로 여러분이 서비스 받을 위치에서 보호받는 호스트로 접근하지 마시오. 이유는 만일 그렇게 하면 여러분은 스스로 자신을 막아버리게 될 것이기 때문이다.

위의 주의점을 다시 한 번 숙지하라. 우리는 아래와 비슷한 것을 우리에게 알리는 사람들을 봤다.(만들어진 예기지만, 여러분들은 이 예기를 참고 할 수 있다)

"안녕하세요, 제가 일년에 일주 정도만 헬리콥터를 타고서만 접근가능한 north atlantic의 고립된 석유 시추선에 있는 나의 웹 서버에다가 port sentry 를 설치했는데요. 그리고 나서 저는 웹 서버에 접속할 수 있는 온전한 행성에서 유일한 관리 시스템으로 가서 보호받는 포트에 텔넷으로 접근하여 port sentry 를 테스트 해 보았습니다. 지금으로서는 port sentry가 온전하게 작동하는 것 같습니다. 왜냐하면 제가 저의 컴퓨터에 접근할 수 없기 때문입니다. 하지만 이젠 제 컴퓨터에 접근해야겠는데요. 저 좀 도와주시겠어요?"

그건 그렇고...

여러분은 곧 다음과 같은 것들을 보게 될 것이다:

Mar 5 21:17:39 packetmonkey portsentry[2286]: attackalert: Host 192.168.2.15 has been blocked via wrappers with string: "ALL: 192.168.2.15"
Mar 5 21:17:39 packetmonkey portsentry[2286]: attackalert: TCP SYN scan from host 192.168.2.15/192.168.2.15 to TCP port: 143 from TCP port: 31337

만약 여러분이 접속이 끊어지고 다시 telnet으로 접속하기를 시도한다면 여러분은 방금 전의 호스트에 접근할 수 없음을 확인해야 한다. 이러한 동작이 확인된다면, 축하한다! 여러분은 PortSentry를 제대로 작동시킨 것이다.

만약 여러분의 로그체크 데몬이 띄워져 있다면 여러분이 서버에 접속할 때, 위의 접근거부 상황에 대한 경고 메시지 내용이 로그파일에 나타나는 것을 확인할 수 있을 것이다.

만약 여러분이 netstat -rn 명령을 하면 여러분은 이전에 동작하던 의심가는 호스트로의 죽은 경로를 보게 될 것이다.( 내가 이전에 권장했던 것과 같이, 패킷필터를 사용하지 않으면...)

PortSentry 명령들을 리눅스 시작 스크립트파일(startup file)에 쓰고 나서, 여러분이 한 작업으로 돌아와라.

이게 어떻게 도움이 될 것인가 하면??

여기 몇몇 좋은 생각들이 있다.

- Run as a UDP service on port 69 to catch TFTP probes.
(TFTP 침입을 잡기 위해서는 포트 69에 UDP 감지모드를 가동하라.)
- Run as a UDP service on port 161,162 to catch SNMP probes.
(SNMP 침입을 잡기 위해서는 포트 161,162에 UDP 감지모드를 가동하라.)
- Run as a UDP service in the port range 32000-33000 to catch RPC probes.
(RPC 침입을 잡기 위해서는 포트범위 32000-33000 에 UDP 감지모드를 가동하라.)
- Run as a TCP service on port 143 to catch IMAP probes.
(IMAP 침입을 잡기 위해서는 포트 143에 TCP 감지모드를 가동하라.)
- Run as a TCP service on ports 11,15 to catch netstat/systat probes.
(netstat/systat 침입을 잡기 위해서는 포트 11,15에 TCP 감지모드를 가동하라.)
- etc. 등등

실제로 PortSentry는 빠르게 반응해서, 공격자에 의한 호스트 포트스캔은 감시대상 포트에 접근이 있은 후 1초이내에 차단될 것이다.

UDP 스캔에 대해서는 모든 포트가 "열려진 상태"로 나타나게 함으로써 여러분을 스캔하는 이들을 매우 짜증스럽게 만들 것이다.
TCP 스캔에서 공격자는 어떠한 응답도 얻을 수 없을 것이다.


안전성
=-=-=-

만약 우리가 프로그램의 안전에 대한 고려사항 중 잊고 놓친 것이 있다면, 여러분이 그 내용을 BugTraq에 올리기 전에 우리에게 알려주기를 원한다 :).


메시지
=-=-=-=-

가능한 모든 states/errors/successes and unknowns(상태/오류/성공 그리고 알 수 없는 것들)은 syslog 파일에 쓰여진다.
다음의 tag들이 의미하는 바는:

adminalert: - PortSentry의 상태를 나타내는 메시지.
securityalert: - 보안 관련 사건들이 일어났음을 나타내는 메시지
attackalert: - 스캔을 감지했다는 것과 그에 따른 동작이 실행되었다는 것.


파일들
=-=-=

현 상태로는, 모든 호스트들은 그들이 접속금지(blocked) 되었을 때 portsentry.history 파일뿐만 아니라 portsentry.blocked 파일에 기록된다. blocked file은 PortSentry가 다시 시작될 때마다 지워진다. history file은 간단히 덧붙여지며 일정한 기한까지 접속금지(blocked)된 호스트들의 기록으로 사용할 수 있다.

기한이 지난 후에 여러분은 공격했던 호스트들에 대해 죽은 경로를 삭제하고, 호스트를 hosts.deny 파일에 저장하길 원할 수도 있다. 이것은 전적으로 여러분의 결정에 달려있다. 만약 여러분이 공격자가 다시 접근할 때 접근금지(blocking)을 작동시키기를 원한다면, 단지 PortSentry를 재시작하거나 혹은 blocked file에서 개개의 호스트를 제거하면 된다.

대부분의 시스템에서 여러분이 접근금지시킨 호스트로의 경로를 회복시키길 원한다면 여러분은 단순히 아래와 같이 경로를 지움으로써 회복시킬 수 있다:

리눅스:

route del <ip_address> reject

기타:

route delete <ip_address> <dead_route>

또는 간단히 여러분의 패킷 필터들을 쏟아냄으로써 가능하다.

이것이 바로 내가 말하고자 한 것이다. 로그파일의 내용을 보는 것뿐만이 아니라 여러분이 다른 문제점들도 알 수 있도록 하기 위해서, 나는 여러분이 Abacus 프로젝트의 Logcheck를 사용하길 강력히 권장한다. 그리고 PortSentry가 여러분에게 무엇을 알리려고 하는지 살펴보길 권장한다. 여러분은 본 프로그램을 아래 주소에서 찾을 수 있다:

http://www.psionic.com

이 문서를 읽어준 것에 감사히 생각하고, 질문이나 추가적인 조언이 있다면 내게 메일로 써 주기를 바란다.

감사한다,
Posted by 큰바우
:
굼벵이(chtla_com) http://cafe.naver.com/linuxserver/85
리눅스 시스템 관리자가 알아두면 좋은 50가지 정도의 방법을 기술한 글.
출처는 모르겠네요.. ㅡ.ㅡ;;

예전에 구사이트에 있는 자료중 누락된 내용입니다..
(몇몇개가 누락이 되는군요..)
어디서 퍼온것 같은데.. 출처를 모르겠네요..ㅡ.ㅡ;;
찬찬히 살펴 보세요..

=======================================================
시스템 관리자를 위한 50가지 비법

리눅스 시스템 관리자가 되기 위해서는 많은 것을 알아두어야 한다. 시스템 관리자의 관리 여하에 따라 많은 사람들의 시스템 장애를 초래할 수 있기 때문이다. 물론 시스템 관리자가 모든 것을 미리 예방할 수는 없다. 하지만 불가피한 상황을 제외하고는 시스템이 정상적으로 작동되도록 해야한다.
이번 호에서는 시스템, 네트워크, APM, 메일, 보안, 장애 발생시 복구 등에서 일어날 수 있는 시스템 관리자의 행동요령에 대해 알아볼 것이다. 시스템 관리자는 항상 모니터와 키보드와 함께 한다는 사실을 기억해야 한다.

막강한 시스템 길들이기

시스템이 네트워크에 연결되어 있다면, 다음과 같이 한국 표준시간 서버에서 표준시간을 받아서 설정할 수 있다.

# rdate -s time.kriss.re.kr

시스템이 온라인 상태가 아니라면 아래와 같이 수동으로 설정할 수도 있다.

# date -s ?1999-12-30 22:22:40?

위와 같이 실행하면 실행할 때만 적용되므로 이후 시간이 늦어지는 것을 막기 위해서는 주기적으로 변경 가능하게 크론(/etc/crontab)에 설정하는 것이 좋다.
.profile은 로그인시 적용되는 내용들이고, rc.local은 시스템 부팅시 실행해야 할 것들을 적어 놓은 것이다. 사용자 홈디렉토리의 .profile 이 /etc에 있는 설정 파일보다 우선하기 때문에 홈 디렉토리에 .profile 에 패스를 설정해주거나 쉘 환경 파일 등을 설정해 주면 계정 내에서 적용이 된다. rc.local에는 부팅시 가장 마지막에 실행되므로 일반적으로 부팅시 실행되어야 할 데몬 등을 적어준다.

리눅스 시스템의 자원 정보는 proc 파일시스템 구조를 통해서 알 수 있다. 이는 실제로 디스크 용량을 차지하는 파일들이 아닌 가상의 디렉토리 구조이며 리눅스 커널에 의해 사용되는 시스템의 정보를 담는 곳으로 사용된다. 다음의 위치에서 하드웨어에 대한 정보 및 시스템 관련 정보들을 확인할 수 있다.
위와 같이 관련된 정보에 해당하는 파일 이름이 존재한다. 이 파일들은 텍스트 포맷이므로 cat 명령을 통해서 확인할 수 있다.

^M 문자를 공백으로 치환하면 된다.

:1,$s/^M//g

# rpm -qa | grep 패키지 명으로 확인할 수 있다.

rpm2cpio filename.rpm | cpio -I -make-deretories -E filename

Tcp Syn Flooding은 웹으로의 공격이 대부분이므로 syn_recv 프로세스가 일정 개수가 넘게 되면 아파치를 재시작한다. 지속적인 공격일 경우 대처 방안으로 두 가지 방법이 있다.
첫째, sysctl -a |grep syn_backlog으로 확인 후 backlog를 늘려주거나
둘째, sysctl -a |grep syncookies로 확인 후 syncookies의 값을 1로 바꾸어준다. syn_backlog의 값을 조정해주는 방법은 다음과 같다.

# sysctl -w net.ipv4.tcp_max_syn_backlog=1024
# echo 1024 > /proc/sys/net/ipv4/tcp_max_syn_backlog

syncookies의 값은 다음과 같이 변경이 가능하다.

# sysctl -w net.ipv4.tcp_syncookies=1

Umount시 위와 같은 메시지가 나는 것은 unmount하려는 디렉토리에서 실행되고 있는 프로세스가 있기 때문이다. 예로 /tmp 디렉토리를 umount시키려 할 때 위의 메시지가 뜨는 경우 mysql. socket파일이 /tmp에 있는 경우를 들 수 있다. 이 경우에는 해당 파일시스템에서 실행중인 프로세스를 제거해야 하나 일일이 제거가 번거로우므로 Fuser에서 -k 옵션을 사용하면 간단히 해결할 수 있다.

Fuser -km 장치명

디렉토리나 파일 퍼미션 중 setuid는 소유자의 권한을 잠시 빌려 실행 후 권한을 돌려주고 실행을 마치게 되는데 실행도중 인터럽트가 발생한다면 정상적으로 권한을 반환하지 못하게 되어 소유자의 권한을 그대로 가지고 있게 된다. 이때 파일의 소유자가 루트였다면 이것은 보안에 문제가 될 수 있으며 이런 점을 이용해 해킹에 많이 사용된다. Setuid가 걸려 있는 파일 중에 실행권한이 있으며 루트권한일 경우에는 위험하다. 특정 디렉토
리에서 setuid가 걸려있는 파일을 찾으려면 find /usr -perm 4755와 같이 perm 옵션으로 찾을 수 있다.

다음과 같이 ~/.bash_profile를 실행해서 변경이 적용되도록 한다.

# source ~/.bash_profile

리눅스 시스템을 재부팅하고 lilo가 뜨면 ‘linux single’로 부팅한다.
Tab 키를 누르면 등록되어 있는 라벨이 모두 보이므로, 여기에서 선택하도록 한다. 부팅 후 쉘 명령어 화면에서 /etc/passwd 파일에서 암호 부분을 삭제하거나 passwd를 실행하여 루트의 패스워드를 새로 설정해 준다.

# passwd root

위의 명령을 입력한 후 변경할 패스워드를 입력하면 된다.

보통 파티션을 나누는 것에 대해서 별다른 고려 없이 /로 모든 것을 잡아서 설치하는 경우가 종종 있다. 이럴 경우 설치시 편리하지만, 나중에 파일시스템에 문제가 생기거나 효율적으로 파티션을 관리하기에는 많은 어려움이 있다. 파티션을 나눌때는 어떤 용도로 쓸 것인지에 대해서 충분히 생각한 후 파티션을 해야 한다. 다음은 9.1GB 스카시 하드디스크를 기준으로 웹 서버에 이용될 서버에 대해 파티션한 경우의 예다.
/var 디렉토리와 같이 항상 새로운 자료가 쌓이는 곳은 안전성이 우선시 되므로, ext3 파일시스템이 유리하며, /usr와 같이 내용 변화 없이 빠르게 액세스하여 쓸 수 있어야 하는 부분은 ext2 시스템을 이용하여 성능에 초점을 두면 좋을 것이다.

1024KB인 경우에는 블럭이 작은 만큼 4096KB보다 하드의 낭비가 적다.
1023KB의 데이터를 저장하는 경우, 기본 블럭사이즈가 1024KB일 때는 1K 공간이 사용되지만, 4096KB가 기본 블럭이라면 4K를 차지하게 된다. 하지만 아주 작은 파일들이 많은 경우 해당 데이터를 액세스하는 데는 1024KB가 4096KB보다 더 걸리게 되므로 퍼포먼스가 급격히 떨어지게 된다. 따라서 자신이 이용하는 시스템의 특성과 용도에 맞게 블럭 사이즈를 지정해서 사용하면 된다.

RAID는 ‘Redundant Array of Inexpensive (or Independant) Disks’의 약어다. RAID 시스템은 여러 드라이브의 집합을 하나의 저장장치처럼 다룰 수 있게 하고, 장애가 발생했을 때 데이터를 잃어버리지 않게 하며 각각에 대해 독립적으로 동작할 수 있도록 한다.

시스템의 다운, 데이터 손실에 대비하여 보통 여러 가지 RAID 레벨 중에서 1과 5번 방법을 많이 사용한다.
RAID 1(mirroring)의 특징은 빠른 기록 속도와 함께 장애 복구 능력이 있다는 것이다. 2대의 드라이브만으로 구성할 수 있기 때문에 작은 시스템에 적합하다. 읽을 똑같은 하드가 복제되고 있으므로, 시스템에 문제 발생시 서비스 지연 시간이 매우 짧아서 웹 서비스를 하는 곳에서 유용하게 쓸 수 있다. 하지만 한 하드의 내용이 또 다른 하드에 똑같이 복사되므로 하드용량의 낭비가 심하다.
RAID 5(distributed parity)는 작고 랜덤한 입출력이 많은 경우 더 나은 성능을 제공한다. 빠른 기록 속도가 필수적이지 않다면, 일반적인 다중사용자 환경을 위해 가장 좋은 선택이다. 그러나 최소한 3대, 일반적으로는 5대 이상의 드라이브가 필요하다. 변경된 내용이 있을 경우 그것만 기록한다. 일반적으로 RAID 1은 ECC 계산을 하지 않으므로 RAID 5보다 빠르고, raid5는 하드 공간을 좀 더 여유있게 쓸 수 있다는 장점을 지닌다.

먼저 시스템의 전체 용량이 어떻게 되고, 그 중에서 백업할 가치가 있는 것은 어떤 부분인지를 결정한다. 사용할 백업 장비와 종류를 알아보고, 총 백업 시간과 어느 정도 부하가 걸리는지 예상해보고 테스트 해 본 후 마지막으로 백업 스케줄을 정한다. Full 백업은 백업할 자료를 처음부터 끝까지 다 기록하는 것이고, Incremental 백업은 이전의 데이터와 비교해서 새로 추가된 내용만 백업하는 방법이다. 따라서 Full 백업시 완전히 데이터를 백업할 수 있지만 시간이 많이 걸리고, 시스템에 부하를 초래할 수 있는 반면에 Incremental 백업은 빠른 시간내에 백업을 할 수 있지만, 백업하는 시간에 따라 데이터가 완전히 백업되지 못할 경우도 있을 수 있다.

SNMP는 ‘Simple Network Management Protocol’의 약자다. 네트워크에 연결되어 있는 장치에서 네트워크에 관련된 정보를 모으고 문제점 등을 보고할 수 있는 기능을 제공하는 프로토콜이다. 구성 요소는 에이전트와 매니저가 있다. 이것은 서버/클라이언트 구조로서 에이전트가 서버에 해당되고, 매니저가 클라이언트에 해당한다. 에러가 발생하는 경우는 선택한 장비에 SNMP가 Enable이 안 되었거나, 네트워크에 문제가 있어서 모니터링
하려는 장비까지 프로토콜이 전송되지 않는 경우, community 값이 잘못 사용된 경우 등이 있다.

/etc/rc.d/init.d이 디렉토리에 있는 서비스를 ‘서비스명’ stop 또는 start 시키거나 재시작시킨다.

quota를 이용하면 된다. df 명령으로 사용자의 홈디렉토리가 있는 디바이스를 확인한다.

ilesystem 1k-blocks Used Available Use% Mounted on
/dev/sda5 3028080 878480 1995780 31% /
/dev/sda1 62217 7713 51291 13% /boot
/dev/sda6 2759260 2088820 530276 80% /home2
/dev/sdb1 8744304 6496724 1803388 78% /home3
/dev/sdc1 35296928 25597968 7905940 76% /home4
/dev/sda10 202220 6 191774 0% /tmp
/dev/sda7 1517920 1280648 160164 89% /usr
/dev/sda8 608724 426992 150812 74% /var
# edquota username
Quotas for user jhk1:
/dev/sda6: blocks in use: 47584, limits (soft = 0, hard = 0) /* 이 부분에 설정 */
inodes in use: 4590, limits (soft = 0, hard = 0)
/dev/sda8: blocks in use: 4, limits (soft = 0, hard = 0)
inodes in use: 1, limits (soft = 0, hard = 0)
Soft는 용량에 설정되어 있는 용량은 넘어도 어느 정도 여유가 있지만, hard 용량에 설정된 크기는 절대적이다. 따라서 hard 용량을 사용자는 넘을 수 없다. 일반적으로 soft 용량을 hard 용량보다 조금 더 적게 설정해 놓는다. 쿼터 조정후 quotacheck /dev/sda6를 해줘서 체크를 해 주도록 한다.

파일명이 하이픈(-)으로 시작하는 파일

rm ./-filename 상대경로를 이용하여 파일명을 지정해줌
rm -- -filename --를 이용 그 이후에 오는 '-filename'이라는 파일이 옵
션이 아닌 파일이라는 것을 밝힘

/etc/inittab에서 사용하지 않은 가상콘솔 레벨을 주석처리 해주면 된다.

# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
#4:2345:respawn:/sbin/mingetty tty4
#5:2345:respawn:/sbin/mingetty tty5
#6:2345:respawn:/sbin/mingetty tty6


먼저 psacct라는 패키지가 필요하다. 설치되지 않은 경우 rpm이나 소스 등을 직접 설치 한다(대부분 배포본에 기본적으로 포함되어 있으므로 그대로 사용하면 된다). 다음과 같이 명령하면 사용한 명령어를 확인할 수 있다.

더미 로그 파일 생성(데이타를 기록할 파일 생성)
# touch /var/log/pacct
# /sbin/accton /var/log/pacct 체크를 시작하게 하는 명령어 실행
# lastcomm 사용자계정 사용자가 수행한 명령어 체크 */
tar xvfpz 압축파일 또는 .tgz -C 특정경로 특정 파일의 절대경로(또는 파
일명)로 입력하면 된다. test.tgz 파일에서 /home/test /test.txt파일
을 /tmp 디렉토리에 압축해제를 한다면, tar xvfpz test.tgz -
C /tmp /home/test/test.txt와 같이 하면 된다.

TTL이란 Time To Live의 약자다. 이것은 라우팅 에러로 인하여 데이터그램이 네트워크를 영원히 떠돌아다니는 것을 방지한다. 라우터는 네트워크 간을 이동하는 데이터그램의 TTL 필드를 감소시키며 TTL 필드가 0이 되는 데이터그램은 버린다(drop). IPv4 멀티캐스트에서 TTL은 문턱값(threshold)의 의미를 지닌다.
다음 예를 보면 그 용도가 분명해진다. 회사에서 모든 호스트가 속하는 아주 길고 대역폭에 한 부서가 대역폭을 많이 차지하는 인터넷 방송을 한다면, 랜에는 엄청난 용량의 트래픽이 발생할 것이다. 인터넷 방송도 하길 원하지만, 멀티캐스트 트래픽 때문에 인터넷 전체가 마비되어서는 안된다. 멀티캐스트 트래픽이 라우터간을 얼마나 멀리까지 이동할 수 있도록 할 것인지 제한할 필요가 있다. 이것이 TTL의 용도다.

TCP Wrapper를 사용하는 방법과 ipchains를 사용할 수 있는데 커널 2.4 버전부터는iptables을 사용한다. hosts.allow와 hosts. deny를 사용한다면, hosts.deny 파일에서 다음과 같이 모두 제한을 한다.

all : ALL

hosts.allow 파일에서 허용할 IP를 여러 개 설정할 경우 다음과 같이 스페
이스로 구분하여 준다.

all : xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx ....

ipchains나 iptables의 경우에는 다음과 같이 설정하여 주면 된다.

# ipchains ?A input ?s xxx.xxx.xxx.xxx ?j DENY
# iptables ?A INPUT ?s xxx.xxx.xxx.xxx ?j DROP

안전한 네트워크 다지기

시스템에 기본적으로 설치된 아래의 명령들을 사용하여 네트워크가 정상적으로 작동하지 않는 경우 여러 가지 테스트를 해볼 수 있다.
/etc/sysconfig 디렉토리 밑에 하드웨어에 대한 정보가 나오는데 이더넷 카드가 여러 개 꽂혀 있다면 ifcfg-eth1, ifcfg-eth2 식으로 확인할 수 있다.

/etc/sysconfig/network-scripts/ifcfg-eth0

#cat ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static /* 정적 아이피 */
BROADCAST=211.47.64.255
IPADDR=211.47.64.80
NETMASK=255.255.255.0
NETWORK=211.47.64.0
ONBOOT=yes /* 부팅시 자동인식 */

사용하는 IP를 변경하거나, 새로운 네트워크 카드 추가시에는 ifcfg-eth0 파일을 수정한 후에 반드시 ifdown ifcfg-eth0, ifup ifcfg-eth0 명령을 실행해 주어야 변경된 IP가 적용된다. 또는 /etc/rc.d /init.d/network restart를 실행해 주어도 된다.

Apache PHP MySQL

아파치에만 적용되는 내용은 아니지만 standalone으로 설정할 경우에는 /etc/rc.d/rc.local나 /etc/rc.d/rc3.d/밑에 설정되어 데몬으로 실행되며, inetd로 설정할 경우 /etc/inetd.conf에 추가되어 실행되어 텔넷이나 FTP와 같이 시스템 프로세스로 실행되므로 접속이 많은 httpd 인 경우 standalone으로 설정하여야 한다. 그리고 inetd로 설정시에는 한정된 프로세스만 수용 가능하며 반응속도가 standalone 방식에 비해 느리다.

httpd -t 옵션으로 우선 syntax error부터 확인한 후 syntax error가 있으면 먼저 수정을 해주고 Logs 디렉토리에서 에러 로그 파일을 확인하여 수정 후 재실행한다.

php3 버전의 경우 index.php3을 php4의 경우 index.php라는 파일을 다음과 같은 내용으로 작성하여 웹에서 열어보면 버전 및 연동 현황을 확인할 수 있다.

phpinfo();
?>

먼저 php설치 후 apache 컴파일시 php 모듈 넣어서 재컴파일 해준다.
./configure --prefix=/usr/local/apache --activate-
module=src/modules/php4/libphp4.a

아파치에서 bandwidth 모듈이 삽입되어 있는 상태라면 모든 호스트에 대해 1024byte로 속도를 제한하기 위해 아파치에서 설정해 주는 부분은 다음과 같다. Httpd.conf에서 BandWidthModule On라고 설정 후 BandWidth all 1024라고 설정한다.

아파치에서 index.html 파일이 없을 때 디렉토리 목록 출력을 원하지 않을 경우에는 DocumentRoot 디렉토리쪽에 설정되어져 있는 옵션에서 Indexes를 삭제한다. 또한 특정 디렉토리에서만 인덱스를 허용치 않을 경우에는 특정 디렉토리의 .htaccess 파일안에 ‘Options -Indexes’ 이 부분을 삽입하면 된다.

안전한 메일 관리법

센드메일에서 한번에 보낼 수 있는 메일 용량은 /etc/mail /send mail .cf 파일에서 MaxMessageSize 부분에서 다음과 같이 주석을 제거하고 바이트 단위로 설정을 해줄 수 있다. 받는 메일 계정의 용량은 Mlocal 부분에서 M=1000000 부분에서 바이트 단위로 제한량을 적는다.

MaxMessageSize=1000000

relay를 막는 방법도 있지만 그건 외부에서 로컬 서버를 SMTP로 사용하지 못하도록만 할 수 있으며 iptables를 이용하면 로컬 서버에서 보내는 메일에 대해 제한이 가능하다.

# iptables -A OUTPUT -p tcp --syn --dport 25 -j DROP

-A 기존의 iptable에 추가
-p 프로토콜
-dport 포트 넘버
로컬에서 외부로 보내는 메일이라면 remote의 25번 포트로 접속이 되므로 OUTPUT 패킷 중 목적지 포트가 25번인 패킷만 drop 한다. 메일 송수신은 tcp이므로 --syn을 추가하지 않을 경우에는 3 way-handshaking에 의해 메일을 받을 수도 없게 되므로 반드시 --syn을 추가해야 한다. 보내는 메일은 일단 메일큐 디렉토리에 저장된 후 발송되므로 메일큐 디렉토리를 삭제하거나 다른 이름으로 변경하면 메일을 발송할 수 없게 된다.

/etc/mail/access 파일에서 Relay 여부를 설정한다.

localhost RELAY

변경한 후 적용하려면 다음과 같이 실행해 준다. 또는 인증 기능(SMTP AUTH)이 지원되는 최신 버전의 센드메일을 사용한다.
# makemap hash /etc/mail/access < /etc/mail/access

간단한 방법으로 다음과 같이 텔넷으로 센드메일 포트인 25번으로 접속해 보면 알 수 있다

# telnet jimmy.tt.co.kr 25

가상 계정을 이용해서 해결할 수 있다. 아웃룩에서 jhk라는 계정을 설정하면 jhk at jungheekim.co.kr, webmaster@jungheekim.co.kr로 오는 메일을 모
두 받아 볼 수 있다.

# vi /etc/mail/virtusertable
webmaster at jungheekim.co.kr jhk(jhk계정에 webmaster라는 계정이 가상계정으로 설정)

해외에 출장이 잦은 사용자가 메일을 자신이 사용하는 웹메일로 포워딩해 달라고 하고, 회사에 돌아와서도 포워딩된 메일을 아웃룩에서 다시 받아보길 원한다면 다음과 같이 한다. 해당 사용자의 홈디렉토리 밑에 .forward 파일을 만들어서 이메일 주소를 입력하고 자신의 계정에는 \를 추가해 주어야 루프를 막을 수 있다.

vi ~junghee/.forward
sitsme75 at hanmail.net, junghee.kim at tt.co.kr

메일을 확인할 수 없는 상황일 때, 메일 수신 후 자동으로 미리 작성되어 있는 메시지를 보낼 수 있는 방법(즉 자동응답 메일 작성 방법)은 자신의 홈디렉토리에 “.procmailrc” 파일을 만들고 다음의 내용을 입력한다.
-------------------------------------------
:0 h c
* !^FROM_DAEMON
* !^X-Loop: YOUR@EMAIL
| (formail -r -A"Precedence: junk"
-I"From: YOUR_NAME "
-A"X-Loop: YOUR@EMAIL
cat $HOME/autoreply.txt) | $SENDMAIL -t
--------------------------------------------
그리고 ‘autoreply.txt’ 파일에 답변 글을 작성하면 그 내용이 자동 답변된다.

아웃룩에서 메일을 받아보려고 하는데, POP3가 다운되어 반응하지 않을 때 다음과 같이 조정한다. inetd는 기본적으로 1분에 fork 할 수 있는 인스턴스가 40으로 제한되어 있으므로 이 값을 늘려줘야 한다. POP3 부분에서 nowait.200이나 적절한 수만큼 늘려주면 된다. nowait 뒤에 반드시 .(점)을 찍고 허용할 만큼의 POP 데몬의 수를 입력한다. 이후 iinetd를 재시작하면 적용된다.


A # vi /etc/inetd.conf
# Pop and imap mail services et al
#pop-2 stream tcp nowait root /usr/sbin/tcpd ipop2d
pop-3 stream tcp nowait root /usr/sbin/tcpd ipop3d
#imap stream tcp nowait root /usr/sbin/tcpd imapd


철통 보안 관리

① 현재 서버에서 사용하지 않고, 보안상 취약점이 있는 데몬에 대해 서비스를 중지한다.
② TCP Wrapper와 ipchains를 이용한다. 커널 2.4에서는 iptables를 이용해 각 서비스에 대해서 접속을 허락하거나, 제한한다.
③ 섀도우 패스워드를 반드시 이용한다.
④ su 권한의 사용을 특정 사용자만 가능하도록 정의한다.
⑤ 원격에서 루트 권한으로 접속할 수 없도록 한다.
⑥ 지속적으로 패치한다.


echo 1> /proc/sys/net/ipv4/icmp_echo_ignore_all

다시 응답하게 하려면 다음과 같이 실행하면 된다.

echo 0> /proc/sys/net/ipv4/icmp_echo_ignore_all

보통 백도어 파일은 rm 명령으로도 삭제되지 않는다. 속성이 있을 경우 다음과 같이 삭제 한다.

# lsattr /usr/sbin/in.fingerd
lsattr 1.12, 9-Jul-98 for EXT2 FS 0.5b, 95/08/09
-----a-- /usr/sbin/in.fingerd
==> a 속성이 있음을 확인

chattr -a /usr/sbin/in.fingerd
chattr 1.12, 9-Jul-98 for EXT2 FS 0.5b, 95/08/09
==> -a로 속성을 해제

# lsattr /usr/sbin/in.fingerd
lsattr 1.12, 9-Jul-98 for EXT2 FS 0.5b, 95/08/09
-------- /usr/sbin/in.fingerd
==>해제


lpd는 내부와 원격 프린트 작업을 수행하는 BSD 라인 프린터 데몬이다.
lpd 데몬의 접근 권한을 가지고 있는 내부 시스템이나 원격 시스템의 사용자가 특별히 변형된 불완전한 프린트작업을 요청하고 이어서 프린터 큐의 디스플레이를 요청하게 되면 해당 시스템에 버퍼 오버플로우를 일으킬 수 있다. 결국 관리자 권한으로 내부 시스템에 공격 코드를 실행시킬 수 있게 된다. 따라서 패치를 해주거나 서비스를 하지 않는다면 데몬을 중지하는 것이 좋다.

BIND 4.x, 8.x에서 문제가 검출되었다. BIND 8 버전에서는 트랜잭션 시그너쳐(TSIG) 핸들링 코드에 버퍼오버플로우 취약점을 포함하고 있다.
유효한 키를 포함하지 않는 TSIG를 발견하는 경우 BIND 8 버전에서는 에러응답을 보내기 위한 코드를 실행하게 되며, 이때 발생하는 변수 초기화 방식의 차이에 의해 해당 취약점이 발생하게 된다. DNS 시스템에 대한 요청 접근만으로 해당 취약점을 발생시킬 수 있으므로 이로 인한 위험성은 크게 된다.
BIND 4 버전에서는 nslookupComplain( ) 내부에 있는 문자 배열(syslog 를 위한 에러 메시지 작성 버퍼)에 대해 버퍼 오버플로우 취약점을 포함하고 있다. 특수한 포맷 형태를 가진 쿼리를 전송함으로써 해당 취약점을 발생시킨다.
또한 nslookupComplain( ) 내부에 있는 문자 배열(syslog를 위한 에러 메시지 작성 버퍼)에 대해 입력 검증(input validation) 취약점을 포함하고 있다. 이것은 특수한 포맷 형태를 가진 쿼리를 전송함으로써 입력 검증 취약점을 발생시킨다.
BIND 4,8 버전에서는 해당 서버가 쿼리를 처리하는 동안 정보가 누출(information leak)될 수 있는 취약점을 포함하고 있다. 특수한 포맷 형태를 가진 쿼리 전송을 통해 공격자가 프로그램 스택에 접근할 수 있게 함으로써 해당 취약점을 발생시킨다.
해결책은 BIND 버전은 8.2.3 이상이나 9.1버전으로 업그레이드하는 것이다. 이것은 해결책이 아니라 시스템 관리자가 반드시 해야 할 일이다.

장애 발생시 복구

대부분 정전이 발생한 후에도 시스템은 정상적으로 부팅되며 파일시스템도 자동으로 check하지만 간혹 관리자가 수동으로 해주어야 하는 경우가 발생한다. 리눅스가 다운 되었을때 보통 Power OFF를 하는데, 이때 문제가 발생할 수 있으므로 Magic SysRq라는 것을 이용하여 안전하게 재부팅하는 방법을 이용한다.
Magic SysRq key란 시스템의 제어가 불가능한 상태(일반적으로 ‘다운’되었다고 한다)에서도 제어를 가능하게 해주므로 커널 컴파일시 Kernel hacking ---> [*] Magic SysRq key를 체크해야 한다. Magic SysRq key를 사용하려면 다음과 같이 /proc/sys/kernel /sysrq 값을 1로 만들어야 한다.

# echo 1 > /proc/sys/kernel/sysrq
lilo: linux init=/bin/sh

그러면 커널이 뜨고 나서 바로 shell prompt ‘#’가 나타난다. 이때에는 filesystem도 read only로 마운트 되고, 동작하는 deamon process도 전혀 없는 상태가 된다. 그 상태에서 수동으로 모든 파일 시스템을 체크한다.

# fsck [-t ext2] 장치명
# e2fsck 장치명

위의 명령 사용시 문제가 생긴 블록의 수정 여부를 묻게 되는데 ‘y’를 선택하고 만약 수정여부를 묻는 질문이 많다면 -y 옵션을 사용하여 자동으로 ‘y’를 선택하게 할 수 있다.

# e2fsck -y 장치명

Ctrl-Alt-Del로 리부팅하면 아주 심하게 깨지거나, 디스크에 이상이 있지 않는 한 복구가 된다.
Posted by 큰바우
:
 

리눅스 시스템 모니터링 시스템 최적화


글쓴이 : 문태준

대한매일 뉴스넷 서비스지원팀장 (http://www.kdaily.com, http://seoul.co.kr)

taejun@tunelinux.pe.kr

http://tunelinux.pe.kr, http://database.sarang.net 운영자



0. 들어가며

이글은 효율적으로 시스템을 모니터링하고 어떻게 리눅스 서버를 최적화할 수 있을까에 대해서 다룬다.


첫 번째 장에서는 현재 시스템이 어떻게 운영되고 있고 어디에서 문제가 생기고 있는지를 알기 위한 시스템 모니터링에 대해서 설명을 한다. 시스템관리의 출발은 현재의 상태를 제대로 파악하고 여기에서 시스템을 최적화하기 위해 무엇을 해야하는지 파악을 해야하는 것이다. 프로세스, 메모리, 디스크 I/O와 네트워크의 모니터링에 대해서 알아본다.


두 번째 장에서는 운영체제가 부팅을 하면서부터 시작하는 작업인 로그파일 기록에 대하여 알아본다. 현재의 시스템에서 발생하고 있는 모든 작업은 로그를 통해 기록을 남고 문제가 발생했을 경우 가장 먼저 해야 할 작업이 로그분석작업이다. 이와 더불어 계속 불어나는 로그파일을 어떻게 효율적으로 처리할 수 있는 지에 대해서 알아보겠다.


세 번째 장에서는 앞의 두 강좌를 통해 시스템의 활동을 분석하는 방법에 대해서 배운 것을 기초로 하여 시스템 모니터링을 자동화하는 방법에 대하여 설명을 할 것이다. 시스템관리자가 해야 할 역할이 많은데 언제나 사무실에 앉아서 top만 치고 있을 수는 없지 않은가. 또 시스템이 한 대라면 모르겠지만 적게는 몇 대에서 수십, 수백대가 되는 경우 시스템관리를 한다고 애인까지 만나지 못하고 더운 여름을 전산실 에어컨과 함께 밀월을 즐길 수는 없을 것이다.


네 번째 장에서는 운영체제의 설치 및 서비스를 위한 프로그램 설치과정과 관련되어 필요한 최적화 방법에 대해서 설명을 할 것이다. 효율적인 서비스를 위해서는 설치 과정부터 필요한 프로그램만 설치하고 불필요한 프로그램을 제거를 하여 시스템의 성능은 물론 보안으로부터 대처를 할 수 있을 것이다.


마지막 장에서는 커널 차원에서의 튜닝과 보안에 대해서 다루겠다. 커널은 운영체제의 핵심부분으로 메모리 관리, 프로세스 관리, 파일 시스템 관리 등 모든 작업을 배후에서 처리하고 있는 부분이다. 그러므로 커널의 작동 원리를 이해하면 현재의 시스템에 대해서 좀 더 깊은 지식을 가질 수 있고 시스템 성능과 관련한 여러 가지 옵션들을 효율적으로 조정하여 같은 하드웨어를 가지고도 더 좋은 성능을 낼 수 있다.



기본기를 다지자

전산학의 빅5는 컴퓨터 구조론, 운영체제, 자료구조와 알고리즘, 프로그래밍 언어론 및 컴파일러, 데이터베이스론이라고 흔히 이야기를 한다. 소프트웨어 개발자의 경우 단순하게 문법을 잘 외운다고 해서 프로그래밍 능력이 높은 것은 아니다. 효율적으로 프로그램을 설계하고 적절한 알고리즘을 사용하는 것이 중요하고 하드웨어와 운영체제에 대해서 더 깊이 알고 있을수록 뛰어난 프로그램을 작성할 수 있다. 시스템 관리자의 경우도 여기에서 벗어날 수 없다. 운영체제가 어떤 방식으로 작동을 하고 있는지, 어떻게 인터넷이라는 무한한 공간에서 컴퓨터가 자료를 주고 받는지에 대한 기본 지식이 풍부할수록 시스템 관리도 단순한 세팅에서 벗어나 제대로 된 시스템 관리를 할 수가 있는 것이다. 물론 여기 글을 쓴 것처럼 그 중요성을 알고 있지만 생각만큼 쉬운 작업은 아니고 많은 노력이 필요한 작업이며 이 글을 쓰는 필자도 운영체제 및 네트웍에 대해서 뛰어난 고수는 아니다. 그렇지만 계속 발전하기 위해서는 기본기가 탄탄해야 한다는 생각을 가지고 있으며 다른 사람들과 같이 노력을 해 가고자 한다.


본 글과 관련하여 궁금한 점은 본인이 운영하는 사이트 등을 통하여 같이 논의를 했으면 좋겠다. 글을 시작하기에 앞서 본인이 이러한 글을 정리할 수 있도록 수많은 자료를 제공해준 인터넷의 수많은 사람들에 대하여 감사한 마음을 전한다. 개인의 지식은 한정될 수 밖에 없지만 네트웍을 통해 공유한 지식은 전인류의 자산이 될 것이다.





1. 시스템 모니터링 하기

- 시스템이 어떻게 움직이고 있는가?


1. 시스템 모니터링 결과에 대해서 정확히 알고 있자

ㅇ 메모리가 왜 이리 모자라지? - free 에 대하여

밤에 잠을 자고 있는데 사무실에서 급하게 전화가 왔다. 웹서비스가 엄청 느려져서 도저히 웹사이트를 볼 수가 없다는 것이다. 잽싸게 일어나서 컴퓨터를 켰다. 원격으로 접속을 해서 서버를 관찰한다. 가장 먼저 무엇을 해야할까? 어디에서 시스템이 느려지고 있는지 찾아야한다. 그리고 평상시의 상태와 비교를 해야한다. 시스템 관리자라면 흔히 일어나는 경우이다. 시스템 관리의 첫 출발은 평상시에 계속 시스템의 상태를 파악하고 모니터링 결과를 비교하는 작업이다. 또한 나온 결과를 제대로 파악하고 있어야하는데 주기적으로 시스템을 모니터링해놓고도 그 결과를 엉뚱하게 해석한다면 전혀 다른 결과를 초래할 수 있다.


예를 한번 들어보자. 리눅스에서 메모리를 점검하기 위해 흔히 free를 사용한다. 그런데 free의 결과를 잘못 이해하는 경우가 상당히 많고 필자도 마찬가지였다. 아래 결과를 보자. 512M의 메모리를 가진 시스템이다.



$ free

             total       used       free     shared    buffers     cached

Mem:        513368     503180      10188          0       3772     332740

-/+ buffers/cache:     166668     346700

Swap:      1028152      84908     943244



이상하게 쓰는 것도 없는데 513M에서 현재 사용하는 것이 503M이다. 아무래도 시스템에 문제가 생겼나해서 재부팅을 했는데 조금 지나자 또 대부분의 메모리를 used에서 잡아먹는다. 에라 모르겠다 메모리를 512M 더 추가시키자. 농담이 아니라 실제로 충분히 발생할 수 있는 상황이다.


디스크를 읽는 일은 메모리에 비해서 아주 느리다. 수많은 사람들이 접속해서 ls 명령어를 모두 디스크에 읽어서 실행을 한다면 그 시스템의 속도가 아주 느려질 것이다. 물론 여기서는 ls라는 간단한 명령을 말했지만 시스템의 자원을 엄청 잡아먹는 프로그램이라면 문제가 또 달라질 것이다. 이런 경우 디스크에서 한번 읽어들인 정보를 메모리에 일정기간 보관하고 있다면 처음 읽을때만 속도가 느리지 이후에는 전반적으로 빨라질 것이다. 이것을 가르켜 디스크 버퍼링이라고 하며 이런 목적으로 사용되는 메모리가 위에서 나오는 버퍼 캐쉬이다.**주1 (실제로 버퍼 캐쉬는 파일을 버퍼링하는 것은 아니고 디스크 입출력의 가장 작은 단위인 블록을 버퍼링한다. 블록 디바이스 드라이버가 사용하는 데이터 버퍼를 가지고 있는 것이다) 만일 캐쉬의 크기가 고정되어 있다면 그 크기가 너무 커도 메모리 부족현상이 생길 수 있을 것이고 지나친 스와핑을 발생하게 해서 시스템이 느려질 가능성이 크다. 리눅스에서는 자동적으로 모든 램의 빈 공간을 버퍼 캐쉬로 사용하여 메모리를 효율성을 높이고 있으며 프로그램에서 많은 메모리를 필요로 하는 경우에는 자동으로 캐쉬의 크기를 줄인다. 그렇다면 위에서 실제로 사용가능한 메모리는 free+buffers+cached 이다. -/+ buffers/cache: 이 줄이 이러한 내용을 반영하고 있다. 일반적인 리눅스 시스템관리와 관련된 서적에는 이 부분에 대하여 지적을 한 곳이 거의 없으며 맨페이지에도 이런 설명은 아직 찾지 못했다. 운영체제와 커널의 원리에 대해서 모른다면 같은 결과를 놓고도 정말 엉뚱한 분석을 할 수 있는 것이다. 위의 내용을 아는 분이라면 모르겠지만 이 글을 보는 사람들중에 위의 내용을 몰랐던 사람들은 정말 모르고 있었구나 하는 생각이 들지 않을까?



2. 현재 시스템의 문제를 찾자

시스템의 성능은 현재의 시스템 자원을 여러 가지 프로그램들의 요청에 대하여 얼마나 효율적으로 적용을 하는가에 달려있다. 요즘처럼 인터넷이 보편화된 상황에서 네트워크도 중요한 부분이기는 하지만 일반적으로 성능에서 가장 중요한 시스템 자원은 CPU, 메모리, 디스크 입출력이다. 그래서 위의 부분들을 중심으로 성능에 문제가 생기기 전에 미리 시스템을 분석하는 것이 중요하다. 시스템에 문제가 생긴다면 다음을 먼저 점검해보자


ᄋ CPU 문제 점검 - top, ps, uptime, vmstat, pstree 등

ᄋ 메모리 문제 점검 - free, vmstat 등

ᄋ 메모리에 문제가 없다면 디스크 I/O 점검 - df, du, 쿼타 등

ᄋ 디스크와 메모리에 문제가 없는데도 시스템에 문제가 생기면 CPU의 오버헤드에 문제가 있을 가능성이 크다

ㅇ 네트웍 문제 점검 - netstat, ping, traceroute, tcpdump 등


3. 사전 점검 사항

시스템이 정상적으로 작동하고 있을 때 정기적으로 모니터링을 해 두어야 시스템에 문제가 생겼을 때 대처를 할 수 있다. 아래를 참고로 하여 주기적으로 시스템 모니터링 결과를 모아두자.


ᄋ 주요 사용자들한테 성능이 괜찮다는 동의를 먼저 얻어야한다. 그리고 시스템 성능을 계속 유지할 수 있도록 정기적으로 점검한다.

ᄋ 시스템 accounting 프로그램을 이용한다. 시스템에서 CPU, I/O, 메모리 집약적인 프로그램들을 알고 있어야한다. (**주2)


$ sa


   75563  169479.02re     510.44cp         0avio       506k

   14056     450.37re     448.85cp         0avio       497k   webalizer

     361   91931.12re      37.86cp         0avio      1355k   httpd*

     275       7.50re       5.38cp         0avio       402k   gawk

   14056     455.55re       4.95cp         0avio       438k   weblog

   14226     588.92re       2.57cp         0avio       437k   sh

      11      18.88re       2.45cp         0avio       332k   slocate

     162     670.85re       1.46cp         0avio       666k   in.telnetd

    2298      45.83re       1.09cp         0avio      2858k   mysqld*

     325       0.86re       0.76cp         0avio       642k   ps

     358    1185.61re       0.66cp         0avio       454k   bash

    1419       0.48re       0.47cp         0avio       283k   rmmod


accounting 결과 예제



ᄋ vmstat 등의 프로그램을 이용 I/O연산이 얼마나 분산되어있는지, CPU가 작동하지 않고 노는 시간(idle)은 얼마인지, 정상적인 부하가 걸릴 경우 메모리를 얼마나 사용하고 있는지 확인한다.


주기적으로 시스템 상황을 자동으로 모니터링하는 방법에 대해서는 세 번째 강좌에서 설명을 할 예정이다.




4. 문제가 발생했을 경우의 대처 방법

시스템이 정상적으로 작동하고 있을때 제대로 모니터링을 하고 분석을 해 두었다면, 사용자가 불평하거나 문제가 터지기 않더라도 언제 시스템의 성능이 나빠질지 알 수 있다. 그러면 시스템에 문제가 발생하였을 경우에는 어떻게 대처를 해야 할까?


ᄋ 어떤 프로그램을 실행하고 있으며 어떻게 사용하고 있는가? 현재 시스템에서 주요하게 제공하는 서비스는 어떤 것인가? 예를 들어 NFS를 통해 파일에 접근을 한다면 네트웍 성능이 떨어지는게 문제의 한 부분이라는 것을 알 수 있다. 웹서비스를 한다면 시스템 자체의 부하가 아니라 네트웍 회선의 문제로 속도가 느려질 가능성도 있다.

ᄋ uptime을 이용하여 시스템의 부하를 확인한다. 시스템의 부하가 어떤 추세로 움직이고 있고 어느 정도 수치로 작동하는지 확인을 한다. 웹서비스의 경우 보통 낮시간대에 접속이 폭주하므로 S자 형태로 시스템 부하가 변화될 것이다. 그런데 최대 접속할 시간이 아닌데도 시스템의 부하가 높아진다면 불필요한 프로그램이 계속 돌면서 시스템의 자원을 소비할 가능성도 있고 DOS 공격 등을 받고 있을 가능성도 크다.


$  uptime

  9:23pm  up 61 days,  5:23,  1 user,  load average: 0.02, 0.05, 0.00



ᄋ ps와 top를 활용한다.

- 디스크 액세스나 페이징을 기다리고 이는 프로세스가 있는가? 그렇다면 I/O와 메모리를 점검하자. 리눅스에서 프로세스 대기 상태는 인터럽트 허용과 인터럽트 금지의 두가지 형태가 있다. 세마포어를 기다리거나 파일을 읽을 수 있게 되길 기다리는 것처럼 자원을 기다리는 일반적인 대기상태는 대개 인터럽트로 처리가 가능하다. (인터럽트가 허용되는 sleep 상태는 ps,top 등에서 S로 나타난다.) 그렇지만 인터럽트가 금지되는 대기상태는 스왑파일에서 메모리로 페이지를 읽어들이는 것과 같이 임계지역에서 일이 끝마치기를 기다리고 있는 상태이다. 프로세스 상태에서 D 는 uninterruptible sleep로서 page fault 등을 의미하며 page fault 등을 통해 I/O중인 상태를 나타낸다. W는 has no resident pages를 의미하며 프로세스가 스왑아웃된 상태를 나타낸다. (W는 커널 프로세스에 대해서는 정확히 동작을 하지않는다.

- CPU와 메모리를 가장 많이 사용하는 프로세스를 찾으면 부하를 분산시키는데 도움이 될 것이다.


$ ps auxw

USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  1120   68 ?        S    Jun17   0:06 init [3]

root         2  0.0  0.0     0    0 ?        SW   Jun17   0:00 [keventd]

root         3  0.0  0.0     0    0 ?        SW   Jun17   0:00 [kswapd]

root         4  0.0  0.0     0    0 ?        SW   Jun17   0:00 [kreclaimd]

root         5  0.0  0.0     0    0 ?        SW   Jun17   0:32 [bdflush]

root         6  0.0  0.0     0    0 ?        SW   Jun17   0:02 [kupdated]

root       351  0.0  0.0  1164  284 ?        S    Jun17   0:01 syslogd -m 0

root       360  0.0  0.0  1728  356 ?        S    Jun17   0:00 klogd

root       388  0.0  0.0  1156  220 ?        S    Jun17   0:00 inetd

root       402  0.0  0.2  3824 1452 ?        S    Jun17   3:09 /usr/sbin/snmpd

named      416  0.0  0.3  3376 1904 ?        S    Jun17   0:27 named -u named




$ top

  7:34pm  up 14:19,  3 users,  load average: 1.20, 0.54, 0.20

57 processes: 53 sleeping, 4 running, 0 zombie, 0 stopped

CPU states: 94.6% user,  5.3% system,  0.0% nice,  0.0% idle

Mem:   513368K av,  321260K used,  192108K free,       0K shrd,    9208K buff

Swap: 1028152K av,  115000K used,  913152K free                  270924K cached


  PID USER     PRI  NI  SIZE  RSS SHARE STAT  LIB %CPU %MEM   TIME COMMAND

12436 root      20   0  6428 6428  1564 R       0 13.1  1.2   0:00 cc1

3570 nobody    12   0 11148 6140  5016 R       0  2.5  1.1   0:09 httpd

12435 root       8   0  1528 1528   388 S       0  1.3  0.2   0:00 cpp

4185 root       9   0   512  328   312 S       0  0.3  0.0   0:01 sshd2

11364 taejun    10   0   876  876   680 R       0  0.3  0.1   0:00 top

    1 root       8   0   120   68    68 S       0  0.0  0.0   0:04 init

    2 root       9   0     0    0     0 SW      0  0.0  0.0   0:00 keventd

    3 root       9   0     0    0     0 SW      0  0.0  0.0   0:03 kswapd

    4 root       9   0     0    0     0 SW      0  0.0  0.0   0:00 kreclaimd

    5 root       9   0     0    0     0 SW      0  0.0  0.0   0:01 bdflush

    6 root       9   0     0    0     0 SW      0  0.0  0.0   0:00 kupdated

  348 root       9   0   208  156   156 S       0  0.0  0.0   0:00 syslogd

  357 root       9   0   608    4     4 S       0  0.0  0.0   0:00 klogd

  371 root       8   0   180  124   120 S       0  0.0  0.0   0:00 crond



ᄋ vmstat를 이용한다. (vmstat 5 5)


$ vmstat 5 5

   procs                      memory    swap          io     system         cpu

r  b  w   swpd   free   buff  cache  si  so    bi    bo   in    cs  us  sy  id

3  0  0 115000 189428   9220 272608   1  28    10    36  108    25   2   0  98

1  0  0 115000 189972   9220 272680   0   0     0   205  196   416  95   5   0

1  0  0 115000 187060   9220 272740   0   0     0   157  156   229  95   5   0

2  0  0 115000 194852   9220 272856   0   0     0   149  142   229  96   4   0

Posted by 큰바우
:
http://linux-sarang.net/board/?p=read&table=tip&no=5712&page=&o[at]=s&o[sc]=r&o[no]=5711
### 부가 설명 ## split 에서 숫자를 세는 방식 우선 십진수와 형식을 비교해 봅니다. 
1자리수에서 2자리수로 넘어가는 형태 0 1 2 3 4 ... 9 10 11 ... aa ab ac ad ae ...
 az ba bb ... 여기서 a는 숫자 0, b는 1 ... z는 25가 되고 26가지가 됩니다.
 따라서 split에서 세는 방법은 26진수가 됩니다.(어찌 보면 당연한 것을 --;;) 
그렇지만 aa는 실제로 0이 아니라 1입니다. 그래서 실제로는 위의 형태가 아래처럼 
한자리씩 밀려나는 형태로 바뀝니다.
 0 1 2 3 4 ... 9 10 11 ... ? aa ab ac ad ay az aa 1 2 3 4 ... 25 26 27 
수식으로 표현하자면 split에서 사용되는 26진법은 십진수로 이런 방식으로 치환됩니다. 
yza --> (26^2 * 24) + (26^1 * 25) + (26^0 * 0) + 1 그런데 문제가 있습니다
. .... yx yy yz .. za .. zz 여기까진 문제가 없습니다만.. 
다음 숫자 baa 가 (이게 맞긴 한걸까 --;;) 만들어진다면... 
알파벳 순서로는 숫자의 순서가 뒤바뀌게 됩니다.
 그래서 split에서는 좀더 이상한(--;;)형태로 숫자를 셉니다. 
aa ab ac ... yz # 십진수로 650(25*26)까지 zaaa zaab zaac ... 
zyzz # + 25*26*26 zzaa zzab zzac ... zzyz # + 25*26 zzzaaa 
zzzaab zzzaac ... zzzyzz # + 25*26*26 . . .
 조금 변경해서 쓰면 
/ / / / / aa / aa / ac ... / yz z/aaa z/aab z/aac 
... z/yzz zz/ aa zz/ aa zz/ ac
 ... zz/ yz zzz/aaa zzz/aab zzz/aac ... zzz/yzz 
이렇게 일정한 패턴이 계속됩니다. 이제는 알파벳순과 숫자순서가 같게됩니다. 
세는 방식이 달라진 만큼 십진수로 바꾸는 방법도 조금 달라집니다. 
우선 "/" 앞에 있는 'z'의 갯수에 따라 이전 까지 있던 숫자가 달라지게 되는데..
 "/" 앞에 있는 z의 갯수를 zt라고 자연수라고 없으면 
: 25*26 * 0 + 25*26*26 * 0 # 0 + 0 = 0 z 
: 25*26 * 1 + 25*26*26 * 0 # 1 + 0 = 1 zz 
: 25*26 * 1 + 25*26*26 * 1 # 1 + 1 = 2 zzz 
: 25*26 * 2 + 25*26*26 * 1 # 2 + 1 = 3 . . . zt 
: 25*26 * (zt-(zt/2)) + 25*26*26 * (zt/2) # zt-(zt/2) + zt/2 = zt # zt/2 
에서의 나머지는 버립니다. 이렇게 되고 우선 z가 한 개면 
zaaa = (25*26*1 + 25*26*26*0) + (26^2*0 + 26^1*0 + 26^0*0 + 1) 
zyzz = (25*26*1 + 25*26*26*0) + (26^2*24 + 26^1*25 + 26^0*25 + 1) 
이됩니다. 좀 색다른 방식이어서 이것때문에 스크립트가 엄청길어졌습니다. 
그렇지만 두자의 숫자로 표현할 수 있는 것이 십진수는 100가지인데 반해 
split방식은 650개까지 표현 할 수 있다는데 의미를 두어야할 것 같습니다.
Posted by 큰바우
:

http://linux-sarang.net/board/?p=read&table=tip&no=5711&page=&o[at]=s&o[sc]=r&o[no]=5711

 

% 알림 시작 %
split의 카운트 방법이 바뀐 것 같습니다.
예전에는 카운트 횟수에 제한이 없었는데..
지금 살펴보니깐 zz까지 되는군요. --;
덕분에 열심히 짰었던 스크립트가 쓸모 없게 되었군요.
뭐 어차피 그렇게 필요한 스크립트는 아니지만 --;;
% 알림 끝 %



## tar.gz -> tar.bz2 형식으로 하려면 (확장자만 바꾸는 것 아님 --;;)

우선 하드 공간이 넉넉하면

$ gzip -d some.tar.gz
$ # tar 파일이름을 확인한 후
$ bzip2 some.tar

하드 공간이 부족하면

$ gzip -dc some.tar.gz | bzip2 -f - > some.tar.bz2

저는 이전에 tar.bz2 를 tar.gz 으로 바꾸어야 하는 상황이 있어서 반대로 이용했습니다. bzip2가 없는 시스템에서 풀어야 했거든요. --;;


## tar + gzip(or bzip2) + split 으로 다중 압축 아카이브 만들기 (거창하다.. --;;)

split을 이용한 팁은 이곳에서 찾았습니다.

다시 한 번 간략하게 쓰면

tar + gzip 으로 하고.. 50메가씩 나누고 싶다면...

$ tar -czvf - /lsn | split -b 50m - lsn.tar.gz_

이렇게 하시면

lsn.tar.gz_aa
lsn.tar.gz_ab
lsn.tar.gz_ac
.
.

이런 순으로 파일을 생성시킵니다.

첫번째 파일은 크기가 지나치게 작지 않다면

file 명령어로 확인해보면 gzip된 파일이라고 알려줍니다.
나머젼 data로 나오고요.

그래서 lsn.tar.gz 이라는 텍스트 파일을 만들어서 약간의 정보를 적어두시면 더 도움이 되리라 생각합니다.(처음 이 파일을 접한 사람을 아리송하겠죠?)


풀려면

$ cat lsn.tar.gz_* | (cd 풀고싶은곳; tar -xzvf - )

문제는 lsn.tar.gz_* 은 lsn.tar.gz_aa lsn.tar.gz_ab ... 이런식으로 확장이 되어 cat에게 넘겨주는데요. 이 순서가 반드시 본래 파일의 byte order로 되어 있어야 합니다. split에 생성된 파일은 알파벳 순으로 정렬하면 그 순서가 맞습니다.


마지막으로 제가 만든 쉘스크립트 중 가장 긴 길이를 자랑하는(정말 읽기 짜증나는) mtar.sh 입니다.

$ mtar.sh -czvf lsn.mtgz /lsn -b 50m

하시면

자동으로

lsn.mtgz_aa
lsn.mtgz_ab ...

이렇게 생성을 시켜주고

lsn.mtgz 이라는 이름으로
약간의 정보와 함께 자동으로 파일을 풀 수 있도록해주는 쉘랩퍼(스크립트)를 만들어줍니다.

압축을 풀 때는

$ chmod +x lsn.mtgz
$ cd 풀고싶은곳
$ /lsn.mtgz가있는곳/lsn.mtgz

이렇게 하시면

빠진 파일이 없는지 체크하고, 이상이 없으면 파일을 풉니다.

아직 테스트 중입니다. --;;
만일 쓰시려면 각오하시고 쓰십시오. 적어도 하드 포맷은 안될 것입니다. --;;
테스트 결과 ksh에서도 동작하는 듯 보입니다. --;;

느끼는 건데 쉘스크립트에서는 bash만한 것도 없네요.

mtar.sh


텍스트로 보기
mtar.sh


p.s) chmod +x mtar.sh # 필수 --+

 

Posted by 큰바우
:

# httpd.conf

DefaultLanguage kr 로바꾸고

LanguagePriority kr en da nl fr de el it ja no pl pt pt-br ltz ca es sv tw 순서 바꾸고

AddDefaultCharset EUC-KR 추가

Posted by 큰바우
:

[Linux] eth0 설정방법

os/Linux 2004. 2. 2. 09:49 |
시스템에 기본적으로 설치된 아래의 명령들을 사용하여 네트워크가 정상적
으로 작동하지 않는 경우 여러 가지 테스트를 해볼 수 있다.
/etc/sysconfig 디렉토리 밑에 하드웨어에 대한 정보가 나오는데 이더넷
카드가 여러 개 꽂혀 있다면 ifcfg-eth1, ifcfg-eth2 식으로 확인할 수 있
다.

/etc/sysconfig/network-scripts/ifcfg-eth0

#cat ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static /* 정적 아이피 */
BROADCAST=211.47.64.255
IPADDR=211.47.64.80
NETMASK=255.255.255.0
NETWORK=211.47.64.0
ONBOOT=yes /* 부팅시 자동인식 */

사용하는 IP를 변경하거나, 새로운 네트워크 카드 추가시에는 ifcfg-eth0
파일을 수정한 후에 반드시 ifdown ifcfg-eth0, ifup ifcfg-eth0 명령을
실행해 주어야 변경된 IP가 적용된다. 또는 /etc/rc.d /init.d/network
restart를 실행해 주어도 된다.
Posted by 큰바우
:
http://www.wowlinux.co.kr/knowledge/qnaview.html?id=69019&view=1&db=qna&gpage=1


오라클 9i(Oracle9i (9.2.0)) 와 7.3 Paran R2 설치 설명서

작성자: 김효준
직업: 본인도 모름
연락처: jk@jktech.net
설치환경
서버: 7.3 Paran R2(레드헷 7.x 버전에서는 거의 설치 가능하다고 믿음 8.0에는 아직 못 해 봤음.)
오라클 버전: Oracle9i Database Release 2 Enterprise/Standard Edition for Intel Linux
오라클 받는 주소: http://otn.oracle.com/software/content.html
오라클 화일명:
lnx_920_disk1.cpio.gz (553,607,967 bytes)
lnx_920_disk2.cpio.gz (588,817,480 bytes)
lnx_920_disk3.cpio.gz (442,135,815 bytes)
설치방법: 여러가지 설치 방법이 존제하지만 쉽게 리눅스 시스템에 직접(원격이 아닌 로칼로)
설치한다. 특히 다운받은 오라클 파일을 시디로 만들지 않고 압축을 푼 후에 집접 설치 하는 방식이다.

들어가기전에.
몇년전 처음으로 오라클 8i를 리눅스(레드헷 6.2)에 성공적으로 설치를 했습니다.
그리고 몇 달후 릴리스된 레드헷 7버전에 오라클 8i를 인스톨 하면서 엄청난 삽질을 동반한
낙심에 고통받다가 오라클 사이트에서 제공하는 포럼에서 레드헷 6.2버전에 오라클을 깔고
통째로 레드헷 7에다 카피를 하는 방법을 읽게되었습니다.
그리고 그런방식으로 오게 되었습니다.
솔직히 오라클 서버를 설치하는것은 거의 공포에 가깝습니다.
깔기도 전에 게시판의 비명소리들을 보면서 기가 죽으니깐요....
거기다 아직까지 확실히 레드헷 7.3(파란 R2)에 성공해서 올라온 메뉴얼이 없기에 망설이다가
http://www.puschitz.com/OracleOnLinux.shtml 사이트에서 Werner Puschitz씨가 적어놓은
메뉴얼을 보면서 깔기로 마음 먹었습니다.
아무조록 이 설치 메뉴얼을 보고 모두다 성공하시길 바라며 즐거운 리눅서의 삶을 영위하시가 바랍니다.


다음의 주소로 가서 오라클 파일을 받는다.
http://otn.oracle.com/software/products/oracle9i/htdocs/linuxsoft.html
3개의 오라클 파일들을 편한곳에(당근 오라클을 설치할 리눅스 서버...)에 저장한다.

저장한 디렉토리에서 받은 파일들을 다음과 같이 압축해제한다.
zcat lnx_920_disk1.cpio.gz | cpio -idmv
zcat lnx_920_disk2.cpio.gz | cpio -idmv
zcat lnx_920_disk3.cpio.gz | cpio -idmv

****************시스템 설정!******************
오라클 사에서 제공하는 리눅스 서버는 최소한 512MB의 메모리와 이의 두배에 또는 같은 양의 swap space가
필요하다고 기술하고 있습니다(최소 400MB의 swap space)

#grep Mem /proc/meminfo

필자의 컴퓨터
Mem:  261107712 257212416  3895296        0 54464512 178733056
MemTotal:      254988 kB
MemFree:          3804 kB
MemShared:          0 kB

다음의 명령으로 시스템의 스왑스페이스를 알아본다.
#cat /proc/swaps

필자의 컴퓨터
Filename                        Type            Size    Used    Priority
/dev/hda2                      partition      1052248 37752  -1

오라클을 설치하면서 가장 많이 일어나는 문제중 하나가 공용메모리 문제인것 같다.
다음의 명령문을 루트의 권한으로 실행하여 임시적으로 최대 공용 메모리를 만든다.
# cat /proc/sys/kernel/shmmax
33554432
# echo `expr 1024 * 1024 * 1024` > /proc/sys/kernel/shmmax
# cat /proc/sys/kernel/shmmax
1073741824


The Oracle Universal Installer requires up to 400 MB of free space in the /tmp directory. If you do not have enough space in the /tmp directory,  you can temporarily create a tmp directory in another filesystem. Here is how you can do this:
오라클 사에서 요구하는 사향중 하나가 /tmp 의 크기가 최소 400MB 이다. 필자는 그 이상 이였기에 이 절차는 거치지 않았다.
만약 본인의 시스템에 /temp의 크기를 조정해야 한다면 루트의 권한으로 다음과 같이 한다.
mkdir /<AnotherFilesystem>/tmp
chown root.root /<AnotherFilesystem>/tmp
chmod 1777 /<AnotherFilesystem>/tmp
export TEMP=/<AnotherFilesystem>/tmp          # used by Oracle
export TMPDIR=/<AnotherFilesystem>/tmp        # used by Linux programs like the linker "ld"

그리고 오라클의 설치가 끝난 후 다음과 같이 실행하여 원상태로 복구한다.(아직 설치도 않했는데.. ^^)
rmdir /<AnotherFilesystem>/tmp
unset TEMP
unset TMPDIR

오라클 설치에 필요한 파일은 다음과 같다.
gcc
cpp
glibc-devel
kernel-headers
binutils

# rpm -q gcc cpp glibc-devel kernel-headers binutils 으로 확인
만약 이중에 설치되지 않은 것이 있다면 http://rpmfind.net에서 최신 rpm으로 설치한다.
필자의 리눅스 서버에는 kernel-headers가 설치되어 있지 않았고
kernel-headers 인스톨시 glibc-kernheaders-2.4-7.14와 충돌 하여 에러가 났다.
만약 여러분의 시스템에도 이러한 문제가 있다면 필자처럼
#rpm -e --nodeps glibc-kernheaders-2.4-7.14
로 삭제후 설치하기 바란다.
참고로 rpm 설치의 명령어는
#rpm -i 페케지이름
이다.

자바 설치
Download JDK 1.3.1 or Blackdown 1.1.8_v3
http://java.sun.com

루트의 권한으로 다음과 같이 설치한다.
#bzip2 -dc jdk118_v3-glibc-2.1.3.tar.bz2 | tar xf - -C /usr/local
#ln -s /usr/local/jdk118_v3 /usr/local/java

자 이제 오라클 설치를 위한 리눅스 서버 준지가 끝이 났다.
이제부터 오라클을 설치하기 위해 본격적인 작업에 들어가 보자.

우선 루트의 권한으로 오라클을 설치할 사용자 계정부터 만들어야 한다.

#groupadd dba
#groupadd oinstall
#useradd -g oinstall -G dba oracle
#passwd oracle

오라클이 설치될 디렉토리를 만들자.
중요한것은 오라클이 설치될 곳에 충분한 공간이 있는지 확인해야한다.

루트의 권한으로 다음과 같이 명령어를 실행한다

#mkdir /opt/oracle
#mkdir /opt/oracle/product
#mkdir /opt/oracle/product/9.2.0
#chown -R oracle.oinstall /opt/oracle

#mkdir /var/opt/oracle
#chown oracle.dba /var/opt/oracle
#chmod 755 /var/opt/oracle

마지막 작업으로 우리가 만든 oracle계정으로 로그인 후
다음과 같은 명령문을 실행한다.
필자는 /home/oracle/.bash_profile 에 밑의 내용을 복사했다.
***가장 중요한것은 ORACLE_SID 항목이다.
지금은 중요하지 않지만 오라클 인스톨이 끝나고 DBCA(database configuration assistant)로
데이타베이스를 작성시 SID항목을 작성하는 절차가 있다. 이때 적어놓은 것을 꼭 ORACLE_SID
에 적어야 한다. 그렇지 않으면 오라클 서버가 구동되지 않는다.


# Oracle Environment
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=/opt/oracle/product/9.2.0
export ORACLE_SID=test #중요! 나중에 꼭 바꾸어야 합니다.
export ORACLE_TERM=xterm
#export TNS_ADMIN= Set if sqlnet.ora, tnsnames.ora, etc. are not in $ORACLE_HOME/network/admin
export NLS_LANG=AMERICAN;
export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export LD_LIBRARY_PATH
export LANG=c

# Set shell search paths
export PATH=$PATH:$ORACLE_HOME/bin

# CLASSPATH:
CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib
CLASSPATH=$CLASSPATH:$ORACLE_HOME/network/jlib



끝이 났으면 로그오프한 후에 다시 로그인 하자.

자 그럼면 아까 오라클 파일의 압축을 푼 곳으로 가서 시작을 하자.

#/앞축풀린디렉토리/Disk1/runInstalle

설치 관정은 오라클 사에서 한글로 제공하는 메뉴얼을 참고하기 바란다.
계인적으로 설치하는 것 까지 필자가 관섭할수는 없으니깐.... ^^;;
http://otn.oracle.co.kr/products/oracle9i/download/oracle9i_for_linux_install.doc

만약 인스톨 도중에 다음과 같은 에러가 나오면..
"Error in invoking target install of makefile /opt/oracle/product/9.2.0/ctx/lib/ins_ctx.mk"
필자도 이 에러가 나왔었다. 우선 아무것도 하지 말고 에디터로
$ORACLE_HOME/ctx/lib/env_ctx.mk 의 파일을 열고
"INSO_LINK =" 라는 곳을 찾아서 다음과 같이 끝에 추가한다.
$(LDLIBFLAG)dl
그리고 다시 Oracle Universal Installer로 돌아가서 retry를 클릭한다.

이 외의 에러가 발견되면
http://www.puschitz.com/OracleOnLinux.shtml
의 내용을 참조하기 바란다.

자 설치가 다 끝났다. 이제는
/opt/oracle/product/9.2.0/bin/ 에서 dbca 를 실행해서 데이타베이스를 만들어야 한다.
중요한것은 위에서 언급했듯이 데이타베이스 작성시 SID에 항목에 적어 놓은 항목을

ORACLE_SID=적어놓은SID이름
으로 해야 오라클 서버가 가동 된다는 것이다.
Posted by 큰바우
:

오류]Red Hat 8.0 + Oracle9i(9.2.0.1.0) 설치시 root.sh 실행 후 발생한 에러...
순 번
        
1216
        
등록일
        
2003/04/29
        
등록자
        
cocadio
        
조회
        
2000
내용
        
root.sh 실행후 다음과 같은 에러가 발생합니다.

오류: 의존성 문제로 인해 실패함:
libncurses.so.4 (은)는 orclclnt-nw_lssv.Build.71-1에서 필요로 합니다.
오류: 의존성 문제로 인해 실패함:
orclclnt = nw_lssv.Build.71-1 (은)는 orcldrvr-nw_lssv.Build.71-1에서 필요로 합니다.
오류: 의존성 문제로 인해 실패함:
orclclnt = nw_lssv.Build.71-1 (은)는 orclnode-nw_lssv.Build.71-1에서 필요로 합니다.
orcldrvr = nw_lssv.Build.71-1 (은)는 orclnode-nw_lssv.Build.71-1에서 필요로 합니다.
libscsi.so = nw_lssv.Build.71-1 (은)는 orclnode-nw_lssv.Build.71-1에서 필요로 합니다.
libsji.so = nw_lssv.Build.71-1 (은)는 orclnode-nw_lssv.Build.71-1에서 필요로 합니다.
오류: 의존성 문제로 인해 실패함:
orclclnt = nw_lssv.Build.71-1 (은)는 orclserv-nw_lssv.Build.71-1에서 필요로 합니다.
orclnode = nw_lssv.Build.71-1 (은)는 orclserv-nw_lssv.Build.71-1에서 필요로 합니다.
/bin/ksh (은)는 orclserv-nw_lssv.Build.71-1에서 필요로 합니다.
orclman-nw_lssv.Build.71-1 패키지는 이미 설치되어 있습니다.


Red Hat 7.3에서는 에러가 발생하지 않았는데...
7.3에는 libncurses.so.4가 있거든요,
그런데, 8.0에는 없고 libncurses.so.5는 있습니다.

제가 리눅스를 설치할때 뭘 잘못 설치한건지 아님 뭘 빠트린건가요?
답변 부탁드립니다.

답변순번
        
1
        
답변자
        
cocadio
        
답변일
        
2003-04-30 17:01:01.0
내용
        
설치시에 custom으로 설치하고,

Enterprise Edition Options 9.2.0.1.0 아래

Legato Networker Single Server 6.1.0.0.0은 선택하지 않는다.

답변순번
        
2
        
답변자
        
styx
        
답변일
        
2003-05-02 10:44:49.0
내용
        
Red Hat 8.0에도 ncurses4-5.0-9.i386.rpm이 있습니다. 설치하면 됩니다.

ftp://rpmfind.net/linux/redhat/8.0/en/os/i386/RedHat/RPMS/ncurses4-5.0-
9.i386.rpm

답변순번
        
3
        
답변자
        
siri
        
답변일
        
2003-05-04 21:27:36.0
내용
        
cocadio님 말씀대로 LSSV를 스킵하고 설치해보시고 꼭 나는 깔아야겠다 그러시면
거기 오류 맨끝에 나온대로 관련 사이트로 가보기시 바랍니다.

 

 

 


냥 참조만 하세요...

Red Hat Linux Advanced + Oracle9i(9.2.0.1)시 입니다...


1. gunzip lnx_920_disk1.cpio.gz 으로 해서 압축 해제

2. gunzip lnx_920_disk2.cpio.gz 으로 해서 압축 해제

3. gunzip lnx_920_disk3.cpio.gz 으로 해서 압축 해제

4. cpio -idmv < Linux9i_Disk1.cpio.gz 으로 해서 압축 해제

4. cpio -idmv < Linux9i_Disk2.cpio.gz 으로 해서 압축 해제

4. cpio -idmv < Linux9i_Disk3.cpio.gz 으로 해서 압축 해제


# 오라클을 위한 커널 설정 (/etc/rc.d/rc.local 파일에 추가해 준다)

echo 100 32000 100 100 > /proc/sys/kernel/sem

echo 2147483648 > /proc/sys/kernel/shmmax

echo 4096 > /proc/sys/kernel/shmmni

echo 2097152 > /proc/sys/kernel/shmall

echo 65536 > /proc/sys/fs/file-max

ulimit -n 65536

echo 1024 65000 > /proc/sys/net/ipv4/ip_local_port_range

ulimit -u 16384


# 오라클을 위한 설정 파일 (.bash_profile 또는 .bashrc에 추가해준다.)

export ORACLE_SID=idb920

export ORACLE_BASE=/app/oracle

export ORACLE_HOME=$ORACLE_BASE/product/idb920

export LD_LIBRARY_PATH=$ORACLE_HOME/lib

export NLS_LANG=AMERICAN_AMERICA.KO16KSC5601

export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data

export PATH=$PATH:.:$ORACLE_HOME/bin

export LANG=korean

umask=022

Posted by 큰바우
:
간단히 icmp로 장난치다가 ping도 만들어 봤습니다.
완전한 ping구현은 난이도상 공개해봤자 별로 초보분들에게는 도움이 될거 같지 않아서
어설픈 단계까지만 구현하였습니다. (Seq만 검사하는 것)
사실 이거가지고 linux.co.kr에 엄청난 ping을 잠시 걸어봤는데 8%정도 에러가 나네요. 제가 있는 곳에서는...

참고로 원래는 Packet 을 보낸는곳과 받는곳이 따로 비동기적으로 움직여야 할거라
판단되었지만 간단하게 하려고 합친거니까 분석 다 하신분덜은 그렇게 바꿔보세요.


- 주의사항
반드시 root유저만이 이것을 정상적으로 실행가능합니다.
또는 root실행권한을 실행퍼미션에 주어야 합니다.
일반 유저는 원래 ping기능을 사용할수 없나봅니다. 왜냐하면 RAW socket이니까~

- 컴파일 방법
bash# gcc -Wall -Werror -s -O2 -o ping ping.c

============= [ 절취선: ping.c ] =======================
/*
Copyright (c) Information Equipment co.,LTD.
Code by JaeHyuk Cho <mailto: minzkn@infoeq.co.kr >

- Simple is best ! (Sequence number check ping)

2003.1.20
*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

static int __MZ_ICMP_CheckSum__(void *s_Buffer, int s_Size)
{
int s_Return = 0;
if(s_Size & 1)s_Return += (int)((*(unsigned char *)s_Buffer)++);
s_Size >>= 1;
while(s_Size-- > 0)s_Return += (int)(*(((unsigned short *)s_Buffer)++));
if(s_Size == 1)s_Return += (int)(*(unsigned char *)(s_Buffer));
s_Return = (s_Return >> 16) + (s_Return & 0xFFFF);
s_Return += (s_Return >> 16);
return((~s_Return) & 0xffff);
}

int CORE_Ping(const char *s_HostName, unsigned int s_Index, unsigned int s_TimeOut)
{
int s_Return = (-1), s_Socket, s_SendBytes, s_RecvBytes, s_IsSelect;
struct protoent *s_ProtoEntry;
struct hostent *s_HostEntry;
struct sockaddr_in s_PingAddress, s_FromAddress;
socklen_t s_FromAddressLength;
struct icmp *s_ICMP;
struct iphdr *s_IPHeader;
unsigned char s_ICMP_Packet[ 60 + 76 + 56 ]; /* Packet assembly */
fd_set s_FD;
struct timeval s_TimeVal;
s_HostEntry = gethostbyname(s_HostName);
if(s_HostEntry)
{
memset((void *)(&s_PingAddress), 0, sizeof(s_PingAddress));
s_PingAddress.sin_family = AF_INET;
memcpy((void *)(&s_PingAddress.sin_addr), s_HostEntry->h_addr, sizeof(s_PingAddress.sin_addr));
memset((void *)(&s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet));
s_ICMP = (struct icmp *)(&s_ICMP_Packet[0]);
s_ICMP->icmp_type = ICMP_ECHO;
s_ICMP->icmp_seq = s_Index;
s_ICMP->icmp_id = getpid() & 0xffff;
gettimeofday((struct timeval *)(&s_ICMP_Packet[8]), (void *)0);
s_ICMP->icmp_cksum = __MZ_ICMP_CheckSum__((void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet));
s_ProtoEntry = getprotobyname("icmp");
s_Socket = socket(AF_INET, SOCK_RAW, s_ProtoEntry ? s_ProtoEntry->p_proto : 1);
setuid(getuid()); /* Who are you ? */
if(s_Socket >= 0)
{
s_SendBytes = sendto(s_Socket, (void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet),
MSG_NOSIGNAL, /* Ignore broken pipe */
(struct sockaddr *)(&s_PingAddress), sizeof(s_PingAddress));
if(s_SendBytes == sizeof(s_ICMP_Packet))
{
memset((void *)(&s_FromAddress), 0, sizeof(s_FromAddress));
s_FromAddressLength = sizeof(s_FromAddress);
memset((void *)(&s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet));
s_TimeVal.tv_sec = s_TimeOut, s_TimeVal.tv_usec = 0;
FD_ZERO(&s_FD); FD_SET(s_Socket, &s_FD);
s_IsSelect = select(s_Socket + 1, &s_FD, (fd_set *)0, (fd_set *)0, &s_TimeVal);
if(s_IsSelect > 0 && FD_ISSET(s_Socket, &s_FD) != 0)
{
s_RecvBytes = recvfrom(s_Socket, (void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet),
MSG_NOSIGNAL, /* Ignore broken pipe */
(struct sockaddr *)(&s_FromAddress), (socklen_t *)(&s_FromAddressLength));
}
else s_RecvBytes = 0;
if(s_RecvBytes >= 76)
{
s_IPHeader = (struct iphdr *)(&s_ICMP_Packet[0]);
s_ICMP = (struct icmp *)(&s_ICMP_Packet[ s_IPHeader->ihl << 2 ]);
if(s_ICMP->icmp_type == ICMP_ECHOREPLY)
{
/* TODO:
Packet check sum need
Time compute
Duplicate packet check
Send packet & Recv packet -> Two thread or alarm
*/
s_Return = (int)s_ICMP->icmp_seq;
}
}
}
close(s_Socket);
}
}
return(s_Return);
}

int main(int s_Argc, char *s_Argv[])
{
int s_Return, s_Check, s_Index, s_ErrorCount, s_IsError, s_Count;
fprintf(stdout, "MZ_Ping v0.0.1 - Code by JaeHyuk Cho < minzkn@infoeq.co.kr >\n\n");
if(s_Argc > 1)
{
s_ErrorCount = 0, s_Index = 1;
if(s_Argc > 2)sscanf(s_Argv[2], "%i", &s_Count);
else s_Count = 8;
do
{
s_Check = CORE_Ping(s_Argv[1], s_Index /* Request sequence number */, 4u /* Timeout 4 second */);
if(s_Check != s_Index)s_ErrorCount++, s_IsError = 1;
else s_IsError = 0;
fprintf(stdout, "Ping[%s]: %s (Seq %d->%d) - ERR=%d\n",
s_Argv[1], s_IsError == 0 ? "OK" : "LOSS", s_Index, s_Check, s_ErrorCount);
usleep(10000);
}while(s_Index++ < s_Count);
fprintf(stdout, "Total %d%% loss.\n", s_ErrorCount * 100 / s_Index);
s_Return = s_ErrorCount;
}
else
{
fprintf(stdout, "usage: ping <host> <count>\n");
s_Return = 0;
}
return(s_Return);
}

/* End of source */
Posted by 큰바우
: