This is a small HOWTO about doing source routing with Squid and Linux. With Squid you can specifiy the outgoing IP address using ACLs. That means that you can select the outgoing IP using the information inside HTTP messages, thing that you can’t do with a firewall. The syntax is simple:


acl somedomain dstdomain somedomain.com
tcp_outgoing_address 1.2.3.4 somedomain

Those two lines say: “If the request is asking for somedomain.com, go to the world using IP 1.2.3.4″.

Now the Linux part. If you have more than one public IP address and you want to make the Squid configuration to work you need some iproute lines.


ip rule add table 10 from 1.2.3.4
ip route add table 10 default via GW

And those two lines says: “If the source IP of the packaet is 1.2.3.4, go via GW”.

Source routing with Linux is simple. What you do is to create a new table. This table will be used by that packets that match the criteria specified in “ip rule”. The “default table” is the table main, everything goes there if there is no rule. Is the table that you see with “ip route” or “route -n” (please, don’t use the last command anymore).

 

Post to Twitter

 

Today I calculated the space saved in one of the stores thanks to archiving+compression in one of the Zimbra servers that I’ve installed more than one ayer ago. The archiving volume has 273GB of email that uses 159GB of disk after compression. That’s 42% of saving.

I’m using a script to archive mails in the Open Source Edition that I’ve developed last year, running without any problems for more that 12 months.

It’s in my toolbox: https://github.com/diegows/toolbox

Post to Twitter

 

Today I had a problem with cron. One of that typical situation where a cron job doesn’t run and you don’t know the reason. If I ran the cron daemon from the command line, the cron job was executed. If I ran the daemon from the init script, nothing. Debugging the problem I executed the init script with “bash -x” where I saw that the script set the variable TZ with the content of /etc/timezone. This file had a different timezone from /etc/locatime link. The problem was that the job was working, but at different time. Cron has been a source of headaches…

Conclusion, if you have a problem with check, check /etc/localtime and /etc/timezone. They should point to the same timezone.

Post to Twitter

 

Today chatting via IRC I remembered a problem that I had some years ago with virtualization, iptables, nat and bridge. The situation of the guy asking was pretty similar. He has a one virtual machine (Qemu/KVM) connected to the world using a bridge and its default gateway is the virtualization host. He was trying to apply destination NAT to the VM in the host machine but it didn’t work. The rule was simple:


iptables -t nat -A POSTROUTING -s 10.0.3.11 -o eth0 -j MASQUERADE

It is perfect, there is nothing wrong there but he never saw the packet in the POSTROUTING chain. Why? The quick answer is “packets don’t cross nat table twice”. There is a flag in the Linux bridge to enable filtering with Iptables. Packets go to Iptables in the kernel when they are forwarded by the bridge. This includes the NAT table.

In the bridging process, you don’t know the outgoing interface so the previous rule doesn’t work. He needs the interface because he’s using MASQUERADE. In the routing process, the packets go to iptables but they never cross NAT tables because the packet already crossed the table in the bridging process.

How can we fix this? There are two options I think:

  • echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables #To disable Iptables in the bridge.
  • Raw table: Some years ago appeared a new tables in Iptables. This table can be used to avoid packets (connection really) to enter the NAT table: iptables -t raw -I PREROUTING -i BRIDGE -s x.x.x.x -j NOTRACK.
If you still don’t understand why this happens, I’ll try to explain one more thing. If you have an scenario with Virtualization and you host is your gateway, the packets follow this steps: [VM]->[bridge]->[virtual interface]->[host]->[physical interface]->[net]. When they cross the host, you have the routing process there.

Post to Twitter

 

There is a bug in some place of Ubuntu 10.04 that does crazy things with virtual machines using KVM. The symptoms are a really crazy cron process and time going backward. I don’t know the root of the problem but I suspected that is related with power saving. Why? Because the problems appear at night, when the systems are usually idle. Solution: processor.max_cstate=0. That disable CPU power saving. I don’t have an explanation but works for me.

Post to Twitter

 

Hice un upgrade de mi viejo módulo de Netlink ping. Primero lo renombré a Netlink Echo que encaja mejor a lo que hace. Después le hice unos cambios por que la API de netlink del kernel cambió desde la primera vez que lo armé con kernel 2.4. Está probado con el kernel 2.6.31 y funciona sin problemas.

Lo que publico acá es un módulo de kernel y su respectiva herramienta de userspace. La idea es mandar un mensaje de texto al kernel y que el kernel devuelva el mismo mensaje. Por eso el nombre Netlink Echo.

Netlink es un mecanismo que provee el kernel para comunicarse con él. Distintos subsitemas del kernel (Networkin en general, Udev, SCSI, etc) lo usan para que podamos configurarlos y pasarle parámetros. Netlink es un tipo de socket y se utilizan las mismas funciones que en otro tipos de socket: connect, bind(), send(), recv().

Les dejo el link del ejemplo en GitHUB, espero que les sirva. Más informacion “man 7 netlink”.

Post to Twitter

 

Estaba mirando un post en Lwn.net que hablaba de Tail Calls y un problema con Linux, así que me puse a investigar el tema. Ésto requiere un poco de conocimiento de la ABI de Unix, que en todo caso lo resumiré en otro post, si es posible.

Tail call es una llamada a una función, que se realiza al final de la función invocante, la cual suele ser optimizada en tiempo y espacio usando el stack frame de esta. Algo asi como:

int calc(int a){
   .
   .
   .

return func(a);

}

Reservar el stack frame para func() desperdicia tiempo y espacio. Aprovechando que el de calc() ya no va a ser utilizado. GCC lo deja a disposición de func().

Esta optimización es problemática en Linux, principalmente en system calls, por lo que es evitada con un hack que básicamente mete código nulo entre el fin de la función y el tail call:

asmlinkage long sys_open(const char __user *filename, int flags, int mode)
{
        long ret;

        if (force_o_largefile())
                flags |= O_LARGEFILE;

        ret = do_sys_open(AT_FDCWD, filename, flags, mode);
        /* avoid REGPARM breakage on x86: */
        prevent_tail_call(ret);
        return ret;
}

Los system calls tienen la etiqueta asmlinkage que indica que al GCC que esa función tiene todos sus argumentos en el stack.

Post to Twitter

© 2012 DiegoWoitasen Suffusion theme by Sayontan Sinha