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.

Helpful Exim ACLs -- Add Your Own

Discussion in 'General Discussion' started by mctDarren, Dec 21, 2006.

  1. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    With so much spam discussion on the board lately, I thought maybe we can put our heads together in one thread and come up with the most helpful Exim ACLs for everyone to share.

    I'll start off with a custom HELO ACL we use on our servers:

    HELO BASED EXIM ACL (CPANEL ADDITIONAL)

    This is a tutorial on how to add a HELO scanning ACL to your exim configuration in cPanel to help cut down on load and spam at the same time. Use this at your own risk! The potential to block legitimate traffic is of course a factor. Educate your users, clients and friends. Oh, and yourself! :)

    Background Information
    The "HELO" (or "EHLO") is part of the simple procedure machines use to send mail - SMTP, or Simple Mail Transfer Protocol. We won't delve into the details here, suffice it to say that mail servers should follow the SMTP procedure. Most mail servers (including cPanel's standard Exim configuration) are set up to be forgiving. Spammers sometimes don't follow the rules in order to take advantage of our attempt to accept every piece of mail that comes down the pipe. But we can set up our cPanel server to block what we know is not following the rules.

    The Procedure
    1. Log in to WHM as root and scroll down the left hand side until you find "Service Configuration". Click the "Exim Configuration Editor" link.

    2. Click the "Advanced Editor" button at the right side bottom.

    3. In the first input box you might see some options already there. Scroll below them and add the following two lines, replacing the IPs in the local_ips hostlist with your own IPs for your server:
    Code:
    hostlist local_ips = 127.0.0.1: :192.168.1.1:192.168.1.2:192.168.1.3
    acl_smtp_helo = check_helo
    
    Be sure you add the extra "empty space" after 127.0.0.1 - it's not a typo!

    4. Now scroll all the way down until you find "begin acl" and three input boxes in a row. In the second box you will most likely see the "check_recipient" ACL. I don't know why everyone always uses the second box, but I usually use the first one to keep my addtions separated from cPanels. In the first box, add the following:
    Code:
    check_helo:
    
    # HELO is empty or not sent
    deny condition = ${if eq{$sender_helo_name}{}}
      message = You have sent no HELO! Please see RFC 2821 section 4.1.1.1
      log_message = Bad HELO: Empty HELO
    
    # HELO is not a fully qualified domain name
    deny condition = ${if match {$sender_helo_name} {\.} {no}{yes}}
      message = Your mail server announcement ($sender_helo_name) \
                         is a single word rather than a FQDN. This is \
                         in breach of RFC2821
      log_message = Bad HELO: Not FQDN
    
    # IP Only is sent as the HELO
    deny condition = ${if match {$sender_helo_name}\
                                {^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\$}\
                                {yes}{no}}
      message = Your server announces itself ($sender_helo_name) with a plain \
                         IP address which is in breach of RFC2821.
      log_message   = Bad HELO: IP Only Announce
    
    # Someone is trying to spoof your own IPs!
    deny condition = ${if eq {$sender_helo_name} {$interface_address} {yes}{no}}
      message = HELO/EHLO IP is local. You are not this server.
      log_message = Bad HELO: Local IP Spoof Attempt
    
    # Someone is trying to spoof a domain on the server
    deny condition = ${if match_domain{$sender_helo_name}\
                              {+local_domains}}
      message = Forged HELO: you are not $sender_helo_name
      log_message   = Forged HELO: $sender_helo_name Spoof Attempt
    
    accept
    
    5. I've added a comment before each distinct rule so you can have some idea of what these do if you've never used them before. In a nut shell, these are going to drop any connection to the mail server if:
    (a) There is no HELO set or it's empty. A HELO statement must by definition be followed by a fully qualified domain name (FQDN). Some spammers try to get around this by sending an empty HELO.
    (b) The HELO is not a FQDN. Same as above - a FQDN should be a domain name that can be used to find an IP. (IE: timmysbox is not a FQDN, but mail.timmysbox.net is!)
    (c) An IP is sent instead of a FQDN. Spammers will sometimes even try to put your IP as the sending server, hoping it will trick the MTA into thinking the connection is local I suppose. We zap it here.
    (d) A domain that resides on your server is sent as the HELO. How could your server be sending itself an email? Zap that connection!

    6. Now scroll to the page bottom and SAVE. This will save your new configuration within cPanel so that it will not be overwritten when upgrading to a new version. It restarts Exim as well for you so you can test the results right away. And if your spam problem is like most people, you'll see the results pretty quickly. Do
    Code:
    tail -f /var/log/exim_mainlog
    and watch the scrolling log for any forged or bad HELO messages from our ACL. After a little while, try this one:
    Code:
    grep "HELO" /var/log/exim_mainlog | more
    
    and scroll through all the spammer connections your machine has dropped BEFORE processing. This procedure is especially helpful to those running high memory eaters like SpamAssassin and/or MailScanner, since the message is dropped rather than run through the queue and scanned.

    Hope this helps people out there. Comments, suggestions, additions welcomed!
     
    #1 mctDarren, Dec 21, 2006
    Last edited: Dec 25, 2006
  2. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    Got a couple question on this setup, as it looks very helpful, but what to make sure I've got the setup correct.

    Code:
    3. In the first input box you might see some options already there. 
    Scroll below them and add the following two lines, replacing the IPs in the 
    local_ips hostlist with your own IPs for your server:
    
    now the IP's for the server, your referring to the main IP assigned to the server(DNS) IP for ns.hostname and ns2.hostname IP's ??

    Code:
    4. Now scroll all the way down until you find "begin acl" and three input boxes in a row. 
    In the second box you will most likely see the "check_recipient" ACL. I don't know why 
    everyone always uses the second box, but I usually use the first one to keep 
    my addtions separated from cPanels. In the first box, add the following:
    
    now this is added right AFTER the "begin acl" and BEFORE the "check_recipient:"

    TIA,
    Mickalo
     
  3. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Actually, any IPs associated with the server. Not just those used for Bind (NS). You, you're resellers and hosting clients. Any IP assigned to that box. Sometimes you can find them in a file like /etc/ips but I was trying to make it easy to see what was happening. :)

    You got it, although I don't think it matters what order they're in. My understanding is you could still have our new ACL after the other two that were there and it wouldn't matter. :)
     
  4. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    Ok, got it now .... ;)

    we'll give a try and see how well it works.

    UPDATE:
    Seems to work very well .... but it sure fills up the exim log files FAST!!! :)


    Thx's much!
    Mickalo
     
    #4 mickalo, Dec 21, 2006
    Last edited: Dec 21, 2006
  5. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    is it possible for this to be setup to read/search from a file instead of manually listing IP's here, as IP's are added/removed during the course of time. It would make it easier to maintain. Other then that, this seems to work quiet well. Nice little tweak.

    Thx's
    Mickalo
     
  6. chirpy

    chirpy Well-Known Member

    Joined:
    Jun 15, 2002
    Messages:
    13,475
    Likes Received:
    20
    Trophy Points:
    38
    Location:
    Go on, have a guess
  7. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Testing this now, not sure if it will work as expected or not - I know Exim grabs the ip literals for the server's domains before delivering emails (part of the RFC that most people ignore):

    Code:
    # Someone is trying to spoof your own IPs!
    deny condition = ${if eq {$sender_helo_name} {$interface_address} {yes}{no}}
      message = HELO/EHLO IP is local. You are not this server.
      log_message = Bad HELO: Local IP Spoof Attempt
    
    This change does work well, so I have edited my original post. Spammers spoofing local IP addresses were caught regularly in our test of this addition.
     
    #7 mctDarren, Dec 23, 2006
    Last edited: Dec 25, 2006
  8. isputra

    isputra Well-Known Member

    Joined:
    May 3, 2003
    Messages:
    576
    Likes Received:
    0
    Trophy Points:
    16
    Location:
    Mbelitar
    Hi,

    Is there any rules that can block script from my server sending mass email out using fake email address ?

    I have client that installed script like mailbomb that can send email and using fake email as From, not his own email address :

    ----------
    1GxvF5-0002La-Ln-H
    gembong 32244 500
    <myclient@myserver.net>
    1166835603 0
    -ident myclient
    -received_protocol local
    -body_linecount 29
    -auth_id myclient
    -auth_sender myclient@myserver.net
    -allow_unqualified_recipient
    -allow_unqualified_sender
    -deliver_firsttime
    -local
    XX
    1
    BiroIklan@yahoogroups.com

    157P Received: from myclient by myserver.net with local (Exim 4.52)
    id 1GxvF5-0002La-Ln
    for BiroIklan@yahoogroups.com; Sat, 23 Dec 2006 08:00:04 +0700
    030T To: BiroIklan@yahoogroups.com
    031 Subject: NOT A DREAM ANYMORE
    034F From: national_teamwork@yahoo.com
    ---------------------

    This account already suspended so he can't send this mailbomb again

    Thanks
     
  9. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    I have edited my original posts above, testing of the change to the HELO IP Spoof portion were sucessful.

    @ Chirpy: Nice! Close to what I have (which I got from here - should have given credit!). The one they had which I did not I just tried:
    Code:
    deny message = Invalid HELO. You must be spam or a virus, or your system \
       administrator is an idiot.
       condition = ${if match{$sender_helo_name}{\\.}{no}{yes}}
    
    However, I found that one client actually hit this message when sending from their office PCs, which were called things like JACKSPC, OFFICE1 and such. Their sys admin was not amused by the message. :)
     
  10. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    what did you change in your original coding ??

    Mickalo
     
  11. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Local IP Spoof scan was changed to match the code in post #7:
    Code:
    # Someone is trying to spoof your own IPs!
    deny condition = ${if eq {$sender_helo_name} {$interface_address} {yes}{no}}
      message = HELO/EHLO IP is local. You are not this server.
      log_message = Bad HELO: Local IP Spoof Attempt
    
    Where we used to use the hostlist called "local_ips", we now use "$interface_address" in the code above. Works just fine! :) No need to manually add local IPs to that IP list now. :)
     
    #11 mctDarren, Dec 25, 2006
    Last edited: Dec 25, 2006
  12. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    Hmm... I think you lost me here. where is this "$interface_address" coming from ?? Would it be possible to post the new code completely ??

    is this the only part of the code that was changed ??

    shouldn't that be deny condition instead of just condition ??


    Mickalo
     
    #12 mickalo, Dec 25, 2006
    Last edited: Dec 25, 2006
  13. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Yes. That's what I get for trying to post quick before the Christmas festivities. :)

    That "deny" should definitely be in there. And the $interface_address is an Exim assigned variable the contains a list of all the local IPs, which it collects prior to receipt from your server. I wasn't sure how it would match in that reference, but it seems to be working well on the box I am testing it on. It blocked attempts to spoof the IP of a couple of the IPs assigned to that machine. Success! And without the need for that hostlist we created called "local_ips", so you can remove that too. Here's the revised configurations:

    Very first input box when you click Advanced Editor in WHM's Exim Config Editor:
    Code:
    acl_smtp_helo = check_helo
    
    Then scroll all the way down until you find "begin acl" and three input boxes in a row and in the first box, add the following:
    Code:
    check_helo:
    
    # HELO is empty or not sent
    deny condition = ${if eq{$sender_helo_name}{}}
      message = You have sent no HELO! Please see RFC 2821 section 4.1.1.1
      log_message = Bad HELO: Empty HELO
    
    # HELO is not a fully qualified domain name
    deny condition = ${if match {$sender_helo_name} {\.} {no}{yes}}
      message = Your mail server announcement ($sender_helo_name) \
                         is a single word rather than a FQDN. This is \
                         in breach of RFC2821
      log_message = Bad HELO: Not FQDN
    
    # IP Only is sent as the HELO
    deny condition = ${if match {$sender_helo_name}\
                                {^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\$}\
                                {yes}{no}}
      message = Your server announces itself ($sender_helo_name) with a plain \
                         IP address which is in breach of RFC2821.
      log_message   = Bad HELO: IP Only Announce
    
    # Someone is trying to spoof your own IPs!
    deny condition = ${if eq {$sender_helo_name} {$interface_address} {yes}{no}}
      message = HELO/EHLO IP is local. You are not this server.
      log_message = Bad HELO: Local IP Spoof Attempt
    
    # Someone is trying to spoof a domain on the server
    deny condition = ${if match_domain{$sender_helo_name}\
                              {+local_domains}}
      message = Forged HELO: you are not $sender_helo_name
      log_message   = Forged HELO: $sender_helo_name Spoof Attempt
    
    accept
    
    Scroll to the page bottom and SAVE. Test the results after some time by doing:
    Code:
    grep "Local IP Spoof" /var/log/exim_mainlog
    
     
  14. mickalo

    mickalo Well-Known Member

    Joined:
    Apr 16, 2002
    Messages:
    765
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    N.W. Iowa
    yes, I finally figured it out earlier after looking at it again. made the new changes and it seems to work quiet nicely now.

    thx's
    Mickalo
     
  15. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Just a quick note on the ACL I posted above: investigating an incident on one of our servers turns up that the domain match HELO check breaks Mailman. Mailman sends out as localhost (127.0.0.1) and uses the server hostname as the HELO, which our ACL catches and denies.

    So we have to set up the ACL to accept messages coming from localhost. So before the other checks in the ACL we need to accept locally hosted mail for things like Mailman. We could just do:
    Code:
    accept hosts = 127.0.0.1
    
    But I think that would accept mail from anyone using 127.0.0.1 in their HELO - which we want to avoid since this is one way spammers push their mail through.

    So I am (now - after changing it) testing this, which is similar to the exim standard check for mailman traffic:
    Code:
    # Accept mailman deliveries
      accept   condition    = \
               ${if and {{match{$sender_helo_name}{(.*)-bounces\+.*}} \
                         {exists {/usr/local/cpanel/3rdparty/mailman/lists/${lc:$1}/config.pck}}} \
                    {yes}{no}}
               endpass
               log_message = $sender_helo_name resides in mailman-passed
    
    The code is pasted above all else in the "check_helo:" ACL block. It goes right after "check_helo:" and right before "# HELO is empty or not sent". So the top of your ACL looks like this:
    Code:
    check_helo:
    
    # Accept mailman deliveries
      accept   condition    = \
               ${if and {{match{$sender_helo_name}{(.*)-bounces\+.*}} \
                         {exists {/usr/local/cpanel/3rdparty/mailman/lists/${lc:$1}/config.pck}}} \
                    {yes}{no}}
               endpass
               log_message = $sender_helo_name resides in mailman-passed
    
    # HELO is empty or not sent
    drop condition = ${if eq{$sender_helo_name}{}}
    
    Open to suggestions from anyone who knows better but I think this might be the fix I need... But if I'm wrong, or you know a better way, feel free to chime in! :)
     
    #15 mctDarren, Dec 31, 2006
    Last edited: Dec 31, 2006
  16. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Hmm, no that's not working either. Create a mailing list and the creation announce email to the admin gets blocked... Happy New Year to me - this stinks! :)

    Time to spend some quality ticks with the family and will think on this one...
     
  17. isputra

    isputra Well-Known Member

    Joined:
    May 3, 2003
    Messages:
    576
    Likes Received:
    0
    Trophy Points:
    16
    Location:
    Mbelitar
    I use this rule :

    # Someone is trying to spoof a domain on the server
    deny condition = ${if match_domain{$sender_helo_name}\
    {+local_domains}}
    message = Forged HELO: you are not $sender_helo_name
    log_message = Forged HELO: $sender_helo_name Spoof Attempt

    And i have my client sending email from office pc with "clientoffice-sb2003.ClientOffice.local" as hostname rejected by this rule.

    how to solve this problem ?
     
  18. mctDarren

    mctDarren Well-Known Member

    Joined:
    Jan 6, 2004
    Messages:
    664
    Likes Received:
    2
    Trophy Points:
    18
    Location:
    New Jersey
    cPanel Access Level:
    Root Administrator
    Does "clientoffice-sb2003.ClientOffice.local" match one of your local domains on the server? Is it a FQDN? If they have their domain name in their HELO, but it's not a FQDN then technically they are breaking RFC. But I know it can be tough to tell a customer they might be the cause. :)

    Perhaps if we place an accept for authenticated users above all the rules it would help to solve your problem?
    Code:
    check_helo:
    
    accept authenticated = *
    
     
  19. isputra

    isputra Well-Known Member

    Joined:
    May 3, 2003
    Messages:
    576
    Likes Received:
    0
    Trophy Points:
    16
    Location:
    Mbelitar
    Yes, it's hard to tell my client that they are breaking RFC.

    His domain for example using clientoffice.com and his office pc using clientoffice.local

    Now i add accept authenticated = * and waiting for the result.
     
  20. isputra

    isputra Well-Known Member

    Joined:
    May 3, 2003
    Messages:
    576
    Likes Received:
    0
    Trophy Points:
    16
    Location:
    Mbelitar
    using accept authenticated = * all my clients email can't received any email
     
Loading...

Share This Page