¸ðµç ³×Æ®¿öÅ© ¿¬°áÀº 2°³ÀÇ IP ¾îµå·¹½º/Æ÷Æ® ½ÖÀ¸·Î ÀÌ·ç¾îÁø´Ù.
³×Æ®¿öÅ© ÇÁ·Î±×·¡¹ÖÀ» À§ÇÑ API(Applications Program Interface)´Â
¼ÒÄÏ API·Î ºÒ¸°´Ù. ¼ÒÄÏÀº ¸¶Ä¡ ¿·ÁÀÖ´Â ÆÄÀÏ°ú °°ÀÌ ÀÛµ¿Çϱ⠶§¹®¿¡
³×Æ®¿öÅ© ¿¬°áÀ» ÅëÇØ µ¥ÀÌÅ͸¦ ÁÖ°í¹Þ´Â °ÍÀº ¼ÒÄÏ¿¡ ¾²°íÀд °úÁ¤À¸·Î
ÀÌÇصȴÙ. ·ÎÄà ¼ÒÄÏÀÇ ÁÖ¼Ò¸¦ µ¹·ÁÁÖ´Â ÇÔ¼ö´Â getsockname
ÀÌ´Ù.
Virtuald´Â getsockname
À» »ç¿ëÇÏ¿© ·ÎÄà ½Ã½ºÅÛÀÇ ¾î¶² IP°¡
Á¢±Ù °¡´ÉÇÑÁö¸¦ ÆÇ´ÜÇÑ´Ù. Virtuald´Â ¼³Á¤ ÆÄÀÏÀ» ÀÐ¾î¼ ÇØ´ç IP¿¡ ÇÒ´çµÈ
µð·ºÅ丮¸¦ µ¹·Á¹Þ´Â´Ù. ±×¸®°í´Â chroot
¸¦ ÅëÇؼ ¸ðµç ¼ºñ½º¿¡ ´ëÇÑ
Á¦¾î±ÇÀ» ³Ñ°ÜÁØ´Ù. Chroot
Àº ·çÆ® µð·ºÅ丮¸¦ Àç¼³Á¤ÇÏ¿© »õ·Ó°Ô
ÁöÁ¤¹ÞÀº Æ÷ÀÎÆ®¸¦ ·çÆ®·Î ¼³Á¤Çϱ⠶§¹®¿¡ »óÀ§ µð·ºÅ丮´Â ½ÇÇà
ÇÁ·Î±×·¥µé¿¡ ÀÇÇØ ¹«½ÃµÈ´Ù. ³×Æ®¿öÅ© ÇÁ·Î±×·¥¿¡ ´ëÇؼ´Â ÀÌ °úÁ¤Àº ¸¶Ä¡
¾Æ¹«Àϵµ ÀϾÁö ¾ÊÀº °Íó·³ Åõ¸íÇÏ°Ô º¸ÀÏ °ÍÀÌ´Ù. Virtuald´Â inetd¿Í °°Àº
ÇÁ·Î±×·¥°ú ¿¬°áµÇ¾î ¾î¶² ¼ºñ½º¶óµµ °¡»óÀûÀ¸·Î ¸¸µé ¼ö ÀÖ´Ù.
Inetd´Â ¿ÜºÎ¿¡¼ ³×Æ®¿öÅ©¸¦ ÅëÇØ ¿¬°áÀ» ½ÃµµÇÒ ¶§(¿¹¸¦ µé¸é POP¼¹öÀÇ ¿äû) ¿©·¯ °³ÀÇ Æ÷Æ®¸¦ °¨½ÃÇÏ°í ÀÖ´Ù°¡ ¿äû¿¡ ´ëÇÑ Àû´çÇÑ ¿¬°áÀ» ±¸ÇöÇØÁÖ´Â ³×Æ®¿öÅ© super serverÀÌ´Ù. Inetd´Â ³×Æ®¿öÅ©¸¦ Àü¹ÝÀûÀ¸·Î °ü¸®ÇÏ¸é¼ Æ¯Á¤ ÇÁ·Î±×·¥¿¡ ´ëÇØ ³×Æ®¿öÅ©¸¦ ¿¬°áÇØ ÁÖ´Â ÀÏÀ» ÇÑ´Ù. ÀÌ·± °úÁ¤À» ÅëÇØ ¾î¶² ¼ºñ½º°¡ ³×Æ®¿öÅ© ¿¬°áÀÌ ÇÊ¿ä ¾øÀ» ¶§ ºÒÇÊ¿äÇÏ°Ô ½ÇÇàµÇ´Â °ÍÀ» ¸·À» ¼ö ÀÖ´Ù.
Ç¥ÁØÀûÀÎ /etc/inetd.conf ÆÄÀÏÀº ´ÙÀ½°ú °°´Ù:
ftp stream tcp nowait root /usr/sbin/tcpd \ wu.ftpd -l -a pop-3 stream tcp nowait root /usr/sbin/tcpd \ in.qpop -s
°¡»ó ¼ºñ½º¸¦ ÇÒ ¶§ /etc/inetd.conf ÆÄÀÏÀº ´ÙÀ½°ú °°ÀÌ µÈ´Ù:
ftp stream tcp nowait root /usr/local/bin/virtuald \ virtuald /virtual/conf.ftp wu.ftpd -l -a pop-3 stream tcp nowait root /usr/local/bin/virtuald \ virtuald /virtual/conf.pop in.qpop -s
°¢°¢ÀÇ ¼ºñ½ºµéÀº ¾î¶² IPµé°ú µð·ºÅ丮µéÀ» »ç¿ëÇÏ°í °ü¸®ÇÒ °ÍÀÎÁö¿¡ ´ëÇÑ Á¤º¸¸¦ ¼³Á¤ ÆÄÀÏ¿¡¼ ¾ò°Ô µÈ´Ù. ´ç½ÅÀº ÇϳªÀÇ Àüü ¼³Á¤ ÆÄÀÏ (master config file)À» °®´øÁö ¾Æ´Ï¸é ¸î¸îÀÇ ¼³Á¤ ÆÄÀϵéÀ» ÅëÇؼ °¢°¢ÀÇ ¼ºñ½º¿¡¼ µµ¸ÞÀÎÀÇ ´Ù¸¥ ¸®½ºÆ®¸¦ ¾ò°Ô ÇÒ ¼ö ÀÖ´Ù. ¼³Á¤ ÆÄÀÏÀº ´ÙÀ½°ú °°´Ù:
# This is a comment and so are blank lines # Format IP SPACE dir NOSPACES 10.10.10.129 /virtual/domain1.com 10.10.10.130 /virtual/domain2.com 10.10.10.157 /virtual/domain3.com # Default option for all other IPs default /
¾Æ·¡´Â virtuald ÇÁ·Î±×·¥¿¡ ´ëÇÑ C ¼Ò½º ÄÚµåÀÌ´Ù. ÀÌ°ÍÀ» ÄÄÆÄÀÏÇÏ°í /usr/local/bin ¾Æ·¡¿¡ 0755ÀÇ Æ۹̼ÇÀ¸·Î ¼³Ä¡Ç϶ó.(¼ÒÀ¯ÀÚ¿Í ±×·ìÀº ¸ðµÎ root·Î ÇÑ´Ù.) ÄÄÆÄÀϽÿ¡´Â VERBOSELOG°¡ ¿É¼ÇÀ¸·Î »ç¿ëµÉ ¼ö Àִµ¥ (¿ÀÁ÷ ÀÌ ¿É¼Ç¸¸ÀÌ Á¸ÀçÇÑ´Ù), ÀÌ°ÍÀº ¿¬°á½Ã ±â·ÏÀ» ³²±æ°ÍÀÎÁö¸¦ Á¤ÇÑ´Ù.
#include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdarg.h> #include <unistd.h> #include <string.h> #include <syslog.h> #include <stdio.h> #undef VERBOSELOG #define BUFSIZE 8192 int getipaddr(char **ipaddr) { struct sockaddr_in virtual_addr; static char ipaddrbuf[BUFSIZE]; int virtual_len; char *ipptr; virtual_len=sizeof(virtual_addr); if (getsockname(0,(struct sockaddr *)&virtual_addr,&virtual_len)<0) { syslog(LOG_ERR,"getipaddr: getsockname failed: %m"); return -1; } if (!(ipptr=inet_ntoa(virtual_addr.sin_addr))) { syslog(LOG_ERR,"getipaddr: inet_ntoa failed: %m"); return -1; } strncpy(ipaddrbuf,ipptr,sizeof(ipaddrbuf)-1); *ipaddr=ipaddrbuf; return 0; } int iptodir(char **dir,char *ipaddr,char *filename) { char buffer[BUFSIZE],*bufptr; static char dirbuf[BUFSIZE]; FILE *fp; if (!(fp=fopen(filename,"r"))) { syslog(LOG_ERR,"iptodir: fopen failed: %m"); return -1; } *dir=NULL; while(fgets(buffer,BUFSIZE,fp)) { buffer[strlen(buffer)-1]=0; if (*buffer=='#' || *buffer==0) continue; if (!(bufptr=strchr(buffer,' '))) { syslog(LOG_ERR,"iptodir: strchr failed"); return -1; } *bufptr++=0; if (!strcmp(buffer,ipaddr)) { strncpy(dirbuf,bufptr,sizeof(dirbuf)-1); *dir=dirbuf; break; } if (!strcmp(buffer,"default")) { strncpy(dirbuf,bufptr,sizeof(dirbuf)-1); *dir=dirbuf; break; } } if (fclose(fp)==EOF) { syslog(LOG_ERR,"iptodir: fclose failed: %m"); return -1; } if (!*dir) { syslog(LOG_ERR,"iptodir: ip not found in conf file"); return -1; } return 0; } int main(int argc,char **argv) { char *ipaddr,*dir; openlog("virtuald",LOG_PID,LOG_DAEMON); #ifdef VERBOSELOG syslog(LOG_ERR,"Virtuald Starting: $Revision: 1.49 $"); #endif if (!argv[1]) { syslog(LOG_ERR,"invalid arguments: no conf file"); exit(0); } if (!argv[2]) { syslog(LOG_ERR,"invalid arguments: no program to run"); exit(0); } if (getipaddr(&ipaddr)) { syslog(LOG_ERR,"getipaddr failed"); exit(0); } #ifdef VERBOSELOG syslog(LOG_ERR,"Incoming ip: %s",ipaddr); #endif if (iptodir(&dir,ipaddr,argv[1])) { syslog(LOG_ERR,"iptodir failed"); exit(0); } if (chroot(dir)<0) { syslog(LOG_ERR,"chroot failed: %m"); exit(0); } #ifdef VERBOSELOG syslog(LOG_ERR,"Chroot dir: %s",dir); #endif if (chdir("/")<0) { syslog(LOG_ERR,"chdir failed: %m"); exit(0); } if (execvp(argv[2],argv+2)<0) { syslog(LOG_ERR,"execvp failed: %m"); exit(0); } closelog(); exit(0); }