AntiAbuse headers in Sendmail

I sometimes look at the headers of incoming email to try and decipher where it came from, especially if it looks like a phishing attack or some spam. I’ve noticed that some have X-AntiAbuse headers along the lines of:

X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname -
X-AntiAbuse: Original Domain -
X-AntiAbuse: Originator/Caller UID/GID - [42 12] / [42 12]
X-AntiAbuse: Sender Address Domain -

It turns out that these headers are added by Exim, one of the common MTAs. So how do we reproduce them in Sendmail?

Unfortunately, it appears that you cannot have multiple headers of the same name in Sendmail – it simply overwrites them and you just end up with the last one, so I ended up adding the following to my file before compiling it (m4 /etc/mail/ > /etc/
HX-AntiAbuse: These headers were added to track abuse, please include with any abuse report
HX-AntiAbuse-Sender-Domain: ${client_name} ${client_resolve}
HX-AntiAbuse-Sender-Host: $s (Derived from EHLO/HELO)
HX-AntiAbuse-Sender-IP: ${client_addr}
HX-AntiAbuse-Envelope-From: $g. From MAIL FROM Address ${mail_addr} Host ${mail_host} Mailer ${mail_mailer}
HX-AntiAbuse-Envelope-To: ${nrcpts} valid recipients including <$u>, ${nbadrcpts} invalid.
HX-AntiAbuse-RCPT-info: Address ${rcpt_addr} Host ${rcpt_host} Mailer ${rcpt_mailer}
HX-AntiAbuse-Receiving-Host: $j
HX-AntiAbuse-QueueID: $i

A full list of the predefined macros can be found in the Sendmail documentation for the configuration file. The X-AntiAbuse-RCPT-info may not produce results unless the rcpt_check ruleset is used, so can be left out.

Testing SMTP

Sometimes you need to test SMTP Authentication is working on your server, and you want to see what is going on in order to diagnose the problem.

In this case, you can verify SMTP authentication is working by using telnet and accessing the SMTP server directly. Below is a quick tutorial on how to test your server’s SMTP authentication

  1. Create or verify an existing username and password on the system
  2. Build the Base64 username/password
    SMTP AUTH LOGIN will encapsulate the username and password as a Base64 string. This is used to prevent sending the username/password plaintext via the network connection. Using Perl, you can issue the following command to encode the username and password as a base64 string, which can be sent to the SMTP server. Note the @ symbol is escaped to pass the string via Perl.
    # perl -MMIME::Base64 -e 'print encode_base64("myusername\")'


    # perl -MMIME::Base64 -e 'print encode_base64("mypassword")'

  3. Access the local system. Commands we issue are highlighted in bold.
    # telnet localhost 25
    Connected to localhost (
    Escape character is ‘^]’.
    220 Welcome to the @Mail SMTP Server ( Exim )
    ehlo localhost []
    250-SIZE 52428800
    250-AUTH LOGIN
    250 HELP

    The above command will verfiy AUTH LOGIN is enabled on the server (250-AUTH LOGIN). If you do not see that then SMTP AUTH will fail the test which follows.
    Send the following command to start the SMTP Authentication process

    334 VXNlcm5hbWU6 ( Server returns username as a base64 string )


    334 UGFzc3dvcmQ6 ( Server returns password as a base64 string )


    235 Authentication succeeded
    Congratulations, SMTP authentication is now enabled and confirmed working on your server. Note you must send the Base64 string of the username and password as two commands.

Is my server hijacked?

I thought that my server had been compromised.

When working in China recently, I had run a proxy server on my server so that I could access gmail, twitter and facebook. Once I returned, I removed the program, but my site was extremely slow to load and looking at the Apache access_log, it appeared as though somehow the proxy was still operating. access_log was full of lines such as - - [19/Apr/2012:03:36:03 -0600] "GET!lzXvOUmfHwXQIX.entxiWYw5ObQ- HTTP/1.1" 301 346 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)"
and - - [19/Apr/2012:03:36:50 -0600] "CONNECT HTTP/1.1" 301 315 "-" "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0".

Luckily I found this useful script by David Ross on linuxquestions.orgwhich deciphers the access_log and error_log files. (It does not decipher all the response codes. You will have to look at Wikipedia or for full details of the codes)

# Start Config

$access_log = "/var/log/httpd/access_log";
$error_log = "/var/log/httpd/error_log";
$default_log = "error"; # access or error
$default_lines = "15";

# End Config

# Print the top of the page
print <<"EOF";
Content-type: text/html

<TITLE>Viewing $in{'log'} log</TITLE>
<H1>Log viewing options</H1>
<FORM method="get">
<TR><TH>Log Type:</TH><TD>Error<INPUT type="radio" value="error" name="log">
  Access<INPUT type="radio" value="access" name="log"></TD></TR>
<TR><TH>Lines to show:</TH><TD><INPUT type="text" size="5" name="lines" value="$default_lines"></TD></TR>
<TR><TH>&nbsp</TH><TD><INPUT type="submit" value="Show Log"></TD></TR>

# Get values from the query string (not many so we'll not use post)
foreach $pair (split(/&/, $ENV{'QUERY_STRING'})){
$pair =~ tr/+/ /;
($name, $value) = split(/=/, $pair);
$name =~ s/%(..)/pack("C", hex($1))/eg;
$value =~ s/%(..)/pack("C", hex($1))/eg;
$in{$name} = $value;
# If specific options were not given then use the defaults
if(!$in{'log'} && ($in{'log'} ne "access" || $in{log} ne "error")){$in{'log'} = $default_log}
if(!$in{'lines'}){$in{'lines'} = $default_lines}

print "</BODY></HTML>";

sub showlog{
print "<H1>Viewing $in{'log'} log</H1><TABLE border=1 width=90%>";
if($in{'log'} eq "access"){
open(LOG, "$access_log");
@line = <LOG>;
$num = @line;
($start, $request, $response, $ref, $other, $browser, $end) = split (/\"/, $line[$num]);
($browser, $end) = split (/ \(/, $browser);
($client, $other) = split (/\s/, $line[$num]);
($start, $end) = split (/\- /, $line[$num]);
($user, $bad) = split (/ \-/, $end);
($start, $end) = split (/\[/, $line[$num]);
($time, $line[$num]) = split (/\]/, $end);
if($response =~ /^ 200/){$resp = "OK!"}
if($response =~ /^ 500/){$resp = "Server error"}
if($response =~ /^ 404/){$resp = "Page not found"}
if($response =~ /^ 403/){$resp = "Authorisation required"}
if($response =~ /^ 401/){$resp = "Forbidden"}
if($response =~ /^ 400/){$resp = "Bad request"}
if($tm ne $time){print "<TR><TD colspan=4><HR></TD></TR>"}
print "<TR><TD width=35%><B>At:</B> $time
<B>User:</B> $client $user
<B>Browser:</B> $browser</TD>";
print "<TD width=65%><B>From page:</B> $ref
<B>Request:</B> $request
<B>Response:</B> $resp ($response)</TD></TR>";
elsif($in{'log'} eq "error"){
open(LOG, "$error_log");
@line = <LOG>;
$num = @line;
if($line[$num] =~ /^\[.*:..:.*\]/){
$line[$num] =~ tr/\[/ /;
($time, $typ, $cli, $info) = split (/\]/, $line[$num]);
if($line[$num] =~ /\(2\)/){
$cli = "";
if($tm ne $time){print "<TR><TD colspan=4><HR></TD></TR>"}
print "<TR><TD width=100>$time</TD><TD>$typ</TD><TD width=50>$cli</TD><TD>$info</TD></TR>";
print "</TABLE>";

Simply save the code above as apache.cgi in the /var/www/html/cgi-bin/ folder and give it executable rights (chmod +x apache.cgi).

This revealed that my server was responding with code 301 to requests for and, meaning that the requested URI had permanently moved and the request should display my home page instead. This is by design, but obviously was not very healthy as I was getting a lot of these spurious requests and it places undue load on my server.

I therefore followed the instructions on Proxy Abuse to reconfigure the Apache server to deny requests for random hostnames rather than serving local content..
NameVirtualHost *:80
# Disable default host
#<VirtualHost *:80>
# Define new default host, which is denied to all
<VirtualHost *:80>
ServerName default.only
<Location />
Order allow,deny
Deny from all
# Explicitly define previous default
<VirtualHost *:80>
DocumentRoot /var/www/htdocs

My server now responds with a code 403 and does not pass the request through to PHP for processing, substantially reducing the load on my server.

Home Media 2012 – The year of Smart TV?

So what’s it to be? So many choices :) Should I get a new Smart TV, with integrated BBC iPlayer and Demand 5 (such as the Sony KDL-22EX320), or a media server with integrated Hauppauge WinTV card and a web browser? Maybe a Ubuntu PC with MythTV.

Here are my wants:

The requirement for 4oD means no Smart TV – they only seem to offer BBC iPlayer / Demand 5 / Skype, so I’ll have to have a computer with a tuner rather than a TV.
The requirement for iTunes limits me to a Windows / Mac solution (damn that DRM). I’d love to go Linux, but Apple won’t hear of that :(
According to Wikipedia, the only software PVRs which can cope with Digital TV are MythTV and Windows Media Centre.
Macs are so expensive; iMacs start at £999, while the Mac Mini server is £849. A proper server starts at £2041. That’s a lot of TVs. They may look good, but I want to hide my hardware away.

The more I look at it, the more I think I’ll go for some form of PC with SSD drives and TV Tuner card and maybe some form of NAS RAID to serve my music, photos and movies. Lifehacker raves about XBMC, but that’s a media player rather than a recorder.

Changing the number of rings before your mobile diverts to Voicemail

I keep missing phone calls on my mobile because it’s in my pocket and diverts to voicemail. This is so frustrating that I simply disabled voicemail – which annoys those who call me and want to leave a message. However, there is a way out. It is possible to change the delay before your phone will divert to voicemail. On my Nokia E72, you can set your ring time to 5, 10, 15, 20, 25 or 30 seconds.

  • Tap **61*121*11* into your phone as if you’re making a call.
  • Next enter a time between 5 and 30 (the number of seconds in multiples of 5)
  • Press # and then the call button. Don’t put the phone to your ear – just look at the display until you see a message confirming your ring time has been set.

For example, **61*121*11*25# followed by the call button would set your ring time to 25 seconds.

Vodafone warn that this will only work if your mobile phone’s on the Vodafone network and you have voicemail set up, but it may work on your network too.