Saturday, January 15, 2011

Your photography sucks

Have you noticed how everyone and their mother claims photography as a hobby nowadays? Do you know why? I'll cut right through the bullshit: because it's easy.

Okay, that's a bit of an explosive statement; good photography is everything but easy, in much the same way that good abstract expressionism is - I would imagine - extremely fucking difficult to pull off, but that doesn't stop anyone capable of projectile defecating paint from calling themselves an "artist".

Jackson Pollock was a genius. Whoever came up with this abomination, well...




Which brings me neatly to the next point in this disjointed rant: photography is the oil-on-canvas of the twenty first century. Anyone within snatching distance of a camera is equipped to take a picture and plaster it on their Flickr profile, but that doesn't make them a photographer any more than taking a laxative would make me a proctologist.

Annie Leibovitz, Robert Mapplethorpe... These people are photographers. You? You're an asshole with a camera, too much time, and not enough negative reinforcement.

Addendum: Yes, I do recall that I, too, have a Flickr profile. However, I've never claimed to be a photographer nor denied being a hypocrite.

Friday, January 14, 2011

Selective load balancing with Squid and iproute2

Recently I was asked by a client to develop a load balancing solution over two of their ADSL lines, but only for http traffic, and only for specific users. Sounds like a pain in the ass, right? Well, it was.

Essentially they've got four ADSL links:

  • eth0: 111.111.111.111 (main uncapped line)
  • eth1: 100.100.100.11
  • eth2: 100.100.100.22
  • eth3: 100.100.100.33

eth0 is the default route where all traffic goes through, and eth3 is used for something else.

They're using Squid as their proxy server, and want all traffic for a specific Squid ACL (let's call it "employees") to be load balanced between eth1 and eth2.

My biggest worry was in how to set this up without having to alter the default route on the system, but - as is always the case with Linux - there is a way if you look hard enough.

My first thought was to use iptables to mark packets, then set up an iproute2 rule to pick up on those packets and forward them to the relevant routing table. Unfortunately, the best one could do with this method is manipulate all http traffic, however, as mentioned, only the traffic for specific users must be load balanced.

Obviously, this method won't work.

The key to the solution is Squid's TCP_OUTGOING_TOS configuration directive. This directive allows one to set the TOS value in outgoing IP packets on a per-ACL basis. What this means is that if you have an ACL called "employees", you can have all traffic generated by the users in that ACL have the TOS set to an arbitrary value. You can then use an iproute2 rule to pick up on all packets with that value set and do whatever you want with them. Bingo!

Firstly, we need to create three routing tables: ADSL1, ADSL2 and BALANCE. This is usually done in /etc/iproute2/rt_tables.

Then we begin adding routing information:

# Assumes 100.100.100.10 is the address of the router on eth1
ip route add 100.100.100.9/29 dev eth1 src 100.100.100.11 table ADSL1
ip route add default via 100.100.100.10 table ADSL1

# Assumes 100.100.100.21 is the address of the router on eth2
ip route add 100.100.100.20/29 dev eth2 src 100.100.100.22 table ADSL2
ip route add default via 100.100.100.21 table ADSL2

Now we add some rules

# eth1 traffic goes to table ADSL1
ip rule add from 100.100.100.11 table ADSL1

# eth2 traffic goes to table ADSL2
ip rule add from 100.100.100.22 table ADSL2

# Squid sets desired traffic TOS. Marked traffic goes to table BALANCE
ip rule add tos 0x0c table BALANCE

And finally we create the multilink route in the table BALANCE.

ip route add default scope global table BALANCE nexthop via 100.100.100.10 dev eth1 weight 1 nexthop via 100.100.100.21 dev eth2 weight 1

Then finally, in your Squid configuration, simply add the configuration directive

tcp_outgoing_tos 0x0c employees

That's pretty much it. iptraf confirms that all http traffic for the desired ACL gets balanced over eth1 and eth2. Obviously the load balancing won't be perfect due to route caching, etc. But it probably is the most beautiful solution possible without splashing out on a pricey Cisco router or some such.

For more information, be sure to read the Linux Advanced Routing & Traffic Control HOWTO.