안녕하세요
뚱보 프로그래머 입니다.
인터넷서버란?
1. 슈퍼 서버(inetd)
네트워크에 연결된 시스템에서는 서로 다른 시스템(서비스를 제공하는 시스템은 서버, 서비스를 제공받는 시스템은 클라이언트)에 존재하고 있는 프로그램을 서비스 받을 수 있다. 서버에 존재하는 서비스를 받기 위해서는 물리적인 연결이 갖춰져야 함은 물론이거니와 서버에 존재하는 프로그램이 네트워크를 이용해서 접속한 사용자들에게 서비스를 제공해줄 수 있어야 한다. 이와 같이 네트워크를 통해 접근한 클라이언트에게 서비스를 제공해주는 프로그램을 네트워크 데몬(daemon)이라고 한다. 데몬이란 포트(port, 대부분이 잘 알려진 포트:well-known service port)를 열고, 클라이언트가 연결되어 서비스를 요청할 것을 기다리는 응용 프로그램을 말한다.
1). inetd의 개념
하나의 클라이언트가 접속을 해오면 데몬은 자식 프로세스(child process)를 생성하고, 자식 프로세스로 하여금 접속해온 클라이언트에 서비스를 제공해주도록 한다. 또한, 자신(부모 프로세스:parent process)은 다른 클라이언트가 접속해 올 경우에 대비해 자신에게 할당된 포트를 감시한다.
이 과정은 프로그램 구조로서는 상당히 안정적이라고 할 수 있다. 하지만 단점도 있는데, 하루에 한번, 혹은 일주일에 한 번 정도의 서비스를 위해 메모리에 하루 종일 해당 데몬을 적재해둬야 한다는 것은 메모리 낭비일 뿐만 아니라 프로젝트가 늘어날 수록 동일한 포트에 대해서 프로그래밍할 확률이 높아진다는 것이다. 이는 곧 프로그램의 충돌을 의미하며, 이를 방지하기 위해 매번 네트워크 관리자나 서버 관리자가 응용 프로그램간에 조율을 해야 하는 불편이 있다.
이런 단점을 해결하기 위해서 유닉스와 리눅스에서는 아주 특별한 네트워크 데몬을 가동시키고 있는데, 이 프로그램을 “슈퍼 서버(super server)” 혹은 “인터넷 데몬(internet daemon)”이라고 한다. 이 프로그램이 inetd이다. 인터넷 데몬은 다양한 서비스에 대해서 소켓을 생성하고, 동시에 해당 네트워크 서비스에 연결된 포트(TCP 포트 혹은 UDP 포트)들에 대해서 감시하게 된다. 클라이언트가 인터넷 데몬이 감시하고 있는 포트로 접속을 해오게 되면 인터넷 데몬은 접속해온 포트에 연결된 서비스 데몬을 호출하고 클라이언트를 해당 서비스에게 넘겨주게 된다. 그리고 인터넷 데몬은 계속 포트들을 감시한다.
인터넷 데몬은 시스템이 시작할 때 함께 시작하며, 자신이 관리할 응용 프로그램들에 대해서 /etc/inetd.conf라는 파일에 정보를 가지고 있게 된다. /etc/inetd.conf 파일에 등록되어 인터넷 데몬에 의해서 서비스되는 프로그램들을 내부 서비스(internal service)라고 부른다. 실제 /etc/inetd.conf 파일을 열어보면 상당히 많은 응용 프로그램들이 등록되어 있음을 확인할 수 있다(이런 이유로 슈퍼 서버라고 한다). 내부 서비스에는 chargen과 같이 단순히 문자열을 생성하는 프로그램도 있고, 시스템에서 사용하고 있는 날짜의 시간에 대해 서비스하는 daytime이라는 서비스도 있다.
이렇게 다양한 서버 프로그램들을 대신하기 때문에 자연스럽게 서버의 부하를 줄이게 된다. 하지만 서버의 부하는 줄지만 클라이언트가 접속을 요청해 왔을 때 해당 서비스를 제공해주는 서버 프로그램을 호출하기 때문에 시간은 더 소비된다. 그러므로 관리자는 반드시 트레이드 오프(trade off)를 해야 한다.
일반적으로 각각의 서비스들은 “single-threaded”로 설정되어 해당 서버 프로그램이 서비스를 모두 마칠 때까지 인터넷 데몬이 기다리고 있다가 해당 서비스가 끝나고 나면 두 번째 서버를 가동하게 된다. RPC 서비스도 인터넷 데몬에 의해서 시작될 수 있다.
2) /etc/inetd.conf 파일
/etc/inetd.conf 파일을 이루는 형식은 다음과 같다.
Services type protocol wait user server command_line |
각각의 항목은 공백이나 탭 문자로 구분되며, # 이후의 내용은 모두 주석으로 처리된다.
다음은 각각의 필드에 대한 설명이다.
Services
서비스 이름을 지정하는 것으로, 각각의 서비스는 /etc/services 파일을 이용해서 적절한 포트로 대응이 된다. /etc/services 파일에 기록되는 서비스 명은 공식적인 이름이어야 한다. SUN의 경우에는 RPC도 올 수 있고, 서비스 이름 다음에 “/숫자”를 추가하여 해당 서비스나 RPC의 버전 번호를 기록할 수도 있다.
type
소켓의 형태를 지정하는 것으로 연결 지향적 프로토콜(connection-oriented protocol)인 “stream”이나 데이터그램 프로토콜(datagram protocol 혹은 connectionless protocol)인 “dgram’이 올 수 있다. 그렇기 때문에 TCP에 기반을 둔 서비스의 경우에는 항상 stream을 사용해야 하고, UDP에 기반을 둔 서비스의 경우에는 dgram을 사용해야 한다. 이 외에도 “raw”, “rdm”(reliable delivered message), “seqpacket”(sequence packet socket) 등이 있다.
protocol
서비스에 의해서 사용되는 전달 프로토콜을 지정하는 것으로, RPC에 기반을 둔 서비스의 경우에는 서비스 타입에 따라 rpc/tcp나 rpc/udp 등이 오게 된다. /etc/protocol 파일 내에 정해진 이름만이 여기에 올 수 있다.
wait
이 옵션은 dgram 소켓에 대해서만 적용이 되는 것으로, “wait”나 “nowait”이 올 수 있다. 만약 wait이 지정되면 인터넷 데몬은 지정된 포트에 대해서 오직 하나의 서버 프로그램만을 실행시키게 된다. 이 때 두번째 요청이 들어오면 첫번째 요청이 끝날 때까지 기다려야(wait)하는 것이다. 하지만 nowait가 지정된 경우에는 해당 포트와 연관된 서버 프로그램을 실행시킨 후 바로 해당 포트에 귀를 기울이게 된다. 그러므로 dgram 소켓에 대해서만 wait를 지정하고 stream 소켓에 대해서는 nowait를 지정한다. dgram 소켓을 사용하는 프로그램의 경우에는 더 이상 입력되는 데이터가 없을 때까지 들어오는 모든 데이터를 읽고 프로그램을 끝내는 single-threaded 형식의 프로그램이 유리하며, 대부분의 RPC 서버가 이란 형식을 취하게 된다. 하지만 동시에 무제한적으로 운영될 수 있는 stream 형식의 서버인 경우에는 반드시 nowait를 지정하여 모든 입력을 제어하도록 하는 것이 좋으며, 이와 같은 기능을 제공해주는 서버로는 multi-threaded 형식을 취하는 프로그램들이다(UDP는 TCP와 달리 데이터그램에 데이터 위치의 전후를 확인하는 정보를 포함하고 있지 않다. 그러므로 wait를 지정해야 정확한 데이터를 받을 수 있으며, nowait를 지정할 경우 불필요한 서버가 계속 실행되어 엉뚱한 결과를 가져올 수 있다.)
user
프로세스가 가동될 때 어떤 사용자의 로그인 ID를 이용해서 실행되게 할 것인지를 결정하는 것으로, 대부분 root가 사용된다. 하지만 어떤 프로그램의 경우 다른 계정을 사용하기도 하는데, 로그인한 상태에서 실행할 프로그램이 별로 없을 정도의 권한을 가진 계정을 부여하는 것이 좋다. 그렇지 않으면 보안에 치명적일 수 있기 때문이다. 단순하게 특정 사용자 계정만을 추가할 수 있는 것이 아니라 “user.group”이라고 입력함으로써 그룹까지도 추가할 수 있다.
server
실행시킬 서버 프로그램의 전체 경로를 입력하는 곳으로, 인터넷 데몬이 서비스를 제공할 수 있는 내부 서비스인 경우에는 internal이라는 키워드로 표시된다.
command_line
서버 프로그램에 제공될 명령행으로, 실행될 서버 프로그램의 이름으로 시작하며, 전달될 인자들을 포함할 수 있다. 그렇기 때문에 아래에서 제시된 argument는 생략될 수도 있고, 별도로 기록할 수도 있다. 만약 tcp_wrapper와 같은 프로그램을 사용할 때는 여기에 서버 프로그램의 전체 경로가 오게 된다. 그리고 앞 항목인 server에 internal이 사용되게 되면 이후에는 아무런 정보도 와선 안된다.
3) /etc/inetd.conf 파일 예
#echo stream tcp nowait root internal #echo dgram udp wait root internal #discard stream tcp nowait root internal #discard dgram udp wait root internal #daytime stream tcp nowait root internal #daytime dgram udp wait root internal #chargen stream tcp nowait root internal #chargen dgram udp wait root internal #time stream tcp nowait root internal #time dgram udp wait root internal #These are standard services disabled for proftpd #ftp stream tcp nowait root /usr/sbin/tcpd in.ftpd –l –a #telnet stream tcp nowait root /usr/sbin/tcpd in.telnetd #Shell, login, exec, comsat and talk are BSD protocols. shell stream tcp nowait root /usr/sbin/tcpd in.rshd login stream tcp nowait root /usr/sbin/tcpd in.rlogind #exec stream tcp nowait root /usr/sbin/tcpd in.rexecd #comsat dgram udp wait root /usr/sbin/tcpd in.comsat talk dgram udp wait nobody.tty /usr/sbin/tcpd in.talked #tftp dgram udp wait root /usr/sbin/tcpd in.tftpd |
위의 예를 보면, UDP를 이용하는 서비스의 경우에는 모두 dgram 형식의 소켓을 이용하도록 되어 있고, wait를 하도록 지정되어 있는 것을 알 수 있다. 여기서 자신이 서비스를 원하지 않는 것들이 있다면 주석처리 하는 것이 보안에도 좋다.
제일 아래에 있는 tftp(Trivial File Transfer Protocol)의 경우에는 암호 확인없이 사용자의 시스템으로부터 ASCII 파일을 읽어 갈 수 있는 프로그램이기 때문에 반드시 주석 처리해두는 것이 좋다. 이유는 /etc/passwd 파일과 같은 것을 읽어간다면 사용자의 시스템에 치명적인 악영향을 미칠 수 있기 때문이다. 일반적으로 tftp는 디스크가 없는 클라이언트와 X 더미 터미널을 이용할 때 사용되는 것으로, 서버로부터 부트 코드를 다운로드 받을 때 사용할 수 있다. 만약 이런 목적을 이용해서 tftpd를 가동하려면 접근할 수 있는 장비의 IP 주소를 지정하는 것이 좋다.
4) inetd의 가동
인터넷 데몬은 시작할 때만 설정 파일(etc/inetd.conf)을 읽어들이는 것이 아니라 SIGHUP(hangup 신호)을 받을 때마다 설정 파일을 읽어들이게 된다. 그러므로 설정 파일을 변경하고 나면 SIGHUP 신호를 보내 변경된 내용을 적용하도록 한다.
인터넷 데몬을 시작할 때 사용할 수 있는 옵션으로는 다음과 같은 것들이 있다.
-d : 디버깅을 할 수 있도록 실행 방법을 변경함
-i : 백그라운드로 실행되지 않게 설정
-q queue_length : 소켓에 귀 기울일 수 있는 큐의 크기를 지정한다. 지정하지 않으면 기본값은 128이다.
/etc/inetd.conf 파일을 변경했다면 다음처럼 인터넷 데몬을 다시 가동시켜야 한다.
#killall –HUP inetd