The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

High Volume (3-4M) Mail Server

Discussion in 'E-mail Discussions' started by nwilkens, Jan 14, 2007.

  1. nwilkens

    nwilkens Well-Known Member

    Joined:
    May 4, 2006
    Messages:
    59
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Monroe MI
    cPanel Access Level:
    DataCenter Provider
    I am working on a decent volume mail server, rejecting about 3-4 million spammers a day. I would like to share what I have done so far, and would like to know what others have done to cope with this type of scenario.

    The key to this is to reject unknown users, before doing DNSlist checks and a few other mods that I found useful.

    Exim.conf settings:
    Code:
    log_selector = -retry_defer -skip_delivery -host_lookup_failed -lost_incoming_connection -dnslist_defer -rejected_header
    
    write_rejectlog         = false
    deliver_queue_load_max  = 20.00
    queue_only_load         = 10.00
    queue_run_max           = 20
    smtp_accept_max         = 3000
    smtp_accept_reserve     = 100
    smtp_load_reserve       = 20.00
    smtp_reserve_hosts      = +reserve_hosts : +relay_hosts : <ip.addr.> : <ip.addr>
    # ident lookups are not useful and cause firewall problems.
    rfc1413_hosts           = :
    rfc1413_query_timeout   = 0s
    smtp_accept_max_per_host = \
         ${lookup{$sender_host_address}lsearch{/etc/exim_smtp_accept_max_per_host}\
         {$value}\
         {\
    ${lookup{${mask:$sender_host_address/24}}lsearch*{/etc/exim_smtp_accept_max_per_host}}\
         }}
    
    /etc/exim_smtp_accept_max_per_host has the following format:
    ip.a.d.dr: 25
    ip.a.dd.r: 10
    net.wo.r.k/24: 10
    *: 3

    Code:
        deny domains = +local_domains
            !recipients = /etc/exim_recipients
            log_message = The recipient cannot be verified.
            message = "The recipient cannot be verified. Please check all recipients of this \ 
                              message to verify they are valid."
    
    
        deny message = Message rejected - $sender_fullhost is in an RBL, see $dnslist_text
              !hosts = +relay_hosts : <ip.addr> : <ip.addr>
              !authenticated = *
              dnslists = list.dsbl.org : \
                            multihop.dsbl.org : \
                            rbl-plus.mail-abuse.ja.net : \
                            combined.njabl.org : \
                            relays.ordb.org : \
                            dnsbl.sorbs.net : \
                            sbl-xbl.spamhaus.org
              !domains = +rbl_bypass
              !hosts = +rbl_whitelist
    
    I am creating /etc/exim_recipients on an hourly basis using:
    Code:
    use vars qw/ %opt /;
    
    #
    # Command line options processing
    #
    sub init()
    {
        use Getopt::Std;
        my $opt_string = 'hvrad';
        getopts( "$opt_string", \%opt ) or usage();
        usage() if $opt{h};
    
        my %userdomains;
        my $file = open(\*IN,"<","/etc/userdomains");
        my @unix_users = <IN>;
        close(\*IN,$file);
        chomp @unix_users;
        foreach my $line (@unix_users) {
            my ($domain,$user) = split(/\: /,$line,2);
            $userdomains{$domain} = $user;
    
            # get local /home/$user/$domain/passwd entries and print as user@domain
            my $homedir = "/home/$user";
            print "Domain: $domain\n" if $opt{v};
            if ($domain ne "*") { print "$domain\n" if $opt{d} }
    
            if ($opt{r}) {
                    my @accounts;
                    my $file = open(\*IN,"<","$homedir/etc/$domain/passwd");
                    my @unix_users = <IN>;
                    close(\*IN,$file);
                    chomp @unix_users;
                    foreach my $line (@unix_users) {
                            ($username,undef) = split(/\:/,$line,2);
                            if ($username) { print "$username\@$domain\n"}
                    }
            }
    
            # get user aliases per domain and print
            if ($opt{a}) {
                    my $file = open(\*IN,"<","/etc/valiases/$domain");
                    my @email_addresses = <IN>;
                    close(\*IN,$file);
                    chomp @email_addresses;
    
                    foreach my $addresses (@email_addresses) {
                            my ($alias,$recipient) = split(/: /,$addresses,2);
                            if ($alias ne "*") { print "$alias\n" }
                    }
            }
        }
    
    }
    
    #
    # Message about this program and how to use it
    #
    sub usage()
    {
        print STDERR << "EOF";
    
    Show cPanel email information.
    Can be used to show current domains, email adresses, and defined aliases.
    
    usage: $0 [-hvrad]
    
     -h        : this (help) message
     -v        : verbose output
     -r        : show real (not aliases) email addresses associated with a domain.
     -a        : show alias email addresses for all domains
     -d        : like, cat /etc/localdomains, show domain names
    
    example: $0 -v -r -a
    
    EOF
        exit;
    }
    
    init();
    
    I run this using ./script.pl -ra|sort|uniq > /etc/exim_recipients

    The reason I do this instead of something like:
    !verify = recipient

    Is it does not scale for the huge number of connections. The load on the machine skyrockets [20+]. Where when I create the list myself and search this list, my load is now happily less than 1 (usually .4-.6) on a 2x2.8GHz 4GB machine.

    This is working, but I would be happy to hear what you have done, or what else I should / change / consider or any problems you see with this setup.

    BTW this is running on exim version 4.63.
     
  2. inspedium

    inspedium Member

    Joined:
    Jul 15, 2003
    Messages:
    10
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    Pakistan
    Thank you!

    Thank you for the tweaks, they're working like a charm! :)
     
  3. rvskin

    rvskin Well-Known Member
    PartnerNOC

    Joined:
    Feb 19, 2003
    Messages:
    400
    Likes Received:
    1
    Trophy Points:
    18
    Interesting solution. I would like to comment a few enhancements in your script.
    1. my $homedir = "/home/$user"; It should not fix at /home. It should get the homedir from /etc/passwd.
    2. You also need to get the information in /etc/vdomainaliases/*.
    3. if ($alias ne "*") { print "$alias\n" } <-- this line means you will not support catchall. It is a good practice to not support it. But in some case, it is required. For general purpose, you should change it to ($alias ne "*" && $recipient !~/^:)fail:|\/dev\/null)/).
     
Loading...

Share This Page