Monthly Archives: September 2010

DNAT and IP source routing woes

I recently came across a nasty problem.
I have a Linux box (let’s call it LinuxFW) with three ethernet ports:

  • LAN: connected to eth0
  • ADSL1: $IP1 connected to eth1
  • ADSL2: $IP2 connected to eth2

$IP1 and $IP2 are my public IP addresses.
Their respective default gateways are $GW1 and $GW2.

I use IP source routing to accept incoming connections from $IP1 and $IP2.
This is the easy part: there is a lot of documentation (see LARTC website for the details) on how to do this, I’ll just sum it up here for completeness.

ip route add default via $GW1 table adsl1
ip rule add from $IP1 table adsl1
ip route add default via $GW2 table adsl2
ip rule add from $IP2 table adsl2
ip route add default via $GW1

echo 200 adsl1 >>/etc/iproute2/rt_tables
echo 201 adsl2 >>/etc/iproute2/rt_tables

If somebody connects to $IP1 on port 22, LinuxFW receives packets on eth1 and outgoing packets are sent through eth1, thanks to the iproute2 rules mentioned above.
Similarly, if somebody connects to $IP2 on port 22, packets enter from eth2 and exit from eth2.

So far so good. Now comes the hard part:

I added a new Linux box behind the old one, let’s call it LinuxMail. The new box has IP address and is running Postfix. It’s connected to the same LAN switch that LinuxFW has on “eth0”.
Obviously I could install a smtp proxy on LinuxFW and redirect all emails from LinuxFW to LinuxMail, but this poses some tread-offs, i.e.:

  • LinuxMail won’t be able to see the IP addresses of incoming connections directly
  • LinuxMail won’t be able to do connection throttling
  • LinuxMail won’t be able to reject messages for non-existant accounts

All these problems can be solved to some degree by introducing more logic on the smtp proxy of course, but let’s assume that we don’t want to do that, either because LinuxFW doesn’t have enough resources or because we want to keep things simple.
There are three solutions to this problem.


All incoming packets with destination port 25 coming from either eth1 or eth2 will be redirected to and marked respectively with “0x6” and “0x7”. These iproute2 rules will take care of routing the reply packets to the appropriate interface:


Here is a simple way to open port 25 on both $IP1 and $IP2 and redirect incoming connections to LinuxMail using CONNMARK:

Of course you will still need the usual:

3 – Double IP addresses

Another DIY solution is to assign a second private IP address to LinuxMail. In this scenario LinuxMail has the following IP addresses:

and LinuxFW redirects incoming connections from $IP1 to and from $IP2 to

Of course you will still need the usual:


Pascal Hambourg:
Rodrigo Campos:


Usare opkg sulla Fonera

Utilizzando il firmware sulla Fonera 2.0N, il gestore dei pacchetti opkg non funziona di default. Occorre eseguire due operazioni:

  • Creare la directory /usr/lib/opkg: mkdir /usr/lib/opkg
  • Modificare il file /etc/opkg.conf come segue:
    src snapshots2
    dest root /
    dest ram /tmp
    lists_dir ext /var/opkg-lists
    option force_space

Fate attenzione però! L’opzione force_space fa sì che non vengano ignorati controlli sullo spazio libero effettivamente disponibile prima dell’installazione dei pacchetti. Dovrà essere vostra cura verificare di avere spazio disponibile a sufficienza in /jffs2 prima di procedere con l’installazione di nuovo software.


Find subtitles under MacOSX/Linux

There are a plethora of subtitle finders for Windows but only a few for MacOSX and Linux. Most of them often don’t work.

Searching for the right subtitle for a specific avi file can be frustrating. It’s not enough to match the filename. It’s always better to rely on the hash of the movie to find a properly sync’ed subtitle.

Fortunately, started offering a nice and easy interface to search their subtitle database. Here is a simple script I found on site and modified for my needs. It will help you to find the subtitles for your favourite movies and tv series:

use strict;
use warnings;
my $file = $ARGV[0];
unless (defined($file) and -r $file) { print "Syntax: $0 /path/file.avi\n"; }
my $hash = OpenSubtitlesHash($file);
print "
Now visit:
sub OpenSubtitlesHash {
my $filename = shift or die("Need video filename");
open my $handle, "<", $filename or die $!; binmode $handle; my $fsize = -s $filename; my $hash = [$fsize & 0xFFFF, ($fsize >> 16) & 0xFFFF, 0, 0];
$hash = AddUINT64($hash, ReadUINT64($handle)) for (1..8192);
my $offset = $fsize - 65536;
seek($handle, $offset > 0 ? $offset : 0, 0) or die $!;
$hash = AddUINT64($hash, ReadUINT64($handle)) for (1..8192);
close $handle or die $!;
return UINT64FormatHex($hash);
sub ReadUINT64 {
read($_[0], my $u, 8);
return [unpack("vvvv", $u)];
sub AddUINT64 {
my $o = [0,0,0,0];
my $carry = 0;
for my $i (0..3) {
if (($_[0]->[$i] + $_[1]->[$i] + $carry) > 0xffff ) {
$o->[$i] += ($_[0]->[$i] + $_[1]->[$i] + $carry) & 0xffff;
$carry = 1;
} else {
$o->[$i] += ($_[0]->[$i] + $_[1]->[$i] + $carry);
$carry = 0;
return $o;
sub UINT64FormatHex {
return sprintf("%04x%04x%04x%04x", $_[0]->[3], $_[0]->[2], $_[0]->[1], $_[0]->[0]);