inetd Daemon의 이용 VLSI 석사 3학기 고재현
목차 개요 inetd의 소개 간단한 stream tcp 서버 구현 inetd를 이용한 datagram 서버 요약
개요 inetd Daemon은 무엇인가? inetd를 이용한 서버 자원의 활용 문제 해결
모든 서버의 공통 단계 소켓 생성 소켓을 well-known 주소와 바인드 클라이언트 연결을 listen 클라이언트 연결을 accept
inetd의 소개 /etc/rc.d/init.d/inet 스크립트에 의해 실행되는 daemon 다양하게 심볼릭 링크된 스크립트에서 실행 Red Hat Linux의 경우 /etc/rc.d/rc3.d/S50inet – Run level 3에서 /etc/rc.d/rc3.d/S50inet – Run level 5에서 /etc/inetd.conf 파일 inetd daemon이 처음 실행될 때 참조 어떤 Internet 서비스가 listen하는지 요청이 왔을때 어떤 서버에 요청을 넘길지
/etc/inetd.conf 환경설정 파일 한 라인에 인터넷 서비스를 기술 필드 번호 Description Example 1 인터넷 서비스 이름 telnet(혹은 포트 번호) 2 소켓 타입 stream or dgram 3 프로토콜 tcp or udpo 4 플래그 Nowait or wait 5 사용할 사용자 ID root or nobody 6 실행 경로명 /usr/sbin/in.telnetd 7 서버 인수 In.telnetd
/etc/inetd.conf 필드 – (1) 인터넷 서비스 이름 필드 /etc/services 파일에 있는 서비스 이름 telnet : tcp 서비스이고 23번 포트로 설정 inetd daemon이 감시 할 포트 결정 # grep telnet /etc/services telnet 23 / tcp rtelnet 107 / tcp # Remote Telnet rtelnet 107 / tcp
/etc/inetd.conf 필드 – (2) 소켓 타입 필드 stream과 dgram 타입만 언급 inetd(8) man page에 소켓리스트 포함 raw, rdm, seqpacket 타입 stream 타입 : SOCK_STREAM과 대응 socket(2) 함수 호출에 사용 Dgram 타입 : SOCK_DGRAM과 대응
/etc/inetd.conf 필드 – (3) 프로토콜 필드 소켓에서 사용할 프로토콜 선택 /etc/protocols 파일에 있는 목록의 값 가장 일반적으로 사용되는 프로토콜 TCP 프로토콜을 위한 tcp UDP 프로토콜을 위한 udpㅁ
/etc/inetd.conf 필드 – (4) 플래그 필드 datagram에만 사용 비 datagram 소켓에는 nowait 값을 설정 두 가지 datagram-oriented 서버 읽은 UDP 패킷을 timeout 되거나 종료(wait 값 설정)될 때까지 보관하는 서버 하나의 패킷만 읽고 종료(nowait로 설정)하는 서버 datagram traffic 처리를 위해 사용
/etc/inetd.conf 필드 – (5) 사용자 ID 필드 inetd는 root에서 동작 다른 사용자 계정을 inetd daemon의 식별자로 바꾸도록 지원 보안과 관련 최소의 권한으로 서버를 구동하기 위해 사용
/etc/inetd.conf 필드 – (6) 실행 경로 필드 서버 인수 필드 Inetd에게 실행 가능한 완전 경로명 표시 daemon이 fork(2)를 호출한 후 exec(2)가 호출하는 파일 서버 인수 필드 Exec(2)를 호출할 때 사용하는 명령어라인 인수 인수는 argv[0]부터 시작 경로명과 다른 명령어 이름을 허용 실행파일이 이름에 따라 다른 특성 나타낼 때 사용
inetd 서버 설계 파라미터 소켓은 시작된 서버에 다음 파일 유닛 전달 단일 소켓 함수 호출 없도록 설계 File unit 0는 표준 입력을 위한 클라이언트 소켓 File unit 1는 표준 출력을 위한 클라이언트 소켓 File unit 2는 표준 에러를 위한 클라이언트 소켓 단일 소켓 함수 호출 없도록 설계
간단한 stream tcp 서버 구현 5: #include <stdio.h> 6: #include <unistd.h> 7: #include <stdlib.h> 8: #include <errno.h> 9: #include <string.h> 10: #include <time.h> 11: #include <sys/types.h> 소켓 헤더파일이 없다
간단한 stream tcp 서버 구현 30: int z; 31: int n; 32: time_t td; /* Current data&time */ 33: char dtbuf[128]; /* Date/Time Info */ 소켓 주소 구조체 필요없다.
간단한 stream tcp 서버 구현 소켓 호출이 필요없다. 38: time(&td); 39: n = (int) strftime(dtbuf,sizeof dtbuf, 40: "%A %b %d %H:%M:%S %Y", 41: localtime(&td)); 42: 43: /* 44: * Write result back to the client: 45: */ 46: z = write(1,dtbuf,n); 47: if(z ==-1) 48: bail("write(2)"); 소켓 호출이 필요없다.
간단한 stream tcp 서버 구현 Shell을 이용한 테스트 Port 13을 이용한 daytime 서비스 $ make inetdserv gcc –c –D_GNU_SOURCE –Wall –Wreturn –type inetdserv.c gcc inetdserv.o –o inetdserv $ ./inetdserv Tuesday Nov 02 16:29:45 1999 $ telnet 192.168.0.1 13 Trying 192.168.0.1… Connected to 192.168.0.1. Escape character is ‘^]’. Tue Nov 2 16:31:09 1999 Connection closed by foreign host. $
/etc/inetd.conf 파일 수정 실행파일 복사 및 실행 가능하도록 설정 /etc/inetd.conf 파일 수정 $ cp inetdserv /tmp/inetdserv $ chmod a+rx /tmp/inetdserv $ tail –1 /etc/inetd.conf 9099 stream tcp nowait root /tmp/inetdserv inetdserv
/etc/inetd.conf 파일 수정 각 필드의 의미 9099 : 사용할 포트 stream : tcp stream 소켓을 사용 tcp : tcp 스트림을 사용 nowait : tcp 스트림 엔트리가 무엇을 원하는가 root : 수행 권한 /tmp/inetdserv : 실행 경로명 Inetdserv : 명령어 인수 9099 stream tcp nowait root /tmp/inetdserv inetdserv
설정 변화를 inetd에 통보 root 계정에서 다음을 수행 의미 inetd daemon의 process id를 얻는다 Inetd에 HUB 신호를 보내 환경 설정파일을 다시 읽도록 한다. 프로세스는 종료하지 않는다. # ps -ax | grep inetd 314 ? S 0:00 inetd # kill -HUP 314 #
설정 변화를 inetd에 통보 설정 변경 확인 TCP *:9099로 표시된 부분이 새로 추가된 서버 # lsof -i COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME portmap 238 root 3u inet 369 UDP *:sunrpc portmap 238 root 4u inet 370 UDP *:sunrpc (LISTEN) inetd 314 root 4u inet 474 UDP *:ftp (LISTEN) inetd 314 root 5u inet 475 UDP *:telnet (LISTEN) inetd 314 root 6u inet 476 UDP *:login (LISTEN) inetd 314 root 8u inet 477 UDP *:exec (LISTEN) inetd 314 root 10u inet 478 UDP *:auth (LISTEN) inetd 314 root 11u inet 1124 UDP *:9099 (LISTEN) inetd 314 root 12u inet 1163 UDP *:daytime (LISTEN) named 342 root 4u inet 531 UDP *:1024 TCP *:9099로 표시된 부분이 새로 추가된 서버 inetd가 포트 9099로 연결하기 위해 listening *:9099는 어떤 포트로부터의 연결도 받는다는 의미
새로운 서비스 테스트 localhost 주소를 이용한 테스트 카드 인터페이스 주소 이용한 테스트 $ telnet localhost 9099 Trying 127.0.0.1... Connected to localhost Escape character is '^]'. Tuesday Nov 2 17:10:37 1999 Connection closed by foreign host. $ $ telnet 192.168.0.1 9099 Trying 192.168.0.1... Connected to 192.168.0.1. Escape character is '^]'. Tuesday Nov 2 17:13:28 1999 Connection closed by foreign host. $
새로운 서비스 테스트 daytime 서버와 비교 $ telnet 192.168.0.1 13 Trying 192.168.0.1... Connect to 192.168.0.1. Escape character is '^]'. Tue Nov 2 17:16:57 1999 Connection closed by foreign host. $
새로운 서비스 중단 /etc/inetd.conf 파일에서 추가된 내용 삭제 root 계정에서 다음을 수행 # ps -ax | grep inetd 314 ? S 0:00 inetd # kill -HUP 314 #
inetd를 이용한 datagram 서버 UDP 서버에 적용된 inetd inetd 서버가 UDP 포트를 listen Inetd가 select(2) 호출해 datagram의 도착을 알린다. Inetd가 UDP 서버 시작을 위해 fork(2)와 exec(2)를 호출 UDP 서버가 하나의 패킷을 읽기 위해 file unit 0(stdin)을 사용
inetd를 이용한 datagram 서버 UDP 서버의 선택 단계 4에서 UDP 패킷을 처리한 후 Exit(종료) 다른 UDP 패킷을 기다림(timeout 후에 종료)
Wait와 nowait의 이해 nowait wait 하나의 datagram을 처리하고 종료할 때 Inetd가 시작시킨 서버 프로세스가 datagram이 끝날 때까지 datagram 처리 wait(2) 시스템 호출이 inetd에게 서버 종료를 알릴 때까지 새로운 프로세스 시작하지 않음
Wait와 nowait의 이해 시스템적 기술 Inetd 서버에 들어온 datagram때문에 looping UDP 서버 프로세스 시작 다른 이벤트 기다림 첫번째 UDP datagram 처리 마침 표준 입력으로부터 다른 UDP datagram 읽기 시도 더 이상 도착한 datagram이 없어 서버에서 timeout 발생하고 exit(3) 호출에 의해 프로세스 종료 inetd SIGCHLD 신호 발생 inetd 서버가 프로세스 ID와 서버 프로세스 종료 상태 결정 wait(2)가 반환하는 datagram 서버의 프로세스 ID기록 서비스를 기다리는 프로세스가 없음을 표시
Wait와 nowait의 이해 datagram 서비스 정의시 유의사항 inetd daemon은 형성된 datagram 서버가 wait 또는 nowait 인수가 필요한지 알수 없다. wait datagram 서버에 nowait를 지정하면 불필요한 서버 프로세스들이 복제된다. nowait datagram 서버에 wait를 지정하면 서비스에 대한 실행력이 떨어진다.
요약