Cover V13, i02

Article

feb2004.tar

Questions and Answers

Amy Rich

Q I'm using ipfilter on Solaris 8 to protect each of my internal hosts separately. I'm not using NAT on these machines at all. Unfortunately, occasionally some of the more heavily loaded machines will just stop receiving TCP connections altogether. I can clear this up by stopping and starting the filter again, but that kills any existing connections. The weird thing is that it only appears to be TCP and not UDP or ICMP. Any clue what the problem might be?

A Your question is sparse on details, and it would help if I knew the version of ipfilter and saw your ipf.conf. I can hazard an educated guess at what your problem may be, though. It sounds like you're overflowing ipfilter's TCP state database. When you notice a machine having problems, do the following:

ipfstat
ipfstat -s
If you see a large number of lost packet states when you run the first command, and you see a large number of bkts in use with the second command, you've found your culprit. If this isn't the case, then the output from ipfstat will at least give you some statistics to work with.

To correct the bucket overflow issue, take the following steps:

  • Make sure that every rule where you keep state on a TCP connection also has "flags S". Here's an example set of rules for DNS:

    pass out quick on hme0 proto tcp from 0/32 to any port = domain flags S keep state
    pass out quick on hme0 proto udp from 0/32 to any port = domain
    pass in quick on hme0 proto udp from any port = domain to 0/32
    
  • Adjust the ipf:fr_statemax and ipf:fr_statesize kernel variables in /etc/system and reboot:

    set ipf:fr_statemax = 7000
    set ipf:fr_statesize = 10009
    
  • Additionally, if you see a lot of half closed and idle connections, you may also want to adjust ipf:fr_tcpidletimeout and ipf:fr_tcphalfclosed in /etc/system and reboot:

    set ipf:fr_tcpidletimeout = 172800
    set ipf:fr_tcphalfclosed = 7200
    
    If these steps don't seem to correct the problem, search through the ipfilter mailing list archives at:

    http://marc.theaimsgroup.com/?l=ipfilter
    
    After checking through the archives, you can also post to the ipfilter list for help by following the directions at:

    http://www.ipfilter.org/~avalon/ip-filter.html
    
    Q In the past, I've been bitten by cvsup'ing to a release candidate of FreeBSD instead of getting -STABLE. How can I make sure that I get the newest -STABLE instead of the newest RELENG tag? This is what I currently have in my cvsup config file:

      *default host=cvsup3.FreeBSD.org
      *default base=/usr/local/etc/cvsup
      *default prefix=/usr
      *default release=cvs
      *default delete use-rel-suffix
      *default tag=RELENG_4
    
       # These are the individual collections that make up "src-all".
       # If you use these, be sure to comment out "src-all" above.
       src-base
       src-bin
       src-contrib
       src-etc
       src-gnu
       src-include
       src-lib
       src-libexec
       src-release
       src-sbin
       src-share
       src-sys
       src-tools
       src-usrbin
       src-usrsbin
       src-crypto
       src-secure
       src-sys-crypto
       
    A If you know that you want to stick with a certain branch, you can specify it, instead of RELENG_4, in your cvsup configuration file. The following would make sure that you get the 4.9-RELEASE (now in -STABLE) branch. This branch will only contain critical fixes:

    *default tag=RELENG_4_9
    
    If you specify RELENG_4_9, though, you'll never get the next 4.x release until you manually change your cvsup configuration file.

    If you want to leave your tag as RELENG_4, you can always make sure that you've got a -STABLE before you go through and compile everything. The file /usr/src/release/doc/share/sgml/release.ent contains information about the current, previous, and next releases as well as some other versioning information. In particular, you want to look for the release.current entry:

    <!-- Version of the OS we're describing. This needs to be updated \
      with each new release. -->
    <!ENTITY release.current "4.9-STABLE">
    
    Q I'm attempting to do some error checking in one of my Bourne shell scripts, but it's not working as I would expect. The simple case script is as follows:

    #!/bin/sh
    somecommand
    echo $?
    if [ $? = 2 ]; then
      echo "somecommand failed"
    fi
    
    where "somecommand" is a locally written C program that returns 0 on successful completion and 2 on failure. When I run this shell script and somecommand fails, it prints out the number 2, but it never prints out "somecommand failed." Clearly, my debugging shows that an error is being generated by somecommand, but the if statement doesn't appear to work. What is wrong with my code?

    A You have two issues with your code. First, the equal sign (=) is used to compare strings, not numbers. Instead, you should use -eq to compare your error number. Second, the test in your if statement refers to the output of the echo program, not somecommand. If you want to use the return code of somecommand in multiple places, you'll need to store the value in a variable. Try this code instead:

    #!/bin/sh
    somecommand
    returncode=$?
    echo ${returncode}
    if [ ${returncode} -eq 2 ]; then
      echo "somecommand failed with code ${returncode}"
    fi
    Q We recently purchased several Sun V240 systems that came preinstalled with Solaris 8. I tried to reinstall them with the Solaris CD 1 of 2. The installation failed on each machine when it couldn't find kernel/sparcv9/unix. I also tried a copy of Solaris 9, but that failed as well. Since they failed on all of the machines, I'm guessing I have defective or outdated (more likely) installation media. What do the V240s support?

    A If you want to install Solaris 8, you'll need the 12/02 release at a minimum. From the release notes at:

    http://docs.sun.com/db/doc/816-5263-11/6mbdu8brk?a=view
    
    The Solaris 8 HW 12/02 media is intended only for installation on Sun Fire B100s, Sun Fire V210, Sun Fire V240, and Netra 240 systems. It includes no new functionality other than support for these systems. Customers installing the Solaris 8 operating system on systems other than those listed above are advised to use the Solaris 8 2/02 update instead, and may choose to also add standard patches found on the SunSolve web site: http://sunsolve.sun.com/

    Patches included in this platform-specific release that are not in the Solaris 8 2/02 update are listed by number in Chapter 9, Released Patches Integrated into the Solaris 8 HW 12/02 Release of these release notes.

    If you'd rather upgrade the machine to Solaris 9, then you'll need release 04/03 at a minimum:

    http://docs.sun.com/source/817-1106-11/lbnews.html
    
    Q I'm running sendmail 8.12.10 on an OpenBSD for 3.4 machine. This machine acts as the outgoing SMTP host for IMAP clients run by people in each of those domains (no local delivery takes place here). Because each domain has a different set of filtering rules and policies for outgoing mail, I want to smarthost each piece of email based on the sender's domain, not the recipient's domain. I've found instructions on doing the latter, but not the former. Is this possible with the version of sendmail that I'm running?

    A There is an add-on m4 file by Andrzej Filip called smarttable.m4, which should do what you desire. Obtain the m4 file from:

    http://www.polbox.com/a/anfi/sendmail/smarttable.m4
    
    and add it to the cf/feature directory of your sendmail distribution. Create /etc/mail/smarttable and add entries for each of your domains:

    @first.domain      smarthost.first.domain
    @second.domain     smarthost.second.domain
    
    Create the corresponding map file with makemap:

    makemap hash < /etc/mail/smarttable > /etc/mail/smarttable.db
    
    Next, add the following line to your .mc file and rebuild sendmail.cf:

    FEATURE('smarttable')dnl
    
    See additional details at:

    http://www.polbox.com/a/anfi/sendmail/smarttab.html
    
    There's also a different method to do sender-based smarthosting by Neil Rickert, which requires a patch to cf/m4/proto.m4:

    http://www.cs.niu.edu/~rickert/cf/hack/sender_based_routing.m4
    
    This method uses the mailertable functionality of sendmail (make sure that FEATURE('mailertable')dnl is included in the mc file from which sendmail.cf was built) with a From: tag on the LHS. The mailertable format is:

    From:first.domain       esmtp:smarthost.first.domain
    From:second.domain      esmtp:smarthost.second.domain
    
    Q I'm using the new root-delegation-only keyword from BIND 9.2.3, but I notice that we seem to be blocking some valid traffic. I list some entries in the exclude argument, but I'm not certain which are valid and which are not. Is there a canonical list of domains that should be in the exclude list? Here's what I currently have:

    options {
      root-delegation-only exclude { "de"; "museum"; "tw"; "us"; }
    }
    
    A The ISC tries to keep the page:

    http://www.isc.org/products/BIND/delegation-only.html
    
    updated with all of the valid TLD zone exclusions. At the time of writing, the following TLDs are listed:

    options {
      root-delegation-only exclude { "ad"; "ar"; "biz"; "cr"; "cu";
      "de"; "dm"; "id"; "lu"; "lv"; "md"; "ms"; "museum"; "name"; "no";
      "pa"; "pf"; "sr"; "to"; "tw"; "us"; "uy"; }
    }
    
    If you know of any other zones with valid non-delegation records, contact the ISC so that they can be included on the above Web page.

    Q I'd like to restrict a user to his home directory, and I'm not seeing a way to do that in proftpd 1.2.9. Is there a configuration option that I missed, or will I have to use a different ftp daemon?

    A To cause every FTP user to be chrooted into his home directory, use the DefaultRoot directive:

    DefaultRoot ~
    
    If the DefaultRoot directory is a symlink, it will first be resolved to its parent directory before setting up the chroot. The DefaultRoot directive can also specify a subdirectory of a user's home directory, such as "~/ftp."

    The optional group regular expression argument can be used to restrict the DefaultRoot directive to a Unix group, groups, or subset of groups. This becomes especially useful if you want most users to be chrooted to their home directories but want to allow system staff to have the run of the machine. The expression is comma-separated list of the format [!]group-name1. The expression is parsed using a logical boolean AND for each expression. An example /etc/group contains the following lines:

    users::1000:u1,u2,u3,u4
    staff::10:u1,u6
    
    The following DefaultRoot statement chroots users u2, u3, and u4, but not u1 or u6 (logically: users AND NOT staff):

    DefaultRoot ~ users,!staff
    
    If you want every user except those in group "staff" to be chrooted, then you'd use:

    DefaultRoot ~ !staff
    
    Be aware that chrooting is not secure in and of itself as there are ways to circumvent it, especially if the user has shell access to the machine.

    Q I want to set up a system account that should never receive mail. To do this, I've tried using sendmail's accessdb feature, but I'm not seeing the exact behavior I want. I tried the following entry:

    util@  ERROR:"550 User does accept mail"
    
    This blocks mail like I want, but it also blocks mail from any user named "util" that's sending mail to my machine. Obviously, I don't want this behavior, because I'm blocking legitimate email to other accounts.

    Next, I tried the following entry in the accessdb:

    util@my.domain  ERROR:"550 User does accept mail"
    
    This blocks mail that uses the FQDN but doesn't stop anyone from sending unqualified email to the user util. Is there an easy answer to what I want to do, or am I going to have to implement something through a milter?

    A If your machine (you don't mention OS or sendmail version) delivers mail locally without calling sendmail, then you're not going to be able to block local delivery from things like cron. If all of your outbound and inbound email goes through sendmail, you can use the LHS tags for the access database to refine your filtering. From the cf/README file:

    There is now the option to tag entries in the access map according to their type. Three tags are available:

    Connect:    connection information (${client_addr}, ${client_name})
    From:       envelope sender
    To:         envelope recipient
    
    If the required item is looked up in a map, it will be tried first with the corresponding tag in front, then (as fallback to enable backward compatibility) without any tag, unless the specific feature requires a tag. For example,

    From:spammer@some.dom   REJECT
    To:friend.domain        RELAY
    Connect:friend.domain   OK
    Connect:from.domain     RELAY
    From:good@another.dom   OK
    From:another.dom        REJECT
    
    This would deny mails from spammer@some.dom but you could still send mail to that address even if FEATURE('blacklist_recipients') is enabled. Your system will allow relaying to friend.domain, but not from it (unless enabled by other means). Connections from that domain will be allowed even if they end up in one of the DNS-based rejection lists. Relaying is enabled from from.domain but not to it (since relaying is based on the connection information for outgoing relaying, the tag Connect: must be used; for incoming relaying, which is based on the recipient address, To: must be used). The last two entries allow mails from good@another.dom but reject mail from all other addresses with another.dom as domain part.

    So, you'd want the following to block mail to util on your machine:

    To: util@
    
    Amy Rich, president of the Boston-based Oceanwave Consulting, Inc. (http://www.oceanwave.com), has been a UNIX systems administrator for more than 10 years. She received a BSCS at Worcester Polytechnic Institute, and can be reached at: qna@oceanwave.com.
  •