home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 1: Linux / CD1.iso / doc / HOWTO / Virtual-Services-HOWTO < prev    next >
Text File  |  1998-10-14  |  72KB  |  2,839 lines

  1.   Virtual Services Howto
  2.   Brian Ackerman, brian@nycrc.net
  3.   v2.1, 15 August 1998
  4.  
  5.   This document came about to satisfy the ever increasing need to know
  6.   how to virtualize a service.
  7.   ______________________________________________________________________
  8.  
  9.   Table of Contents
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.   1. Introduction
  68.  
  69.      1.1 Knowledge Required
  70.      1.2 Purpose
  71.      1.3 Feedback
  72.      1.4 Revision History
  73.      1.5 Copyright/Distribution
  74.  
  75.   2. IP Aliasing
  76.  
  77.   3. Virtuald
  78.  
  79.      3.1 Introduction
  80.      3.2 Inetd
  81.      3.3 Config File
  82.      3.4 Source
  83.  
  84.   4. Shell Scripts
  85.  
  86.      4.1 Virtfs
  87.      4.2 Virtexec
  88.      4.3 Notes
  89.  
  90.   5. DNS
  91.  
  92.   6. Syslogd
  93.  
  94.      6.1 Problem
  95.      6.2 Solution
  96.         6.2.1 Setup Links
  97.         6.2.2 Syslogd.init
  98.      6.3 Multiple Syslogd's
  99.         6.3.1 One Per Disk
  100.         6.3.2 One Per Domain
  101.  
  102.   7. Virtual FTP
  103.  
  104.      7.1 Inetd
  105.      7.2 Anonymous FTP
  106.      7.3 Virtual FTP Users
  107.  
  108.   8. Virtual Web
  109.  
  110.      8.1 Running With Virtuald
  111.         8.1.1 Not recommended
  112.         8.1.2 Inetd
  113.         8.1.3 Httpd.conf
  114.         8.1.4 Configuration
  115.         8.1.5 Httpd.init
  116.      8.2 Running With Apache VirtualHost
  117.         8.2.1 Access.conf
  118.         8.2.2 Httpd.conf
  119.         8.2.3 Srm.conf
  120.         8.2.4 Httpd.init
  121.      8.3 File Descriptor Overflow
  122.         8.3.1 Warning
  123.         8.3.2 Multiple Apache Servers
  124.      8.4 Sharing Servers With One IP
  125.         8.4.1 Saving IPs
  126.         8.4.2 Drawback
  127.      8.5 More Information
  128.  
  129.   9. Virtual Mail/Pop
  130.  
  131.      9.1 Problem
  132.      9.2 Solution
  133.      9.3 Sendmail Solution
  134.         9.3.1 Introduction
  135.         9.3.2 Create Sendmail Configuration File
  136.         9.3.3 Edit Sendmail Configuration File
  137.         9.3.4 Sendmail Local Delivery
  138.         9.3.5 Sendmail Between Virtual Domains: The Hack (PRE8.8.6)
  139.         9.3.6 Sendmail Between Virtual Domains: New Sendmail Feature (POST8.8.6)
  140.         9.3.7 Sendmail.init
  141.         9.3.8 Inetd Setup
  142.      9.4 Qmail Solution
  143.         9.4.1 Introduction
  144.         9.4.2 Setup Virtual Domains
  145.         9.4.3 Setup Domain Master User
  146.         9.4.4 Tcpserver
  147.         9.4.5 Qmail.init
  148.         9.4.6 Source
  149.         9.4.7 Source
  150.      9.5 Acknowledgement
  151.  
  152.   10. Virtual Samba
  153.  
  154.      10.1 Setup
  155.      10.2 Inetd
  156.      10.3 Smb.init
  157.  
  158.   11. Virtual Other
  159.  
  160.   12. Conclusion
  161.  
  162.   13. FAQ
  163.  
  164.  
  165.  
  166.   ______________________________________________________________________
  167.  
  168.   1.  Introduction
  169.  
  170.   1.1.  Knowledge Required
  171.  
  172.   Creating a virtual services machine is not all that difficult,
  173.   however, more than fundamental knowledge is required.  This document
  174.   is not a primer to how to fully configure a Linux machine.
  175.  
  176.  
  177.   In order to understand this HOWTO document it is assumed that you are
  178.   thoroughly familiar with the following:
  179.  
  180.  
  181.   ╖  Compiling a Linux kernel and adding IP aliasing support IP alias
  182.      mini-HOWTO
  183.  
  184.   ╖  Setting up and configuring of network devices NET-3 HOWTO
  185.  
  186.   ╖  Setting up of inetd NET-3 HOWTO
  187.  
  188.   ╖  Various network packages like Sendmail Apache Qmail SAMBA
  189.  
  190.   ╖  Setting up DNS DNS HOWTO
  191.  
  192.   ╖  Understanding basic system administration Linux Systems
  193.      Administrators's Guide
  194.  
  195.   ╖  Understanding how to setup a Web Server WWW HOWTO
  196.  
  197.   If you are uncertain of how to proceed with any of the above it is
  198.   STRONGLY recommended that you use the html links provided to
  199.   familiarize yourself with all packages.  I will NOT reply to mail
  200.   regarding any of the above.  Please direct your questions to the
  201.   appropriate author of the HOWTO.
  202.  
  203.  
  204.   1.2.  Purpose
  205.  
  206.   The purpose of virtual services is to allow a single machine to
  207.   recognize multiple IP addresses without multiple network cards.  IP
  208.   aliasing is a kernel option that allows you to assign each network
  209.   device more than one IP address.  The kernel then multiplexes (swaps
  210.   between them very fast) in the background and to the user it appears
  211.   like you have more than one server.
  212.  
  213.  
  214.  
  215.   This multiplexing allows multiple domains (www.domain1.com,
  216.   www.domain2.com, etc.) to be hosted by the same machine for the same
  217.   cost as hosting one domain.  Unfortunately, most services (FTP, web,
  218.   mail) were not designed to handle muliple domains.  In order to make
  219.   them work properly you must modify both configuration files and source
  220.   code.  This document describes how to make these modifications in the
  221.   setting up of a virtual machine.
  222.  
  223.  
  224.   A deamon is also required in order to make virtual services function.
  225.   The source for this daemon (virtuald) is provided later in this
  226.   document.
  227.  
  228.  
  229.   1.3.  Feedback
  230.  
  231.   This document will expand as packages are updated and source or
  232.   configuration modifications change.   If there are any portions of
  233.   this document that are unclear please feel free to email me with your
  234.   suggestions or questions.  So that I do not have to go searching
  235.   through the entire HOWTO please make certain that all comments are as
  236.   specific as possible and include the section where the uncertainty
  237.   lies.  It is important that all mail be addressed with VIRTSERVICES
  238.   HOWTO in the subject line.  Any other mail will be considered personal
  239.   and all my friends know that I do not ever read my personal mail so it
  240.   will probably get discarded with theirs.
  241.  
  242.  
  243.   Please note that my examples are just that, examples and should not be
  244.   copied verbatim.   You may have to insert your own values.   If you
  245.   are having trouble, send me mail.  Include all the pertinent
  246.   configuration files and the error messages you get when installing and
  247.   I will look them over and reply with my suggestions.
  248.  
  249.  
  250.   1.4.  Revision History
  251.  
  252.   V1.0
  253.  
  254.   Initial version
  255.  
  256.  
  257.   V1.1
  258.  
  259.   Fixed error in Virtual Web Section
  260.  
  261.  
  262.   V1.2
  263.  
  264.  
  265.   Fixed the date
  266.  
  267.  
  268.   V2.0
  269.  
  270.  
  271.   Updated html links.
  272.  
  273.   Web updates.
  274.  
  275.   New Sendmail option.
  276.  
  277.   New Qmail section.
  278.  
  279.   Syslogd updates.
  280.  
  281.   FTP updates.
  282.  
  283.   Virtuald default option.
  284.  
  285.   New SAMBA section.
  286.  
  287.   FAQ updates.
  288.  
  289.  
  290.   V2.1
  291.  
  292.   Changed all paths to /usr/local.
  293.  
  294.   Added virtuald VERBOSELOG compile option.
  295.  
  296.   Fixed setuid/setgid bug in virtmailfilter.
  297.  
  298.   Fixed execl bug in virtmailfilter.
  299.  
  300.   Fixed capitialization bug in virtmailfilter.
  301.  
  302.   Fixed environment variable sanity check in virtmailfilter.
  303.  
  304.   Removed mbox code from virtmailfilter/virtmaildelivery.
  305.  
  306.   Added tcpserver.init pop section for Qmail.
  307.  
  308.   Added alias domain name question to the FAQ.
  309.  
  310.   Fixed virtmailfilter to send home directory to virtmaildelivery.
  311.  
  312.  
  313.   1.5.  Copyright/Distribution
  314.  
  315.   This document is Copyright (c) 1997 by The Computer Resource Center
  316.   Inc.
  317.  
  318.  
  319.   A verbatim copy may be reproduced or distributed in any medium
  320.   physical or electronic without permission of the author.  Translations
  321.   are similiarly permitted without express permission if it includes a
  322.   notice on who translated it.  Commercial redistribution is allowed and
  323.   encouraged; however please notify Computer Resource Center of any such
  324.   distributions.
  325.  
  326.  
  327.   Excerpts from the document may be used without prior consent provided
  328.   that the derivative work contains the verbatim copy or a pointer to a
  329.   verbatim copy.
  330.  
  331.   Permission is granted to make and distribute verbatim copies of this
  332.   document provided the copyright notice and this permission notice are
  333.   preserved on all copies.
  334.  
  335.  
  336.   In short, we wish to promote dissemination of this information through
  337.   as many channels as possible. However, I do wish to retain copyright
  338.   on this HOWTO document, and would like to be notified of any plans to
  339.   redistribute this HOWTO.
  340.  
  341.  
  342.   2.  IP Aliasing
  343.  
  344.   IP aliasing is a kernel option that needs to be set up in order to run
  345.   a virtual hosting machine.  There is already a mini-HOWTO on IP
  346.   aliasing.  Consult that for any questions on how to set it up.
  347.  
  348.  
  349.   3.  Virtuald
  350.  
  351.   3.1.  Introduction
  352.  
  353.   Every network connection is made up of two IP address/port pairs.  The
  354.   API (Applications Program Interface) for network programming is called
  355.   the Sockets API.  The socket acts like an open file and by
  356.   reading/writing to it you can send data over a network connection.
  357.   There is a function call  getsockname  that will return the IP address
  358.   of the local socket.  Virtuald uses  getsockname to determine which IP
  359.   on the local machine is being accessed.  Virtuald reads a config file
  360.   to retrieve the directory associated with that IP.  It will
  361.    chroot  to that directory and hand the connection off to the service.
  362.   Chroot  resets / or the root directory to a new point so everything
  363.   higher in the directory tree is cut off from the running program.
  364.   Therefore, each IP address gets their own virtual filesystem.   To the
  365.   network program this is transparent and the program will behave like
  366.   nothing happened.  Virtuald in conjunction with a program like inetd
  367.   can then be used to virtualize any service.
  368.  
  369.  
  370.   3.2.  Inetd
  371.  
  372.   Inetd is a network super server that listens at multiple ports and
  373.   when it receives a connection (for example, an incoming pop request),
  374.   inetd performs the network negotiation and hands the network
  375.   connection off to the specified program.  This prevents services from
  376.   running idly when they are not needed.
  377.  
  378.  
  379.   A standard /etc/inetd.conf file looks like this:
  380.  
  381.  
  382.   ftp stream tcp nowait root /usr/sbin/tcpd \
  383.           wu.ftpd -l -a
  384.   pop-3 stream tcp nowait root /usr/sbin/tcpd \
  385.           in.qpop -s
  386.  
  387.  
  388.  
  389.   A virtual /etc/inetd.conf file looks like this:
  390.  
  391.  
  392.   ftp stream tcp nowait root /usr/local/bin/virtuald \
  393.           virtuald /virtual/conf.ftp wu.ftpd -l -a
  394.   pop-3 stream tcp nowait root /usr/local/bin/virtuald \
  395.           virtuald /virtual/conf.pop in.qpop -s
  396.  
  397.   3.3.  Config File
  398.  
  399.   Each service gets a config file that will control what IPs and
  400.   directories are allowed for that service.  You can have one master
  401.   config file or several config files if you want each service to get a
  402.   different list of domains.   A config file looks like this:
  403.  
  404.  
  405.   # This is a comment and so are blank lines
  406.  
  407.   # Format IP SPACE dir NOSPACES
  408.   10.10.10.129 /virtual/domain1.com
  409.   10.10.10.130 /virtual/domain2.com
  410.   10.10.10.157 /virtual/domain3.com
  411.  
  412.   # Default option for all other IPs
  413.   default /
  414.  
  415.  
  416.  
  417.  
  418.   3.4.  Source
  419.  
  420.   This is the C source code to the virtuald program.  Compile it and
  421.   install it in /usr/local/bin with permission 0755, user root, and
  422.   group root.  The only compile option is VERBOSELOG which will turn
  423.   on/off logging of connections.
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.   #include <netinet/in.h>
  464.   #include <sys/socket.h>
  465.   #include <arpa/inet.h>
  466.   #include <stdarg.h>
  467.   #include <unistd.h>
  468.   #include <string.h>
  469.   #include <syslog.h>
  470.   #include <stdio.h>
  471.  
  472.   #undef VERBOSELOG
  473.  
  474.   #define BUFSIZE 8192
  475.  
  476.   int getipaddr(char **ipaddr)
  477.   {
  478.           struct sockaddr_in virtual_addr;
  479.           static char ipaddrbuf[BUFSIZE];
  480.           int virtual_len;
  481.           char *ipptr;
  482.  
  483.           virtual_len=sizeof(virtual_addr);
  484.           if (getsockname(0,(struct sockaddr *)&virtual_addr,&virtual_len)<0)
  485.           {
  486.                   syslog(LOG_ERR,"getipaddr: getsockname failed: %m");
  487.                   return -1;
  488.           }
  489.           if (!(ipptr=inet_ntoa(virtual_addr.sin_addr)))
  490.           {
  491.                   syslog(LOG_ERR,"getipaddr: inet_ntoa failed: %m");
  492.                   return -1;
  493.           }
  494.           strncpy(ipaddrbuf,ipptr,sizeof(ipaddrbuf)-1);
  495.           *ipaddr=ipaddrbuf;
  496.           return 0;
  497.   }
  498.  
  499.   int iptodir(char **dir,char *ipaddr,char *filename)
  500.   {
  501.           char buffer[BUFSIZE],*bufptr;
  502.           static char dirbuf[BUFSIZE];
  503.           FILE *fp;
  504.  
  505.           if (!(fp=fopen(filename,"r")))
  506.           {
  507.                   syslog(LOG_ERR,"iptodir: fopen failed: %m");
  508.                   return -1;
  509.           }
  510.           *dir=NULL;
  511.           while(fgets(buffer,BUFSIZE,fp))
  512.           {
  513.                   buffer[strlen(buffer)-1]=0;
  514.                   if (*buffer=='#' || *buffer==0)
  515.                           continue;
  516.                   if (!(bufptr=strchr(buffer,' ')))
  517.                   {
  518.                           syslog(LOG_ERR,"iptodir: strchr failed");
  519.                           return -1;
  520.                   }
  521.                   *bufptr++=0;
  522.                   if (!strcmp(buffer,ipaddr))
  523.                   {
  524.                           strncpy(dirbuf,bufptr,sizeof(dirbuf)-1);
  525.                           *dir=dirbuf;
  526.                           break;
  527.                   }
  528.                   if (!strcmp(buffer,"default"))
  529.                   {
  530.                           strncpy(dirbuf,bufptr,sizeof(dirbuf)-1);
  531.                           *dir=dirbuf;
  532.                           break;
  533.                   }
  534.           }
  535.           if (fclose(fp)==EOF)
  536.           {
  537.                   syslog(LOG_ERR,"iptodir: fclose failed: %m");
  538.                   return -1;
  539.           }
  540.           if (!*dir)
  541.           {
  542.                   syslog(LOG_ERR,"iptodir: ip not found in conf file");
  543.                   return -1;
  544.           }
  545.           return 0;
  546.   }
  547.  
  548.   int main(int argc,char **argv)
  549.   {
  550.           char *ipaddr,*dir;
  551.  
  552.           openlog("virtuald",LOG_PID,LOG_DAEMON);
  553.  
  554.   #ifdef VERBOSELOG
  555.           syslog(LOG_ERR,"Virtuald Starting: $Revision: 1.49 $");
  556.   #endif
  557.           if (!argv[1])
  558.           {
  559.                   syslog(LOG_ERR,"invalid arguments: no conf file");
  560.                   exit(0);
  561.           }
  562.           if (!argv[2])
  563.           {
  564.                   syslog(LOG_ERR,"invalid arguments: no program to run");
  565.                   exit(0);
  566.           }
  567.           if (getipaddr(&ipaddr))
  568.           {
  569.                   syslog(LOG_ERR,"getipaddr failed");
  570.                   exit(0);
  571.           }
  572.   #ifdef VERBOSELOG
  573.           syslog(LOG_ERR,"Incoming ip: %s",ipaddr);
  574.   #endif
  575.           if (iptodir(&dir,ipaddr,argv[1]))
  576.           {
  577.                   syslog(LOG_ERR,"iptodir failed");
  578.                   exit(0);
  579.           }
  580.           if (chroot(dir)<0)
  581.           {
  582.                   syslog(LOG_ERR,"chroot failed: %m");
  583.                   exit(0);
  584.           }
  585.   #ifdef VERBOSELOG
  586.           syslog(LOG_ERR,"Chroot dir: %s",dir);
  587.   #endif
  588.           if (chdir("/")<0)
  589.           {
  590.                   syslog(LOG_ERR,"chdir failed: %m");
  591.                   exit(0);
  592.           }
  593.           if (execvp(argv[2],argv+2)<0)
  594.           {
  595.                   syslog(LOG_ERR,"execvp failed: %m");
  596.                   exit(0);
  597.           }
  598.  
  599.           closelog();
  600.  
  601.           exit(0);
  602.   }
  603.  
  604.  
  605.  
  606.  
  607.   4.  Shell Scripts
  608.  
  609.   4.1.  Virtfs
  610.  
  611.   Each domain should get their own directory structure.  Since you are
  612.   using  chroot  you will require duplicate copies of the shared
  613.   libraries, binaries, conf files, etc.  I use /virtual/domain1.com for
  614.   each domain that I create.
  615.  
  616.  
  617.   I realize that you are taking up more disk space but it is cheaper
  618.   than a whole new machine and network cards.  If you really want to
  619.   preserve space you can hard link the files together so only one copy
  620.   of each binary exists.  The filesystem that I use takes up a little
  621.   over 2M.  However, this script attempts to copy all the files from the
  622.   main filesystem in order to be as generic as possible.
  623.  
  624.  
  625.  
  626.   Here is a sample virtfs script:
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.   #!/bin/sh
  662.  
  663.   echo '$Revision: 1.49 $'
  664.  
  665.   echo -n "Enter the domain name: "
  666.   read domain
  667.  
  668.   if [ "$domain" = "" ]
  669.   then
  670.           echo Nothing entered: aborting
  671.           exit 0
  672.   fi
  673.  
  674.   leadingdir=/virtual
  675.  
  676.   echo -n "Enter leading dir: (Enter for default: $leadingdir): "
  677.   read ans
  678.  
  679.   if [ "$ans" != "" ]
  680.   then
  681.           leadingdir=$ans
  682.   fi
  683.  
  684.   newdir=$leadingdir/$domain
  685.  
  686.   if [ -d "$newdir" ]
  687.   then
  688.           echo New directory: $newdir: ALREADY exists
  689.           exit 0
  690.   else
  691.           echo New directory: $newdir
  692.   fi
  693.  
  694.   echo Create $newdir
  695.   mkdir -p $newdir
  696.  
  697.   echo Create bin
  698.   cp -pdR /bin $newdir
  699.  
  700.   echo Create dev
  701.   cp -pdR /dev $newdir
  702.  
  703.   echo Create dev/log
  704.   ln -f /virtual/log $newdir/dev/log
  705.  
  706.   echo Create etc
  707.   mkdir -p $newdir/etc
  708.   for i in /etc/*
  709.   do
  710.           if [ -d "$i" ]
  711.           then
  712.                   continue
  713.           fi
  714.           cp -pd $i $newdir/etc
  715.   done
  716.  
  717.   echo Create etc/skel
  718.   mkdir -p $newdir/etc/skel
  719.  
  720.   echo Create home
  721.   for i in a b c d e f g h i j k l m n o p q r s t u v w x y z
  722.   do
  723.           mkdir -p $newdir/home/$i
  724.   done
  725.  
  726.   echo Create home/c/crc
  727.   mkdir -p $newdir/home/c/crc
  728.   chown crc.users $newdir/home/c/crc
  729.  
  730.   echo Create lib
  731.   mkdir -p $newdir/lib
  732.   for i in /lib/*
  733.   do
  734.           if [ -d "$i" ]
  735.           then
  736.                   continue
  737.           fi
  738.           cp -pd $i $newdir/lib
  739.   done
  740.  
  741.   echo Create proc
  742.   mkdir -p $newdir/proc
  743.  
  744.   echo Create sbin
  745.   cp -pdR /sbin $newdir
  746.  
  747.   echo Create tmp
  748.   mkdir -p -m 0777 $newdir/tmp
  749.   chmod +t $newdir/tmp
  750.  
  751.   echo Create usr
  752.   mkdir -p $newdir/usr
  753.  
  754.   echo Create usr/bin
  755.   cp -pdR /usr/bin $newdir/usr
  756.  
  757.   echo Create usr/lib
  758.   mkdir -p $newdir/usr/lib
  759.  
  760.   echo Create usr/lib/locale
  761.   cp -pdR /usr/lib/locale $newdir/usr/lib
  762.  
  763.   echo Create usr/lib/terminfo
  764.   cp -pdR /usr/lib/terminfo $newdir/usr/lib
  765.  
  766.   echo Create usr/lib/zoneinfo
  767.   cp -pdR /usr/lib/zoneinfo $newdir/usr/lib
  768.  
  769.   echo Create usr/lib/\*.so\*
  770.   cp -pdR /usr/lib/*.so* $newdir/usr/lib
  771.  
  772.   echo Create usr/sbin
  773.   cp -pdR /usr/sbin $newdir/usr
  774.  
  775.   echo Linking usr/tmp
  776.   ln -s /tmp $newdir/usr/tmp
  777.  
  778.   echo Create var
  779.   mkdir -p $newdir/var
  780.  
  781.   echo Create var/lock
  782.   cp -pdR /var/lock $newdir/var
  783.  
  784.   echo Create var/log
  785.   mkdir -p $newdir/var/log
  786.  
  787.   echo Create var/log/wtmp
  788.   cp /dev/null $newdir/var/log/wtmp
  789.  
  790.   echo Create var/run
  791.   cp -pdR /var/run $newdir/var
  792.  
  793.   echo Create var/run/utmp
  794.   cp /dev/null $newdir/var/run/utmp
  795.  
  796.   echo Create var/spool
  797.   cp -pdR /var/spool $newdir/var
  798.  
  799.   echo Linking var/tmp
  800.   ln -s /tmp $newdir/var/tmp
  801.  
  802.   echo Create var/www/html
  803.   mkdir -p $newdir/var/www/html
  804.   chown webmast.www $newdir/var/www/html
  805.   chmod g+s $newdir/var/www/html
  806.  
  807.   echo Create var/www/master
  808.   mkdir -p $newdir/var/www/master
  809.   chown webmast.www $newdir/var/www/master
  810.  
  811.   echo Create var/www/server
  812.   mkdir -p $newdir/var/www/server
  813.   chown webmast.www $newdir/var/www/server
  814.  
  815.   exit 0
  816.  
  817.  
  818.  
  819.  
  820.   4.2.  Virtexec
  821.  
  822.  
  823.   To execute commands in a virtual environment you have to
  824.    chroot  to that directory and then run the command.  I have written a
  825.   special shell script called virtexec that handles this for any
  826.   command:
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.   #!/bin/sh
  860.  
  861.   echo '$Revision: 1.49 $'
  862.  
  863.   BNAME=`basename $0`
  864.   FIRST4CHAR=`echo $BNAME | cut -c1-4`
  865.   REALBNAME=`echo $BNAME | cut -c5-`
  866.  
  867.   if [ "$BNAME" = "virtexec" ]
  868.   then
  869.           echo Cannot run virtexec directly: NEED a symlink
  870.           exit 0
  871.   fi
  872.  
  873.   if [ "$FIRST4CHAR" != "virt" ]
  874.   then
  875.           echo Symlink not a virt function
  876.           exit 0
  877.   fi
  878.  
  879.   list=""
  880.   num=1
  881.   for i in /virtual/*
  882.   do
  883.           if [ ! -d "$i" ]
  884.           then
  885.                   continue
  886.           fi
  887.           if [ "$i" = "/virtual/lost+found" ]
  888.           then
  889.                   continue
  890.           fi
  891.           list="$list $i $num"
  892.           num=`expr $num + 1`
  893.   done
  894.  
  895.   if [ "$list" = "" ]
  896.   then
  897.           echo No virtual environments exist
  898.           exit 0
  899.   fi
  900.  
  901.   dialog --clear --title 'Virtexec' --menu Pick 20 70 12 $list 2> /tmp/menu.$$
  902.   if [ "$?" = "0" ]
  903.   then
  904.           newdir=`cat /tmp/menu.$$`
  905.   else
  906.           newdir=""
  907.   fi
  908.   tput clear
  909.   rm -f /tmp/menu.$$
  910.  
  911.   echo '$Revision: 1.49 $'
  912.  
  913.   if [ ! -d "$newdir" ]
  914.   then
  915.           echo New directory: $newdir: NOT EXIST
  916.           exit 0
  917.   else
  918.           echo New directory: $newdir
  919.   fi
  920.  
  921.   echo bname: $BNAME
  922.  
  923.   echo realbname: $REALBNAME
  924.  
  925.   if [ "$*" = "" ]
  926.   then
  927.           echo args: none
  928.   else
  929.           echo args: $*
  930.   fi
  931.  
  932.   echo Changing to $newdir
  933.   cd $newdir
  934.  
  935.   echo Running program $REALBNAME
  936.  
  937.   chroot $newdir $REALBNAME $*
  938.  
  939.   exit 0
  940.  
  941.  
  942.  
  943.   Please note that you must have the  dialog  program installed on your
  944.   system for this to work.  To use virtexec just symlink a program to
  945.   it.  For example,
  946.  
  947.  
  948.   ln -s /usr/local/bin/virtexec /usr/local/bin/virtpasswd
  949.   ln -s /usr/local/bin/virtexec /usr/local/bin/virtvi
  950.   ln -s /usr/local/bin/virtexec /usr/local/bin/virtpico
  951.   ln -s /usr/local/bin/virtexec /usr/local/bin/virtemacs
  952.   ln -s /usr/local/bin/virtexec /usr/local/bin/virtmailq
  953.  
  954.  
  955.  
  956.   Then if you type virtvi or virtpasswd or virtmailq it will allow you
  957.   to vi a program, change a user's password or check the mail queue on
  958.   your virtual system.  You can create as many virtexec symlinks as you
  959.   want.  Please note that if your program requires a shared library it
  960.   has to be in the virtual filesystem as well as the binary.
  961.  
  962.  
  963.   4.3.  Notes
  964.  
  965.   I install all the scripts in /usr/local/bin.  Anything that I do not
  966.   want to put on the virtual filesystem I put in /usr/local.  The script
  967.   does not copy any of the files in /usr/local to the virtual
  968.   filesystem.  Any files that are important to not cross virtual
  969.   filesystems should be removed.  For example, ssh is installed on my
  970.   system and I did not want the private key for the server available on
  971.   all the virtual filesystems so I remove it from each virtual
  972.   filesystem after I run virtfs.  I also change resolv.conf and remove
  973.   anything that has the name of another domain on it for legal reasons.
  974.   For example, /etc/hosts and /etc/HOSTNAME.
  975.  
  976.  
  977.   The programs that I symlink to virtexec are:
  978.  
  979.  
  980.   ╖  virtpasswd -- change a user password
  981.  
  982.   ╖  virtadduser -- create a user
  983.  
  984.   ╖  virtdeluser -- delete a user
  985.  
  986.   ╖  virtsmbstatus -- see SAMBA status
  987.  
  988.   ╖  virtvi -- edit a file
  989.  
  990.  
  991.   ╖  virtmailq -- check out the mailq
  992.  
  993.   ╖  virtnewaliases -- rebuild alias tables
  994.  
  995.  
  996.   5.  DNS
  997.  
  998.   You can configure DNS normally.  There is a HOWTO on DNS.
  999.  
  1000.  
  1001.   6.  Syslogd
  1002.  
  1003.   6.1.  Problem
  1004.  
  1005.   Syslogd is the system logging utility commonly used on UNIX systems.
  1006.   Syslogd is a daemon that opens a special file called a FIFO.  A FIFO
  1007.   is a special file that acts like a pipe.  Anything that is written to
  1008.   the write side will come out the read side.  Syslogd waits for data
  1009.   from the read side.  There are C functions that write to the write
  1010.   side.  If your program uses these C functions your output will go to
  1011.   syslogd.
  1012.  
  1013.  
  1014.   Remember that we have used a  chroot  environment and the FIFO that
  1015.   syslogd is reading from (/dev/log) is not present.  That means all the
  1016.   virtual environments will not log to syslogd.
  1017.  
  1018.  
  1019.   6.2.  Solution
  1020.  
  1021.   6.2.1.  Setup Links
  1022.  
  1023.  
  1024.   Syslogd can look to a different FIFO if you tell it on the command
  1025.   line so run syslogd with the argument:
  1026.  
  1027.  
  1028.   syslogd -p /virtual/log
  1029.  
  1030.  
  1031.  
  1032.   Then symlink /dev/log to /virtual/log by:
  1033.  
  1034.  
  1035.   ln -sf /virtual/log /dev/log
  1036.  
  1037.  
  1038.  
  1039.   Then hard link all the /dev/log copies to this file by running:
  1040.  
  1041.  
  1042.   ln -f /virtual/log /virtual/domain1.com/dev/log
  1043.  
  1044.  
  1045.  
  1046.   The virtfs script above already does this.  Since /virtual is one
  1047.   contiguous disk and the /dev/log's are hard linked they have the same
  1048.   inode number and point to the same data.  The  chroot  cannot stop
  1049.   this so all your virtual /dev/log's will now function.  Note that all
  1050.   the messages from all the environments will be logged in one place.
  1051.   However, you can write separate programs to filter out the data.
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.   6.2.2.  Syslogd.init
  1058.  
  1059.   This version of the syslogd.init file hard links the /dev/log's each
  1060.   time you start it because syslogd deletes and creates the /dev/log
  1061.   FIFO each time it runs.  Here is a modified syslogd.init file:
  1062.  
  1063.  
  1064.   #!/bin/sh
  1065.  
  1066.   . /etc/rc.d/init.d/functions
  1067.  
  1068.   case "$1" in
  1069.     start)
  1070.           echo -n "Starting dev log: "
  1071.           ln -sf /virtual/log /dev/log
  1072.           echo done
  1073.           echo -n "Starting system loggers: "
  1074.           daemon syslogd -p /virtual/log
  1075.           daemon klogd
  1076.           echo
  1077.           echo -n "Starting virtual dev log: "
  1078.           for i in /virtual/*
  1079.           do
  1080.                   if [ ! -d "$i" ]
  1081.                   then
  1082.                           continue
  1083.                   fi
  1084.                   if [ "$i" = "/virtual/lost+found" ]
  1085.                   then
  1086.                           continue
  1087.                   fi
  1088.                   ln -f /virtual/log $i/dev/log
  1089.                   echo -n "."
  1090.           done
  1091.           echo " done"
  1092.           touch /var/lock/subsys/syslogd
  1093.           ;;
  1094.     stop)
  1095.           echo -n "Shutting down system loggers: "
  1096.           killproc syslogd
  1097.           killproc klogd
  1098.           echo
  1099.           rm -f /var/lock/subsys/syslogd
  1100.           ;;
  1101.     *)
  1102.           echo "Usage: syslogd {start|stop}"
  1103.           exit 1
  1104.   esac
  1105.  
  1106.   exit 0
  1107.  
  1108.  
  1109.  
  1110.  
  1111.   6.3.  Multiple Syslogd's
  1112.  
  1113.   6.3.1.  One Per Disk
  1114.  
  1115.   If you run out of space on one filesystem and you have to break up
  1116.   your virtual domains onto different disks remember that hard links
  1117.   will not cross disks.  That means you will have to run a separate
  1118.   syslogd for each group of domains on a disk.  For example, if you had
  1119.   thirteen domains on /virtual1 and fifteen domains on /virtual2, you
  1120.   would hard link thirteen domains to /virtual1/log and run one syslogd
  1121.   with  syslogd -p /virtual1/log  and hard link fifteen other domains to
  1122.   /virtual2/log with a syslogd running with  syslogd -p /virtual2/log .
  1123.   6.3.2.  One Per Domain
  1124.  
  1125.   If you do not want to centralize the logs to one place you could also
  1126.   run one syslogd per domain.  This wastes process ID's so I do not
  1127.   recommend it but it is easier to implement.   You would have to alter
  1128.   your syslogd.init file to run syslogd as  chroot /virtual/domain1.com
  1129.   syslogd  for each domain.  This will run each syslogd within the
  1130.   chroot  and the logs will be in /virtual/domain1.com/var/log rather
  1131.   than all combined in /var/log.  Do not forget to run a syslogd
  1132.   normally  syslogd  for the main system and a kernel logger  klogd .
  1133.  
  1134.  
  1135.   7.  Virtual FTP
  1136.  
  1137.   7.1.  Inetd
  1138.  
  1139.   Wu-ftpd comes with built in support to make it virtual.  However, you
  1140.   cannot maintain separate password files for each domain.  For example,
  1141.   if
  1142.    bob@domain1.com  and  bob@domain2.com  both want an account you would
  1143.   have to make one of them bob2 or have one of the users choose a
  1144.   different user name.  Since you now have a virtual filesystem for each
  1145.   domain you have separate password files and this problem goes away.
  1146.   Just create a virtnewuser script and a virtpasswd script in the way
  1147.   mentioned above and you are all set.
  1148.  
  1149.  
  1150.   The inetd.conf entries for wu-ftpd:
  1151.  
  1152.  
  1153.   ftp stream tcp nowait root /usr/local/bin/virtuald \
  1154.           virtuald /virtual/conf.ftp wu.ftpd -l -a
  1155.  
  1156.  
  1157.  
  1158.  
  1159.   7.2.  Anonymous FTP
  1160.  
  1161.   These are unaffected by the virtuald setup.  For an anonymous user
  1162.   just create the FTP user in /virtual/domain1.com/etc/passwd like you
  1163.   would normally.
  1164.  
  1165.  
  1166.   ftp:x:14:50:Anonymous FTP:/var/ftp:/bin/false
  1167.  
  1168.  
  1169.  
  1170.   Then setup the anonymous FTP directory.  You have separate password
  1171.   files for each domain so you can restrict which domain has an
  1172.   anonymous FTP account.  Please note that since the FTP server is
  1173.   already  chrooted into the /virtual/domain1.com directory you do not
  1174.   have to prefix any paths with it.
  1175.  
  1176.  
  1177.   7.3.  Virtual FTP Users
  1178.  
  1179.   Wu-ftpd supports something called a guest group.  This allows you to
  1180.   create different FTP areas for each user.  The FTP server does a
  1181.   chroot  to the specified area so the user cannot go outside that
  1182.   directory tree.  If you create the users within a virtual domain this
  1183.   way they will not be able to view the system files.
  1184.  
  1185.  
  1186.   Add the guest's group to the /virtual/domain1.com/etc/ftpaccess file.
  1187.  
  1188.  
  1189.   Create an entry in /virtual/domain1.com/etc/passwd with the  chroot
  1190.   dir and the starting home directory separated by  /./ :
  1191.  
  1192.  
  1193.   guest1:x:8500:51:Guest FTP:/home/g/guest1/./incoming:/bin/false
  1194.  
  1195.  
  1196.  
  1197.  
  1198.   Then setup guest's home like you would for anonymous FTP.  You have
  1199.   separate password files for each domain so you can specifiy which
  1200.   domains have guest accounts and which users within a domain are guest
  1201.   users.  Please note that since the FTP server is already  chrooted
  1202.   into the /virtual/domain1.com directory you do not have to prefix any
  1203.   paths with it.
  1204.  
  1205.  
  1206.   8.  Virtual Web
  1207.  
  1208.   8.1.  Running With Virtuald
  1209.  
  1210.   8.1.1.  Not recommended
  1211.  
  1212.   Apache has their own support for virtual domains.  This is the only
  1213.   program I recommend using the internal virtual domain mechanism.
  1214.   When you run something through inetd there is a cost, the program has
  1215.   to start up each time you run it.  This results in slower response
  1216.   time, which is perfectly fine for most services but is completely
  1217.   unacceptable for web service.  Apache also has a mechanism for
  1218.   stopping connections when too many come in, which can be critical for
  1219.   even medium volume sites.
  1220.  
  1221.  
  1222.   Simply stated, virtualizing Apache with virtuald is a really bad idea.
  1223.   The whole point of virtuald is to fill the gap created when services
  1224.   DO NOT have their own internal mechanism to do the job.  Virtuald is
  1225.   not meant to replace good code that already completes the task at
  1226.   hand.
  1227.  
  1228.  
  1229.   The above not withstanding here is how to do it for those who are
  1230.   foolhardy enough to do so.
  1231.  
  1232.  
  1233.   8.1.2.  Inetd
  1234.  
  1235.   Edit /etc/inetd.conf
  1236.  
  1237.  
  1238.   vi /etc/inetd.conf # Add this line
  1239.   www stream tcp nowait www /usr/local/bin/virtuald \
  1240.           virtuald /virtual/conf.www httpd -f /var/www/conf/httpd.conf
  1241.  
  1242.  
  1243.  
  1244.  
  1245.   8.1.3.  Httpd.conf
  1246.  
  1247.   Edit /var/www/conf/httpd.conf
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.   vi /var/www/conf/httpd.conf # Or wherever you put the Apache config files
  1256.   It should say:
  1257.   ServerType standalone
  1258.  
  1259.   Replace it with:
  1260.   ServerType inetd
  1261.  
  1262.  
  1263.  
  1264.  
  1265.   8.1.4.  Configuration
  1266.  
  1267.   Then configure each instance of the Apache server like you would
  1268.   normally for single domain use.
  1269.  
  1270.  
  1271.   8.1.5.  Httpd.init
  1272.  
  1273.   An httpd.init file is not needed since the server is run through
  1274.   inetd.
  1275.  
  1276.  
  1277.   8.2.  Running With Apache VirtualHost
  1278.  
  1279.   Apache has three configuration files  access.conf ,  httpd.conf , and
  1280.   srm.conf .  Newer versions of Apache have made the three configuration
  1281.   files unnecessary.  However, I find that breaking up the configuration
  1282.   into three sections makes it easier to manage so I will be keeping
  1283.   with that style in this HOWTO document.
  1284.  
  1285.  
  1286.   8.2.1.  Access.conf
  1287.  
  1288.   This configuration file is used to control the accessibility of
  1289.   directories in the web directory structure.  Here is a sample
  1290.   configuration file that shows how to have different options for each
  1291.   domain.
  1292.  
  1293.  
  1294.   # /var/www/conf/access.conf: Global access configuration
  1295.  
  1296.   # Options are inherited from the parent directory
  1297.   # Set the main directory with default options
  1298.   <Directory />
  1299.   AllowOverride None
  1300.   Options Indexes
  1301.   </Directory>
  1302.  
  1303.   # Give one domain a passwd protected directory
  1304.   <Directory /virtual/domain1.com/var/www/html/priv>
  1305.   AuthUserFile /var/www/passwd/domain1.com-priv
  1306.   AuthGroupFile /var/www/passwd/domain1.com-priv-g
  1307.   AuthName PRIVSECTION
  1308.   AuthType Basic
  1309.   <Limit GET PUT POST>
  1310.   require valid-user
  1311.   </Limit>
  1312.   </Directory>
  1313.  
  1314.   # Give another domain Server Side Includes
  1315.   <Directory /virtual/domain2.com/var/www/html>
  1316.   Options IncludesNOEXEC
  1317.   </Directory>
  1318.  
  1319.  
  1320.  
  1321.   8.2.2.  Httpd.conf
  1322.  
  1323.   This configuration file is used to control the main options for the
  1324.   Apache server.  Here is a sample configuration file that shows how to
  1325.   have different options for each domain.
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.   # /var/www/conf/httpd.conf: Main server configuration file
  1388.  
  1389.   # Begin: main conf section
  1390.  
  1391.   # Needed since not using inetd
  1392.   ServerType standalone
  1393.  
  1394.   # Port to run on
  1395.   Port 80
  1396.  
  1397.   # Log clients with names vs IP addresses
  1398.   HostnameLookups on
  1399.  
  1400.   # User to run server as
  1401.   User www
  1402.   Group www
  1403.  
  1404.   # Where server config, error and log files are
  1405.   ServerRoot /var/www
  1406.  
  1407.   # Process Id of server in this file
  1408.   PidFile /var/run/httpd.pid
  1409.  
  1410.   # Internal server process info
  1411.   ScoreBoardFile /var/www/logs/apache_status
  1412.  
  1413.   # Timeout and KeepAlive options
  1414.   Timeout 400
  1415.   KeepAlive 5
  1416.   KeepAliveTimeout 15
  1417.  
  1418.   # Number of servers to run
  1419.   MinSpareServers 5
  1420.   MaxSpareServers 10
  1421.   StartServers 5
  1422.   MaxClients 150
  1423.   MaxRequestsPerChild 30
  1424.  
  1425.   # End: main conf section
  1426.  
  1427.   # Begin: virtual host section
  1428.  
  1429.   # Tell server to accept requests for ip:port
  1430.   # I have one for each IP needed so you can explicitly ignore certain domains
  1431.   Listen 10.10.10.129:80
  1432.   Listen 10.10.10.130:80
  1433.  
  1434.   # VirtualHost directive allows you to specify another virtual
  1435.   # domain on your server.  Most Apache options can be specified
  1436.   # within this section.
  1437.   <VirtualHost www.domain1.com>
  1438.  
  1439.   # Mail to this address on errors
  1440.   ServerAdmin webmaster@domain1.com
  1441.  
  1442.   # Where documents are kept in the virtual domain
  1443.   DocumentRoot /virtual/domain1.com/var/www/html
  1444.  
  1445.   # Name of the server
  1446.   ServerName www.domain1.com
  1447.  
  1448.   # Log files Relative to ServerRoot option
  1449.   ErrorLog logs/domain1.com-error_log
  1450.   TransferLog logs/domain1.com-access_log
  1451.   RefererLog logs/domain1.com-referer_log
  1452.   AgentLog logs/domain1.com-agent_log
  1453.   # Use CGI scripts in this domain
  1454.   ScriptAlias /cgi-bin/ /var/www/cgi-bin/domain1.com/
  1455.   AddHandler cgi-script .cgi
  1456.   AddHandler cgi-script .pl
  1457.   </VirtualHost>
  1458.  
  1459.   <VirtualHost www.domain2.com>
  1460.  
  1461.   # Mail to this address on errors
  1462.   ServerAdmin webmaster@domain2.com
  1463.  
  1464.   # Where documents are kept in the virtual domain
  1465.   DocumentRoot /virtual/domain2.com/var/www/html
  1466.  
  1467.   # Name of the server
  1468.   ServerName www.domain2.com
  1469.  
  1470.   # Log files Relative to ServerRoot option
  1471.   ErrorLog logs/domain2.com-error_log
  1472.   TransferLog logs/domain2.com-access_log
  1473.   RefererLog logs/domain2.com-referer_log
  1474.   AgentLog logs/domain2.com-agent_log
  1475.  
  1476.   # No CGI's for this host
  1477.   </VirtualHost>
  1478.   # End: virtual host section
  1479.  
  1480.  
  1481.  
  1482.  
  1483.   8.2.3.  Srm.conf
  1484.  
  1485.   This configuration file is used to control how requests are serviced
  1486.   and how results are formatted.   You do not have to edit anything here
  1487.   for the virtual domains.  The sample config file from Apache should
  1488.   work.
  1489.  
  1490.  
  1491.   8.2.4.  Httpd.init
  1492.  
  1493.   Nothing special has to be done to the httpd.init file.  Use a standard
  1494.   one that comes with the Apache configuration.
  1495.  
  1496.  
  1497.   8.3.  File Descriptor Overflow
  1498.  
  1499.   8.3.1.  Warning
  1500.  
  1501.   This only applies to the standalone style Apache server.  A server run
  1502.   through inetd does not interact with the other domains so it has the
  1503.   whole file descriptor table.
  1504.  
  1505.  
  1506.   Every log file that the Apache server opens is another file descriptor
  1507.   for the process.  There is a limit of 256 file descriptors per process
  1508.   in Linux.  Since you have multiple domains you are using a lot more
  1509.   file descriptors.  If you have too many domains running off of one
  1510.   Apache web server process you can overflow this table.  This would
  1511.   mean that certain logs would not work and CGI's would fail.
  1512.  
  1513.  
  1514.   8.3.2.  Multiple Apache Servers
  1515.  
  1516.   If you assume five file descriptors per domain you can have 50 domains
  1517.   running on your Apache server without any problems.  However, if you
  1518.   find your server having problems like this you could create /var/www1
  1519.   with an Apache server in charge of domain1 - domain25 and /var/www2
  1520.   with an Apache server in charge of domain26 - domain50 and so on.
  1521.   This would give each server their own configuration, error, and log
  1522.   directory.  Each server should be configured separately with their own
  1523.   Listen and VirtualHost directives.  Do not forget to run multiple
  1524.   servers in your httpd.init file.
  1525.  
  1526.  
  1527.   8.4.  Sharing Servers With One IP
  1528.  
  1529.   8.4.1.  Saving IPs
  1530.  
  1531.   The HTTP (HyperText Transfer Protocol) version 1.1 added a feature
  1532.   that communicates the name of the server to the client.  This means
  1533.   that the client does not need to look up the server from its IP
  1534.   address.  Therefore, two virtual servers could have the same IP
  1535.   address and be different web sites. The Apache configuration is the
  1536.   same as above except that you do not have to put in a different Listen
  1537.   directive since the two domains will have the same IP.
  1538.  
  1539.  
  1540.   8.4.2.  Drawback
  1541.  
  1542.   The only problem is that virtuald uses IP addresses to distinguish
  1543.   between domains.  In its current form virtuald would not be able to
  1544.   chroot to different spool directories for each domain.  Therefore,
  1545.   mail would only be able to respond as one IP and there would no longer
  1546.   be a unique spool directory for each domain.  All the web sharing IP
  1547.   clients would have to share that IPs spool directory.  That would mean
  1548.   duplicate usernames would be an issue again.  However, that is the
  1549.   price you pay for sharing IPs.
  1550.  
  1551.  
  1552.   8.5.  More Information
  1553.  
  1554.   This HOWTO only shows how to implement virtual support on the Apache
  1555.   web server.  Most web servers use a similar interface.  For more
  1556.   information on virtual web hosting consult the WWW HOWTO, the
  1557.   documentation for Apache at Apache's Site, or the documentation at
  1558.   ApacheWeek.
  1559.  
  1560.  
  1561.   9.  Virtual Mail/Pop
  1562.  
  1563.   9.1.  Problem
  1564.  
  1565.   Virtual mail support is in ever increasing demand.  Sendmail says it
  1566.   supports virtual mail.  What it does support is listening for incoming
  1567.   mail from different domains.  You can then specify to have the mail
  1568.   forwarded somewhere.  However, if you forward it to the local machine
  1569.   and have incoming mail to bob@domain1.com and bob@domain2.com they
  1570.   will go to the same mail folder.  This is a problem since both bob's
  1571.   are different people with different mail.
  1572.  
  1573.  
  1574.   9.2.  Solution
  1575.  
  1576.   You can make sure that each user name is unique by using a numbering
  1577.   scheme: bob1, bob2, etc or prepending a few characters to each
  1578.   username dom1bob, dom2bob, etc.  You could also hack mail and pop to
  1579.   do these conversions behind the scenes but that can get messy.
  1580.   Outgoing mail also has the banner maindomain.com and you want each
  1581.   subdomain's outgoing mail banner to be different.
  1582.  
  1583.  
  1584.  
  1585.   I have two solutions.  One works with sendmail and one works with
  1586.   Qmail.  The solution with sendmail should work with a stock install of
  1587.   sendmail.  However, it shares all the limitations built into sendmail.
  1588.   It also requires that one sendmail has to be run in queue mode for
  1589.   each domain.  Having 50 or more sendmail queue processes that wake up
  1590.   every hour can put a little strain on a machine.
  1591.  
  1592.  
  1593.   The solution offered with Qmail does not require multiple instances of
  1594.   Qmail and can run out of one queue directory.  It does require an
  1595.   extra program since Qmail does not rely on virtuald.  I believe a
  1596.   similar procedure can be done with sendmail.  However, Qmail lends
  1597.   itself to this solution more readily.
  1598.  
  1599.  
  1600.   I do not endorse any one program over the other.  The sendmail install
  1601.   is a little more straight forward but Qmail is probably the more
  1602.   powerful of the two mail server packages.
  1603.  
  1604.  
  1605.   9.3.  Sendmail Solution
  1606.  
  1607.   9.3.1.  Introduction
  1608.  
  1609.   Each virtual filesystem gives a domain its own /etc/passwd.  This
  1610.   means that bob@domain1.com and bob@domain2.com are different users in
  1611.   different /etc/passwds so mail will be no problem.  They also have
  1612.   their own spool directories so the mail folders will be different
  1613.   files on different virtual filesystems.
  1614.  
  1615.  
  1616.   9.3.2.  Create Sendmail Configuration File
  1617.  
  1618.   Create /etc/sendmail.cf like you would normally through m4.  I used:
  1619.  
  1620.  
  1621.   divert(0)
  1622.   VERSIONID(`tcpproto.mc')
  1623.   OSTYPE(linux)
  1624.   FEATURE(redirect)
  1625.   FEATURE(always_add_domain)
  1626.   FEATURE(use_cw_file)
  1627.   FEATURE(local_procmail)
  1628.   MAILER(local)
  1629.   MAILER(smtp)
  1630.  
  1631.  
  1632.  
  1633.  
  1634.   9.3.3.  Edit Sendmail Configuration File
  1635.  
  1636.   Edit /virtual/domain1.com/etc/sendmail.cf to respond as your virtual
  1637.   domain:
  1638.  
  1639.  
  1640.   vi /virtual/domain1.com/etc/sendmail.cf # Approximately Line 86
  1641.   It should say:
  1642.  
  1643.   #Dj$w.Foo.COM
  1644.  
  1645.   Replace it with:
  1646.  
  1647.   Djdomain1.com
  1648.  
  1649.  
  1650.  
  1651.   9.3.4.  Sendmail Local Delivery
  1652.  
  1653.   Edit /virtual/domain1.com/etc/sendmail.cw with the local hostnames.
  1654.  
  1655.  
  1656.   vi /virtual/domain1.com/etc/sendmail.cw
  1657.   mail.domain1.com
  1658.   domain1.com
  1659.   domain1
  1660.   localhost
  1661.  
  1662.  
  1663.  
  1664.  
  1665.   9.3.5.  Sendmail Between Virtual Domains: The Hack (PRE8.8.6)
  1666.  
  1667.   However, sendmail requires one minor source code modification.
  1668.   Sendmail has a file called /etc/sendmail.cw and it contains all
  1669.   machine names that sendmail will deliver mail to locally rather than
  1670.   forwarding to another machine.  Sendmail does internal checking of all
  1671.   the devices on the machine to initialize this list with the local IPs.
  1672.   This presents a problem if you are mailing between virtual domains on
  1673.   the same machine.  Sendmail will be fooled into thinking another
  1674.   virtual domain is a local address and spool the mail locally.  For
  1675.   example, bob@domain1.com sends mail to fred@domain2.com.  Since
  1676.   domain1.com's sendmail thinks domain2.com is local, it will spool the
  1677.   mail on domain1.com and never send it to domain2.com.  You have to
  1678.   modify sendmail (I did this on v8.8.5 without a problem):
  1679.  
  1680.  
  1681.   vi v8.8.5/src/main.c # Approximately Line 494
  1682.   It should say:
  1683.  
  1684.   load_if_names();
  1685.  
  1686.   Replace it with:
  1687.  
  1688.   /* load_if_names(); Commented out since hurts virtual */
  1689.  
  1690.  
  1691.  
  1692.   Note only do this if you need to send mail between virtual domains
  1693.   which I think is probable.
  1694.  
  1695.   This will fix the problem.  However, the main ethernet device eth0 is
  1696.   not removed.  Therefore, if you send mail from a virtual IP to the one
  1697.   on eth0 on the same box it will delivery locally.  Therefore, I just
  1698.   use this as a dummy IP virtual1.maindomain.com (10.10.10.157).  I
  1699.   never send mail to this host so neither will the virtual domains.
  1700.   This is also the IP I would use to ssh into the box to check if the
  1701.   system is ok.
  1702.  
  1703.  
  1704.   9.3.6.  Sendmail Between Virtual Domains: New Sendmail Feature
  1705.   (POST8.8.6)
  1706.  
  1707.   As of Sendmail V8.8.6, there is a new option to disable loading of the
  1708.   extra network interfaces.  This means you do NOT have to alter the
  1709.   code in any way.  It is called  DontProbeInterfaces .
  1710.  
  1711.  
  1712.   Edit /virtual/domain1.com/etc/sendmail.cf
  1713.  
  1714.  
  1715.  
  1716.  
  1717.   vi /virtual/domain1.com/etc/sendmail.cf # Add the line
  1718.   O DontProbeInterfaces=True
  1719.  
  1720.  
  1721.  
  1722.  
  1723.   9.3.7.  Sendmail.init
  1724.  
  1725.   Sendmail cannot be started stand alone anymore so you have to run it
  1726.   through inetd.  This is inefficient and will result in lower start up
  1727.   time but if you had such a high hit site you would not share it on a
  1728.   virtual box with other domains.  Note that you are NOT running with
  1729.   the  -bd  flag.  Also note that you need a  sendmail -q  running for
  1730.   each domain to queue up undelivered mail. The new sendmail.init file:
  1731.  
  1732.  
  1733.   #!/bin/sh
  1734.  
  1735.   . /etc/rc.d/init.d/functions
  1736.  
  1737.   case "$1" in
  1738.     start)
  1739.           echo -n "Starting sendmail: "
  1740.           daemon sendmail -q1h
  1741.           echo
  1742.           echo -n "Starting virtual sendmail: "
  1743.           for i in /virtual/*
  1744.           do
  1745.                   if [ ! -d "$i" ]
  1746.                   then
  1747.                           continue
  1748.                   fi
  1749.                   if [ "$i" = "/virtual/lost+found" ]
  1750.                   then
  1751.                           continue
  1752.                   fi
  1753.                   chroot $i sendmail -q1h
  1754.                   echo -n "."
  1755.           done
  1756.           echo " done"
  1757.           touch /var/lock/subsys/sendmail
  1758.           ;;
  1759.     stop)
  1760.           echo -n "Stopping sendmail: "
  1761.           killproc sendmail
  1762.           echo
  1763.           rm -f /var/lock/subsys/sendmail
  1764.           ;;
  1765.     *)
  1766.           echo "Usage: sendmail {start|stop}"
  1767.           exit 1
  1768.   esac
  1769.  
  1770.   exit 0
  1771.  
  1772.  
  1773.  
  1774.  
  1775.   9.3.8.  Inetd Setup
  1776.  
  1777.   Pop should install normally with no extra effort.  It will just need
  1778.   the inetd entry for it with the virtuald part added.  The inetd.conf
  1779.   entries for sendmail and pop:
  1780.  
  1781.  
  1782.  
  1783.   pop-3 stream tcp nowait root /usr/local/bin/virtuald \
  1784.           virtuald /virtual/conf.pop in.qpop -s
  1785.   smtp stream tcp nowait root /usr/local/bin/virtuald \
  1786.           virtuald /virtual/conf.mail sendmail -bs
  1787.  
  1788.  
  1789.  
  1790.  
  1791.   9.4.  Qmail Solution
  1792.  
  1793.   9.4.1.  Introduction
  1794.  
  1795.   This solution takes over the delivery responsibilities of qmail-local,
  1796.   so use of the .qmail files in the virtual home directories will not
  1797.   work.  However, each domain will still get a domain master user that
  1798.   will control aliasing for the whole domain.  Two external programs
  1799.   will be used for that domain masters .qmail-default file.  The mail
  1800.   will be passed through these two programs in order to deliver mail for
  1801.   each domain.
  1802.  
  1803.  
  1804.   Two programs are required since one of them is run setuid root.  It is
  1805.   a small program that changes to a non-root user and then runs the
  1806.   second program.  Consult your nearest security related site for a
  1807.   discussion as to why this is necessary.
  1808.  
  1809.  
  1810.   This solution bypasses the need for using virtuald.  Qmail is flexible
  1811.   enough to not require a general virtuald setup.  Qmail's design
  1812.   utilizes the chaining of programs together to deliver mail.  This
  1813.   design makes it very easy to insert the virtual section into the Qmail
  1814.   delivery process without altering a stock install of Qmail.
  1815.  
  1816.  
  1817.   A note that since you are using one Qmail any unqualified domain name
  1818.   will be expanded with the domain of the main server.  This is because
  1819.   you do not have a separate Qmail server for each domain.  Therefore,
  1820.   make sure that your client (Eudora, elm, mutt, etc.) knows to expand
  1821.   all of your unqualified domain names.
  1822.  
  1823.  
  1824.   9.4.2.  Setup Virtual Domains
  1825.  
  1826.   Qmail has to be configured to accept mail for each of the virtual
  1827.   domains you will be serving.  Type the following commands.
  1828.  
  1829.  
  1830.   echo "domain1.com:domain1" >> /var/qmail/control/virtualdomains
  1831.  
  1832.  
  1833.  
  1834.  
  1835.   9.4.3.  Setup Domain Master User
  1836.  
  1837.   Add to your main /etc/passwd file the user domain1.  I would make the
  1838.   shell /bin/false so that the domain master cannot log in.   That user
  1839.   will be able to add .qmail files and all mail for domain1 will route
  1840.   through that account.  Note that usernames can only be eight
  1841.   characters long and domain names can be longer.  The remaining
  1842.   characters are truncated.  That means that user domain12 and domain123
  1843.   are going to be the same user and Qmail might get confused.  So be
  1844.   careful in your master domain user naming convention.
  1845.  
  1846.  
  1847.   Create the domain master's .qmail files with the following commands.
  1848.   Add any other system aliases at this point.  For example, webmaster or
  1849.   hostmaster.
  1850.  
  1851.  
  1852.   echo "user@domain1.com" > /home/d/domain1/.qmail-mailer-daemon
  1853.   echo "user@domain1.com" > /home/d/domain1/.qmail-postmaster
  1854.   echo "user@domain1.com" > /home/d/domain1/.qmail-root
  1855.  
  1856.  
  1857.  
  1858.   Create the domain master's .qmail-default file.  This will filter all
  1859.   mail to the virtual domain.
  1860.  
  1861.  
  1862.   echo "| /usr/local/bin/virtmailfilter" > /home/d/domain1/.qmail-default
  1863.  
  1864.  
  1865.  
  1866.  
  1867.   9.4.4.  Tcpserver
  1868.  
  1869.   Qmail requires a special pop that can support the Maildir format.  The
  1870.   pop program has to be virtualized.  The author of Qmail recommends
  1871.   using tcpserver (an inetd replacement) with Qmail so my examples use
  1872.   tcpserver and NOT inetd.
  1873.  
  1874.  
  1875.   Tcpserver does not require a config file.  All the information can be
  1876.   passed to it via the command line.  Here is the tcpserver.init file
  1877.   that you would use for the mail daemon and popper:
  1878.  
  1879.  
  1880.   #!/bin/sh
  1881.  
  1882.   . /etc/rc.d/init.d/functions
  1883.  
  1884.   QMAILDUSER=`grep qmaild /etc/passwd | cut -d: -f3`
  1885.   QMAILDGROUP=`grep qmaild /etc/passwd | cut -d: -f4`
  1886.  
  1887.   # See how we were called.
  1888.   case "$1" in
  1889.     start)
  1890.           echo -n "Starting tcpserver: "
  1891.           tcpserver -u 0 -g 0 0 pop-3 /usr/local/bin/virtuald \
  1892.                   /virtual/conf.pop qmail-popup virt.domain1.com \
  1893.                   /bin/checkpassword /bin/qmail-pop3d Maildir &
  1894.           echo -n "pop "
  1895.           tcpserver -u $QMAILDUSER -g $QMAILDGROUP 0 smtp \
  1896.                   /var/qmail/bin/qmail-smtpd &
  1897.           echo -n "qmail "
  1898.           echo
  1899.           touch /var/lock/subsys/tcpserver
  1900.           ;;
  1901.     stop)
  1902.           echo -n "Stopping tcpserver: "
  1903.           killall -TERM tcpserver
  1904.           echo -n "killing "
  1905.           echo
  1906.           rm -f /var/lock/subsys/tcpserver
  1907.           ;;
  1908.     *)
  1909.           echo "Usage: tcpserver {start|stop}"
  1910.           exit 1
  1911.   esac
  1912.  
  1913.   exit 0
  1914.  
  1915.   9.4.5.  Qmail.init
  1916.  
  1917.   You can use the standard Qmail init script provided.  Qmail comes with
  1918.   very good documentation describing how to set this up.
  1919.  
  1920.  
  1921.   9.4.6.  Source
  1922.  
  1923.   You require two other programs to get virtual mail working with Qmail.
  1924.   They are virtmailfilter and virtmaildelivery.  This is the C source to
  1925.   virtmailfilter.  It should be installed in /usr/local/bin with
  1926.   permissions 4750, user root, and group nofiles.
  1927.  
  1928.  
  1929.  
  1930.  
  1931.  
  1932.  
  1933.  
  1934.  
  1935.  
  1936.  
  1937.  
  1938.  
  1939.  
  1940.  
  1941.  
  1942.  
  1943.  
  1944.  
  1945.  
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.  
  1981.   #include <sys/wait.h>
  1982.   #include <unistd.h>
  1983.   #include <string.h>
  1984.   #include <stdlib.h>
  1985.   #include <stdio.h>
  1986.   #include <ctype.h>
  1987.   #include <pwd.h>
  1988.  
  1989.   #define VIRTPRE                 "/virtual"
  1990.  
  1991.   #define VIRTPWFILE              "etc/passwd"
  1992.   #define VIRTDELIVERY            "/usr/local/bin/virtmaildelivery"
  1993.   #define VIRTDELIVERY0           "virtmaildelivery"
  1994.  
  1995.   #define PERM                    100
  1996.   #define TEMP                    111
  1997.   #define BUFSIZE                 8192
  1998.  
  1999.   int main(int argc,char **argv)
  2000.   {
  2001.           char *username,*usernameptr,*domain,*domainptr,*homedir;
  2002.           char virtpath[BUFSIZE];
  2003.           struct passwd *p;
  2004.           FILE *fppw;
  2005.           int status;
  2006.           gid_t gid;
  2007.           pid_t pid;
  2008.  
  2009.           if (!(username=getenv("EXT")))
  2010.           {
  2011.                   fprintf(stdout,"environment variable EXT not set\n");
  2012.                   exit(TEMP);
  2013.           }
  2014.  
  2015.           for(usernameptr=username;*usernameptr;usernameptr++)
  2016.           {
  2017.                   *usernameptr=tolower(*usernameptr);
  2018.           }
  2019.  
  2020.           if (!(domain=getenv("HOST")))
  2021.           {
  2022.                   fprintf(stdout,"environment variable HOST not set\n");
  2023.                   exit(TEMP);
  2024.           }
  2025.  
  2026.           for(domainptr=domain;*domainptr;domainptr++)
  2027.           {
  2028.                   if (*domainptr=='.' && *(domainptr+1)=='.')
  2029.                   {
  2030.                           fprintf(stdout,"environment variable HOST has ..\n");
  2031.                           exit(TEMP);
  2032.                   }
  2033.                   if (*domainptr=='/')
  2034.                   {
  2035.                           fprintf(stdout,"environment variable HOST has /\n");
  2036.                           exit(TEMP);
  2037.                   }
  2038.  
  2039.                   *domainptr=tolower(*domainptr);
  2040.           }
  2041.  
  2042.           for(domainptr=domain;;)
  2043.           {
  2044.                   snprintf(virtpath,BUFSIZE,"%s/%s",VIRTPRE,domainptr);
  2045.                   if (chdir(virtpath)>=0)
  2046.                           break;
  2047.                   if (!(domainptr=strchr(domainptr,'.')))
  2048.                   {
  2049.                           fprintf(stdout,"domain failed: %s\n",domain);
  2050.                           exit(TEMP);
  2051.                   }
  2052.  
  2053.                   domainptr++;
  2054.           }
  2055.  
  2056.           if (!(fppw=fopen(VIRTPWFILE,"r+")))
  2057.           {
  2058.                   fprintf(stdout,"fopen failed: %s\n",VIRTPWFILE);
  2059.                   exit(TEMP);
  2060.           }
  2061.  
  2062.           while((p=fgetpwent(fppw))!=NULL)
  2063.           {
  2064.                   if (!strcmp(p->pw_name,username))
  2065.                           break;
  2066.           }
  2067.  
  2068.           if (!p)
  2069.           {
  2070.                   fprintf(stdout,"user %s: not exist\n",username);
  2071.                   exit(PERM);
  2072.           }
  2073.  
  2074.           if (fclose(fppw)==EOF)
  2075.           {
  2076.                   fprintf(stdout,"fclose failed\n");
  2077.                   exit(TEMP);
  2078.           }
  2079.  
  2080.           gid=p->pw_gid;
  2081.           homedir=p->pw_dir;
  2082.  
  2083.           if (setgid(gid)<0 || setuid(p->pw_uid)<0)
  2084.           {
  2085.                   fprintf(stdout,"setuid/setgid failed\n");
  2086.                   exit(TEMP);
  2087.           }
  2088.  
  2089.           switch(pid=fork())
  2090.           {
  2091.                   case -1:
  2092.                           fprintf(stdout,"fork failed\n");
  2093.                           exit(TEMP);
  2094.                   case 0:
  2095.                           if (execl(VIRTDELIVERY,VIRTDELIVERY0,username,homedir,NULL)<0)
  2096.                           {
  2097.                                   fprintf(stdout,"execl failed\n");
  2098.                                   exit(TEMP);
  2099.                           }
  2100.                   default:
  2101.                           if (wait(&status)<0)
  2102.                           {
  2103.                                   fprintf(stdout,"wait failed\n");
  2104.                                   exit(TEMP);
  2105.                           }
  2106.                           if (!WIFEXITED(status))
  2107.                           {
  2108.                                   fprintf(stdout,"child did not exit normally\n");
  2109.                                   exit(TEMP);
  2110.                           }
  2111.                           break;
  2112.           }
  2113.           exit(WEXITSTATUS(status));
  2114.   }
  2115.  
  2116.  
  2117.  
  2118.  
  2119.   9.4.7.  Source
  2120.  
  2121.   You require two other programs to get virtual mail working with Qmail.
  2122.   They are virtmailfilter and virtmaildelivery.  This is the C source to
  2123.   virtmaildelivery.  It should be installed in /usr/local/bin with
  2124.   permissions 0755, user root, and group root.
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.  
  2171.  
  2172.  
  2173.  
  2174.  
  2175.  
  2176.  
  2177.  
  2178.  
  2179.   #include <sys/stat.h>
  2180.   #include <sys/file.h>
  2181.   #include <stdlib.h>
  2182.   #include <string.h>
  2183.   #include <unistd.h>
  2184.   #include <stdio.h>
  2185.   #include <errno.h>
  2186.   #include <time.h>
  2187.  
  2188.   #define TEMP                    111
  2189.   #define BUFSIZE                 8192
  2190.   #define ATTEMPTS                10
  2191.  
  2192.   int main(int argc,char **argv)
  2193.   {
  2194.           char *user,*homedir,*dtline,*rpline,buffer[BUFSIZE],*p,mail[BUFSIZE];
  2195.           char maildir[BUFSIZE],newmaildir[BUFSIZE],host[BUFSIZE];
  2196.           int fd,n,nl,i,retval;
  2197.           struct stat statp;
  2198.           time_t thetime;
  2199.           pid_t pid;
  2200.           FILE *fp;
  2201.  
  2202.           retval=0;
  2203.  
  2204.           if (!argv[1])
  2205.           {
  2206.                   fprintf(stdout,"invalid arguments: need username\n");
  2207.                   exit(TEMP);
  2208.           }
  2209.  
  2210.           user=argv[1];
  2211.  
  2212.           if (!argv[2])
  2213.           {
  2214.                   fprintf(stdout,"invalid arguments: need home directory\n");
  2215.                   exit(TEMP);
  2216.           }
  2217.  
  2218.           homedir=argv[2];
  2219.  
  2220.           if (!(dtline=getenv("DTLINE")))
  2221.           {
  2222.                   fprintf(stdout,"environment variable DTLINE not set\n");
  2223.                   exit(TEMP);
  2224.           }
  2225.  
  2226.           if (!(rpline=getenv("RPLINE")))
  2227.           {
  2228.                   fprintf(stdout,"environment variable RPLINE not set\n");
  2229.                   exit(TEMP);
  2230.           }
  2231.  
  2232.           while (*homedir=='/')
  2233.                   homedir++;
  2234.           snprintf(maildir,BUFSIZE,"%s/Maildir",homedir);
  2235.           if (chdir(maildir)<0)
  2236.           {
  2237.                   fprintf(stdout,"chdir failed: %s\n",maildir);
  2238.                   exit(TEMP);
  2239.           }
  2240.  
  2241.           time(&thetime);
  2242.           pid=getpid();
  2243.           if (gethostname(host,BUFSIZE)<0)
  2244.           {
  2245.                   fprintf(stdout,"gethostname failed\n");
  2246.                   exit(TEMP);
  2247.           }
  2248.  
  2249.           for(i=0;i<ATTEMPTS;i++)
  2250.           {
  2251.                   snprintf(mail,BUFSIZE,"tmp/%u.%d.%s",thetime,pid,host);
  2252.                   errno=0;
  2253.                   stat(mail,&statp);
  2254.                   if (errno==ENOENT)
  2255.                           break;
  2256.  
  2257.                   sleep(2);
  2258.                   time(&thetime);
  2259.           }
  2260.           if (i>=ATTEMPTS)
  2261.           {
  2262.                   fprintf(stdout,"could not create %s\n",mail);
  2263.                   exit(TEMP);
  2264.           }
  2265.  
  2266.           if (!(fp=fopen(mail,"w+")))
  2267.           {
  2268.                   fprintf(stdout,"fopen failed: %s\n",mail);
  2269.                   retval=TEMP; goto unlinkit;
  2270.           }
  2271.  
  2272.           fd=fileno(fp);
  2273.  
  2274.           if (fprintf(fp,"%s",rpline)<0)
  2275.           {
  2276.                   fprintf(stdout,"fprintf failed\n");
  2277.                   retval=TEMP; goto unlinkit;
  2278.           }
  2279.  
  2280.           if (fprintf(fp,"%s",dtline)<0)
  2281.           {
  2282.                   fprintf(stdout,"fprintf failed\n");
  2283.                   retval=TEMP; goto unlinkit;
  2284.           }
  2285.  
  2286.           while(fgets(buffer,BUFSIZE,stdin))
  2287.           {
  2288.                   for(p=buffer;*p=='>';p++)
  2289.                           ;
  2290.  
  2291.                   if (!strncmp(p,"From ",5))
  2292.                   {
  2293.                           if (fputc('>',fp)<0)
  2294.                           {
  2295.                                   fprintf(stdout,"fputc failed\n");
  2296.                                   retval=TEMP; goto unlinkit;
  2297.                           }
  2298.                   }
  2299.  
  2300.                   if (fprintf(fp,"%s",buffer)<0)
  2301.                   {
  2302.                           fprintf(stdout,"fprintf failed\n");
  2303.                           retval=TEMP; goto unlinkit;
  2304.                   }
  2305.           }
  2306.  
  2307.           p=buffer+strlen(buffer);
  2308.           nl=2;
  2309.           if (*p=='\n')
  2310.                   nl=1;
  2311.           for(n=0;n<nl;n++)
  2312.           {
  2313.                   if (fputc('\n',fp)<0)
  2314.                   {
  2315.                           fprintf(stdout,"fputc failed\n");
  2316.                           retval=TEMP; goto unlinkit;
  2317.                   }
  2318.           }
  2319.  
  2320.           if (fsync(fd)<0)
  2321.           {
  2322.                   fprintf(stdout,"fsync failed\n");
  2323.                   retval=TEMP; goto unlinkit;
  2324.           }
  2325.  
  2326.           if (fclose(fp)==EOF)
  2327.           {
  2328.                   fprintf(stdout,"fclose failed\n");
  2329.                   retval=TEMP; goto unlinkit;
  2330.           }
  2331.  
  2332.           snprintf(newmaildir,BUFSIZE,"new/%u.%d.%s",thetime,pid,host);
  2333.           if (link(mail,newmaildir)<0)
  2334.           {
  2335.                   fprintf(stdout,"link failed: %s %s\n",mail,newmaildir);
  2336.                   retval=TEMP; goto unlinkit;
  2337.           }
  2338.  
  2339.   unlinkit:
  2340.           if (unlink(mail)<0)
  2341.           {
  2342.                   fprintf(stdout,"unlink failed: %s\n",mail);
  2343.                   retval=TEMP;
  2344.           }
  2345.  
  2346.           exit(retval);
  2347.   }
  2348.  
  2349.  
  2350.  
  2351.  
  2352.   9.5.  Acknowledgement
  2353.  
  2354.   Thank you Vicente Gonzalez (vince@nycrc.net) for helping make the
  2355.   Qmail solution possible.  You can certainly mail your thanks to Vince,
  2356.   however all questions and comments including issues regarding Qmail,
  2357.   about this HOWTO should continue to be directed to me.
  2358.  
  2359.  
  2360.   10.  Virtual Samba
  2361.  
  2362.   10.1.  Setup
  2363.  
  2364.   Virtual SAMBA is very simple to install.  Make sure that the following
  2365.   files are setup properly:
  2366.  
  2367.  
  2368.   ╖  /virtual/domain1.com/etc/smb.conf FILE
  2369.  
  2370.   ╖  /virtual/domain1.com/var/lock/samba DIRECTORY
  2371.  
  2372.   ╖  /virtual/domain1.com/var/log DIRECTORY
  2373.  
  2374.   ╖  /usr/local/bin/virtsmbstatus SYMLINK /usr/local/bin/virtexec
  2375.  
  2376.  
  2377.   10.2.  Inetd
  2378.  
  2379.   Edit /etc/inetd.conf
  2380.  
  2381.  
  2382.   vi /etc/inetd.conf # Add this line
  2383.   netbios-ssn stream tcp nowait root /usr/local/bin/virtuald \
  2384.           virtuald /virtual/conf.smbd smbd
  2385.  
  2386.  
  2387.  
  2388.  
  2389.   10.3.  Smb.init
  2390.  
  2391.   An smb.init file is not needed since the server is run through inetd.
  2392.  
  2393.  
  2394.   11.  Virtual Other
  2395.  
  2396.  
  2397.   Any other service should be a similar procedure.
  2398.  
  2399.  
  2400.   ╖  Run virtfs to add the binaries and libraries to the virtual
  2401.      filesystem.
  2402.  
  2403.   ╖  Add it to /etc/inetd.conf.
  2404.  
  2405.   ╖  Create a /virtual/conf.service file.
  2406.  
  2407.   ╖  Create any virtual scripts that need to be made.
  2408.  
  2409.  
  2410.   12.  Conclusion
  2411.  
  2412.   Those are all the steps you need. Again mail any responses to Computer
  2413.   Resource Center.  If you have a question or an update to the document
  2414.   let me know and I will add it.
  2415.  
  2416.  
  2417.   The document has met with a very good response.  I thank all the
  2418.   people who sent me questions as they are helping to shape the document
  2419.   to meet the needs of users everywhere.  Before you ask a question I
  2420.   urge you to read the FAQ to see if it has been already asked and
  2421.   answered.  Thanks again.  Brian
  2422.  
  2423.  
  2424.   13.  FAQ
  2425.  
  2426.   Q1. I created sendmail.init and syslogd.init.  I put them in
  2427.   /usr/local/bin and tried to run them but I got errors.
  2428.  
  2429.  
  2430.   A1. These files are called init scripts.  They are run by the program
  2431.   init when your computer boots.  They do not go with the /usr/local
  2432.   binaries.  Consult the Linux System Administrators Guide or the Linux
  2433.   Getting Started Guide for information on how to use the init scripts
  2434.   system.
  2435.  
  2436.  
  2437.   Q2. I put these lines into /etc/sendmail.cf
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.   divert(0)
  2444.   VERSIONID(`tcpproto.mc')
  2445.   OSTYPE(linux)
  2446.   FEATURE(redirect)
  2447.   FEATURE(always_add_domain)
  2448.   FEATURE(use_cw_file)
  2449.   FEATURE(local_procmail)
  2450.   MAILER(local)
  2451.   MAILER(smtp)
  2452.  
  2453.  
  2454.  
  2455.   And I got really stange output.  Why?
  2456.  
  2457.  
  2458.   A2. You do not put these lines directly in /etc/sendmail.cf.  The
  2459.   sendmail.cf file was written to be easy for sendmail to understand and
  2460.   hard for humans to read.  Therefore, to make it easy to configure we
  2461.   use a program called m4 and its macro capabilities to create the
  2462.   sendmail.cf file.  The FEATURE lines are actually macros that expand
  2463.   to sendmail configuration statements.   See the sendmail docs on how
  2464.   to configure sendmail through this method.  Also note that you create
  2465.   a main /etc/sendmail.cf file and the virtfs script then copies this to
  2466.   /virtual/domain1.com/etc/sendmail.cf.  Then you edit that sendmail.cf
  2467.   file to respond as your domain.
  2468.  
  2469.  
  2470.   Q3. Where do I get virtuald, what is it, and how do I use it?
  2471.  
  2472.  
  2473.   A3. Virtuald is C source that I wrote to run a virtual service.  It is
  2474.   included with this HOWTO.  You compile it like a normal C program
  2475.    make virtuald .  The resulting binary is placed into /usr/local/bin.
  2476.   Add lines to /etc/inetd.conf that use virtuald as a wrapper to a
  2477.   normal network server program.
  2478.  
  2479.  
  2480.   Q4. I do not have dialog installed on my system?
  2481.  
  2482.  
  2483.   A4. Dialog is a program that allows you to put dialog pop up windows
  2484.   into your shell scripts.  It is required for my virtual shell script
  2485.   examples to work.  You can get a copy of dialog at sunsite.  It
  2486.   compiles very easily and should be no problem to install.
  2487.  
  2488.  
  2489.   Q5. How can I know if virtual syslogd is working?
  2490.  
  2491.  
  2492.   A5. When virtuald runs it should output the following messages to
  2493.   syslogd (/var/log/messages):
  2494.  
  2495.  
  2496.   Nov 19 17:21:07 virtual virtuald[10223]: Virtuald Starting: $Revision: 1.49 $
  2497.   Nov 19 17:21:07 virtual virtuald[10223]: Incoming ip: 204.249.11.136
  2498.   Nov 19 17:21:07 virtual virtuald[10223]: Chroot dir: /virtual/domain1.com
  2499.  
  2500.  
  2501.  
  2502.   The  Chroot  dir message is sent by virtuald after the  chroot  system
  2503.   call is performed.  If this message appears virtual syslogd is
  2504.   working.   If the service you are virtualizing logs messages to
  2505.   syslogd and you see them that is also a sign that virtual syslogd is
  2506.   correctly setup.
  2507.  
  2508.  
  2509.   Note that if you have not turned on the compile time option
  2510.   VERBOSELOG, virtuald will not log at all.  The only way to tell if
  2511.   virtual syslogd is working at that point is if the daemon you are
  2512.   virtualizing independently logs something to syslogd.
  2513.  
  2514.  
  2515.   Q6.  How can I setup quotas across virtual filesystems?
  2516.  
  2517.  
  2518.   A6.  You setup quotas like you would normally.  See the Quota mini-
  2519.   HOWTO.  However, you have to make sure there are no uid conflicts
  2520.   across domains.  If there are conflicts you will have users sharing a
  2521.   quota.  Set aside a range of uid's that you know will have quota's
  2522.   enabled and tell your domains that they cannot have any users in that
  2523.   range except the ones registered to have a quota.
  2524.  
  2525.  
  2526.   Q7.  What is this \ notation in all the inetd.conf entries?
  2527.  
  2528.  
  2529.   A7.  That is just a method of breaking up config files across two
  2530.   lines.  I did that so the line would word wrap in a nice place.  You
  2531.   can just ignore the \ and join the two lines back together.
  2532.  
  2533.  
  2534.   Q8.  When I run passwd or other login programs I get  permission
  2535.   denied .  When I run FTP or su I get  no modules loaded for service
  2536.   XXX .  Why?
  2537.  
  2538.  
  2539.   A8.  Those are PAM error messages.  I wrote these scripts before PAM
  2540.   was out.  My virtfs script does not copy /etc/pam.d,
  2541.   /usr/lib/cracklib_dict.*, /lib/security or any of the other files PAM
  2542.   requires.  PAM needs these to function.  If you edit my virtfs script
  2543.   to copy these files the problem will go away.
  2544.  
  2545.  
  2546.   Q9.  Can virtuald work with tcpd hosts.allow and hosts.deny files?
  2547.  
  2548.  
  2549.   A9.  Yes it can with some modifications.
  2550.  
  2551.  
  2552.   First the source has to be changed in two places.
  2553.  
  2554.  
  2555.   This has to be inserted where the arguments are checked.
  2556.  
  2557.  
  2558.           if (!argv[3])
  2559.           {
  2560.                   syslog(LOG_ERR,"invalid arguments: no program to run");
  2561.                   exit(0);
  2562.           }
  2563.  
  2564.  
  2565.  
  2566.   The exec line has to be changed from:
  2567.  
  2568.  
  2569.           if (execvp(argv[2],argv+2)<0)
  2570.  
  2571.  
  2572.  
  2573.   to:
  2574.  
  2575.           if (execvp(argv[2],argv+3)<0)
  2576.  
  2577.  
  2578.  
  2579.   Second the inetd.conf lines have to be changed from:
  2580.  
  2581.  
  2582.   ftp stream tcp nowait root /usr/local/bin/virtuald \
  2583.           virtuald /virtual/conf.ftp wu.ftpd -l -a
  2584.  
  2585.  
  2586.  
  2587.   to:
  2588.  
  2589.  
  2590.   ftp stream tcp nowait root /usr/local/bin/virtuald \
  2591.           virtuald /virtual/conf.ftp tcpd wu.ftpd -l -a
  2592.  
  2593.  
  2594.  
  2595.   Third edit the /virtual/domain1.com/etc/hosts.allow and
  2596.   /virtual/domain1.com/etc/hosts.deny files accordingly.
  2597.  
  2598.  
  2599.   Q10.  Can my virtual hosts run CGI's?
  2600.  
  2601.  
  2602.   A10.  Yes they can but I recommend putting the /cgi-bin in a place
  2603.   outside of the  chroot  that only you have access to.  For example,
  2604.   /var/www/cgi-bin/domain1.com.  Giving clients access to /cgi-bin is
  2605.   giving them the opportunity to run programs on your sever.  This is a
  2606.   big security hole.  Be careful.  I do not let any cgi run on my
  2607.   systems that I have not personally inspected for bugs.
  2608.  
  2609.  
  2610.   Q11.  My configuration files are different from your examples.   What
  2611.   do I do?
  2612.  
  2613.  
  2614.   A11.  There are two basic configuration styles: SystemV and BSD.  The
  2615.   examples provided in the HOWTO are based on SystemV style
  2616.   configuration files.  Virtual services works equally well on either
  2617.   system.  For information on BSD style configuration files consult the
  2618.   origin of your distribution or the nearest LDP site.
  2619.  
  2620.  
  2621.   Q12.  I sent you mail and have not heard a response from you or your
  2622.   response took a long time.  Why?
  2623.  
  2624.  
  2625.   A12.  Probably because you did not put VIRTSERVICES HOWTO in your
  2626.   subject header.  Please bear in mind that I am a network administrator
  2627.   and that among the other things I do in my 20 hour days is
  2628.   administering my own virtual boxes and those of my clients.  Mail that
  2629.   is properly addressed is always responded to within two or three days.
  2630.   Mail that is improperly addressed does not get filtered into my
  2631.   VIRTSERVICES mailbox and can lie around unnoticed for days or weeks.
  2632.  
  2633.  
  2634.   Q13.  Does virtuald work under 100Mbit?
  2635.  
  2636.  
  2637.   A13   The speed of the network card is unrelated to whether virtuald
  2638.   will work or not.  Try making sure that your server works under 10Mbit
  2639.   and that your 100Mbit network card works normally without a virtual
  2640.   server.
  2641.   Q14.  Should I use sendmail's virthost table?
  2642.  
  2643.  
  2644.   A14.  No.  That is sendmail's feature to accept info for multiple
  2645.   domains.  Virtuald gives each sendmail its own separate  chroot
  2646.   environment.  Install virtuald and then configure sendmail like you
  2647.   would normally for each domain.
  2648.  
  2649.  
  2650.   Q15.  Can I setup virtual telnet on my machine?  What about creating a
  2651.   virtual root account so clients can administer their own domains?
  2652.  
  2653.  
  2654.   A15.  These questions come to me quite often and to be honest, I am
  2655.   getting a bit tired of them.  The answer, as stated numerous times in
  2656.   the documentation, is that any service run through inetd can be
  2657.   virtualized using virtuald so there is nothing to stop you from doing
  2658.   either of the above.  Nothing except common sense.  Whatever benefits
  2659.   you might derive from allowing telnet are heavily outweighed by the
  2660.   cost to the virtual box (and thus the sites you are supposed to be
  2661.   hosting in a responsible manner) in terms of security.  Here are just
  2662.   a few issues involved:
  2663.  
  2664.  
  2665.   ╖  In order to completely fool an incoming telnet session you have to
  2666.      hack the kernel to get multiple procs working, reset your source IP
  2667.      address for outgoing connections, fool gethostname so it uses the
  2668.      virtual hostname and not the system hostname, etc.  If you are an
  2669.      advanced user then by all means hack the kernel.  For the newbie I
  2670.      do not recommend it.
  2671.  
  2672.   ╖  By allowing users to come into your box via telnet you allow them
  2673.      to run arbitrary programs.  Through known hacks you can get root
  2674.      and cause damage to the system.
  2675.  
  2676.   ╖  Giving a root telnet account on a virtual box is very bad.  A root
  2677.      virtual user can still read raw device files which nullifies the
  2678.      chroot , shutdown the system, and can kill other processes on the
  2679.      system.
  2680.  
  2681.   ╖  The programs that these telnet sessions are running take up
  2682.      valuable CPU time that the network services could be using.
  2683.  
  2684.   ╖  Telnet is an insecure network service.  Plain text passwords are
  2685.      sent out over the net.  If a malicious user gets this password
  2686.      he/she can use the above mentioned attacks to harm your system.
  2687.  
  2688.   ╖  Your virtual environments will have to be bigger.  You will need
  2689.      more shared libraries, more configuration files, and more binaries.
  2690.      A six gigabyte disk can run out of space really fast.
  2691.  
  2692.  
  2693.   The bottom line is that allowing login's on a virtual box is a really
  2694.   bad idea.  If permitted, every site hosted on that machine is at risk.
  2695.   If you want to allow a site holder to administer users then you are
  2696.   advised to write (not script) the code necessary to run the virtual
  2697.   processes that allow them to add, delete or modify users upon login
  2698.   through ssh.  This should be completely menu driven, should never
  2699.   allow a console and should not run as root.  In order to accomplish
  2700.   this you will have to change ownership of the pertinent files from
  2701.   root to some other user.  If done in this manner it is marginally safe
  2702.   to incorporate into a virtual machine.  There is never an acceptable
  2703.   time to allow root login's either through telnet or ssh.  Doing so is
  2704.   simply an invitation to disaster.  If there is an overwhelming reason
  2705.   to run telnet then the site should be hosted on a dedicated machine
  2706.   where the only risk is to the individual site.  No responsible
  2707.   administrator would ever do otherwise and so I will waste no more time
  2708.   on this issue.
  2709.  
  2710.  
  2711.   Q16.  Is there an rpm, tar, web site, mailing list, etc. associated
  2712.   with virtuald and the Virtual-Services HOWTO?
  2713.  
  2714.  
  2715.   A16.  Currently there is nothing like that available.  This HOWTO is
  2716.   the only source of information to everything I do concerning this
  2717.   project.  I find the HOWTO to be fairly self contained making the need
  2718.   for other pieces of information superfluous.
  2719.  
  2720.  
  2721.   Q17.  When I try to run virtexec as a regular user I get  chroot:
  2722.   operation not permitted .  Why?
  2723.  
  2724.  
  2725.   A17.   Chroot  is a root restricted system call.  Only the superuser
  2726.   can execute it.  The virtexec script runs the  chroot  program which
  2727.   is why you need to be root in order to run it.
  2728.  
  2729.  
  2730.   Q18.  I setup pop and sendmail but popping mail does not seem to work.
  2731.   How come?
  2732.  
  2733.  
  2734.   A18.  Some pop programs come with /usr/spool/mail as their place for
  2735.   mail files.  I know that qpop has to be manually editted to fix this.
  2736.   Either recompile the source to your program or symlink
  2737.   /virtual/domain1.com/usr/spool to /virtual/domain1.com/var/spool.
  2738.  
  2739.  
  2740.   Q19.  I did not use the program mentioned in your HOWTO, I used
  2741.   program XXX.  It does not work.  Why?
  2742.  
  2743.  
  2744.   A19.  I tried to make sure to use the most generic of each server in
  2745.   my examples.  However, I know that everyone has their favorite version
  2746.   of each server.   Send me as much information as possible and I will
  2747.   try to figure out how to solve your problem and document it in the
  2748.   FAQ.  The most important piece of information to send me is where to
  2749.   get the version of the software you are running (in the form
  2750.   ftp://ftp.domain1.com/subdir/subdir/file.tgz).
  2751.  
  2752.  
  2753.   Q20.  When I run virtexec is says  symlink not a virt function .  What
  2754.   does this mean and how do I fix it?
  2755.  
  2756.  
  2757.   A20.  Virtexec is a program that will take its zero argument, strip
  2758.   off the first four characters, and run the remaining name in the
  2759.   virtual environment.  For example, virtpasswd runs passwd.  If the
  2760.   first four characters that it strips off are not  virt  it complains
  2761.   and outputs that error message.  Virtexec is written in shell script
  2762.   and should be fairly simple to follow.  Refer to the manual pages on
  2763.   bash or whatever shell you run for questions about shell script
  2764.   programming.
  2765.  
  2766.  
  2767.   Q21.  I have a question about Qmail, SAMBA, Apache, etc. that is
  2768.   unrelated to the virtuald setup or how the package interfaces to
  2769.   virtuald.
  2770.  
  2771.  
  2772.  
  2773.   A21.  All the packages described here are fully documented.  Some even
  2774.   have full web sites like www.packagename.org dedicated to them.
  2775.   Please consult them about questions dealing with the package that are
  2776.   unrelated to their virtual hosting functionality.
  2777.  
  2778.  
  2779.   Q22.  I have several domain aliases to domain1.com but mail keeps
  2780.   bouncing from the aliases.   How come?
  2781.  
  2782.  
  2783.   A22.  Virtmaildelivery relies on the environment variables passed to
  2784.   it to determine which /virtual/domain1.com directory to deliver to.
  2785.   It does not perform any DNS lookups to determine the address of the
  2786.   mail.  However, if the address is submail.mail.domain1.com,
  2787.   virtmaildelivery will first try that address and then mail.domain1.com
  2788.   and then domain1.com and then com in that order until either a match
  2789.   happens or there is no domain name left.
  2790.  
  2791.  
  2792.   However, if you have domain aliases that are not subdomains of one
  2793.   another you have to create symlinks like so:
  2794.  
  2795.  
  2796.   cd /virtual
  2797.   ln -s domain1.com domain1alias.com
  2798.  
  2799.  
  2800.  
  2801.   That way virtmaildelivery will be fooled into thinking that both
  2802.   directories exist even though one is a symlink and mail will be able
  2803.   to be delivered to user@domain1.com or user@domain1alias.com.  Note
  2804.   that virtexec will list both of the domains in the dialog box when
  2805.   your run it.  You can choose either one since they will be the same
  2806.   virtual filesystem.
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.  
  2838.  
  2839.