DSPAM case sensitivity

I use DSPAM to handle my spam checking and have been quite happy with it as it normally delivers >99.9% hit rate.

In the last few weeks the amount of spam in my INBOX had been getting progressively worse to the point where I noticed no spam whatsoever was making its way into my spam folder.

Looking through my logs I eventually found the following

May 10 10:03:03 fozzie dspam[30287]: Unable to find a valid signature. Aborting.
May 10 10:03:03 fozzie dspam[30287]: process_message returned error -5.  dropping message.

I process my spam by using a mutt macro which bounces emails to johnf-spam at inodes dot org. This then passes the email to DSPAM which reclassifies it. It does this by looking at a header it added to the email.

X-DSPAM-Signature: 464400d0223642194712985

However these were appearing in my INBOX as

X-Dspam-Signature: 464400d0223642194712985

I use procmail and a perl script to pre-process some of my email and it uses Mail::Internet which in turn uses Mail::Header. It bestows this piece of wisdom upon the world.

# attempt to change the case of a tag to that required by RFC822. That
# being all characters are lowercase except the first of each word. Also
# if the word is an `acronym' then all characters are uppercase. We decide
# a word is an acronym if it does not contain a vowel.

sub _tag_case

Now I can’t see where in RFC822 it specifies this but in section B.2 it does specify

Upper and lower case are not dis-tinguished when comparing field-names.

So on that basis I choose to blame DSPAM and applied the following diff

diff -ur dspam-3.8.0.orig/src/dspam.c dspam-3.8.0/src/dspam.c
--- dspam-3.8.0.orig/src/dspam.c        2006-12-13 02:33:45.000000000 +1100
+++ dspam-3.8.0/src/dspam.c     2007-05-11 16:25:11.000000000 +1000
@@ -2165,7 +2165,7 @@
           while(node_header != NULL) {
             head = (ds_header_t) node_header->ptr;
             if (head->heading && 
-                !strcmp(head->heading, "X-DSPAM-Signature")) {
+                !strcasecmp(head->heading, "X-DSPAM-Signature")) {
               if (!strncmp(head->data, SIGNATURE_BEGIN, 

Now to work out the best way to push that upstream.

Ubuntu, VLANs and Bridges

Bridge and VLAN support has improved dramatically under Ubuntu and probably Debian as well since I last looked into it. once upon a time to create a bridge linked to a VLAN interface you would have to do horrible things like.

auto eth0
ifconfig eth0 inet manual
    pre-up /sbin/vconfig set_name_type VLAN_PLUS_VID_NO_PAD || true

auto vlan7
iface vlan7 inet manual
    pre-up /sbin/vconfig add eth0 7 || true
    post-down /sbin/vconfig rem vlan7 || true

auto br0
    pre-up brctl addbr br0
    pre-up brctl addif br0 vlan7
    post-down brctl delbr br0

Now the bridge-utils and vlan packages provide hooks into the ifup and ifdown commands so you can simply do

auto br-vlan4
iface br-vlan4 inet static
    vlan-raw-device eth1
    bridge_ports vlan4
    bridge_maxwait 0
    bridge_fd 0
    bridge_stp off

Which will automagically

  • Bring up eth1
  • Create vlan4 bound to the eth1 interface
  • Bring up vlan4
  • Create the br0 with vlan4 attached
  • Give eth1 the same HW address as br0
  • Bring up br0 with the IP address


Lindsay made me do it!

While at the Waugh Partners launch party tonight, a bunch of people, mainly Lindsay asked for some details on what I’d be talking about at SLUG on Friday. I thought that was a very good question and that I should make something up πŸ™‚

So for those that are wondering I will attempt to cover the following topics in no particular order or level of detail

  • VoIP πŸ™‚
  • Codecs, which one should I use
  • VoIP Hardware (Phones, ATAs, ISDN and PSTN cards, Mobile Pods)
  • VoIP Providers and what they offer
  • Asterisk and what it can do
  • Beagle Internet IVR and distributed VoIP Call Centre as a case study
  • Asterisk@Home

If there is anything else that in particular you are interested in or would like me to talk about then let me know.

I’ll also be bringing along various bits of hardware and hope to have a full demonstration running.

At Jeff’s request I will be doing an in depth overview of the difference between FXO and FXS and why it is critically important to any VoIP implementation. This will most likely require at least 20 slides and about 50 minutes of explanation πŸ˜›

iptables evilness

Matt came to me with an interesting problem at Bulletproof this week. We have a dedicated hosting customer who talks to an external application for e-commerce. The IP for this was going to change but they needed to do to some testing before the switch. As usual with most enterprise applications, the hostname was hard coded. πŸ™

Matt suggested we do some DNS poisoning or do some transparent proxying using squid or similar. While these would have worked they required firewall changes through three levels of firewalls and extra infrastructure.

So I turned to an evil solution, iptables. πŸ™‚ Most people use DNAT on the inbound connection from the Internet to their internal private network to port forward to internal servers, or perform one-to-one NAT mappings. There is nothing stopping you using it the other way around.

Lets say that every time someone browses to http://bulletproof.net we want them to hit http://inodes.org instead. All you need to do is use DNAT to translate one IP address into the other.
animal:~ johnf$ host bulletproof.net
bulletproof.net has address
animal:~ johnf$ host inodes.org
inodes.org has address
animal:~ johnf$ sudo iptables -t nat -A PREROUTING -d -j DNAT –to


Now for some testing, a ping looks normal


animal:~johnf$ ping www.bulletproof.net
PING www.bulletproof.net.au ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=241 time=198 ms


but a tcpdump looks like


animal:~johnf$ sudo tcpdump -ni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
16:35:25.099510 IP > icmp 64: echo request seq 1
16:35:25.301712 IP > icmp 64: echo reply seq 1


Of course if anyone needs to try and debug this they are going to have a really fun time working out what is going on. πŸ™‚

If you want to test this yourself you can do it on your own machine using the OUTPUT chain instead of PREROUTING.


We’ve just hit 250 registrations for linux.conf.au, only 5 days to go before early bird registrations close.

So here are some interesting stats of the attendee breakdown so far:

By Country

Country Number
Brazil 1
Canada 1
France 1
Ireland 1
Liberia 1
Nigeria 1
China 1
Singapore 1
Spain 1
UK 1
Croatia 4
Germany 4
Japan 4
Romania 9
New Zealand 13
USA 18
Australia 188

Australia by state

State Number
NT 1
WA 19
QLD 20
SA 20
ACT 23
VIC 24
NSW 77