Proxy-based Mischief with OpenWRT

Tom's picture
Tags: 

I hope that most of you have already seen the upside-downternet. This hack has been around for a while, but that doesn't make it any less brilliant: thanks to some Linux trickery, every user connected to your network gets served their images upside down. It's pretty clever.

It's also similar to a related but not-quite-identical application I've had in mind. So how does it work? The magic arrives in the form of transparent proxying, a technique whereby a router sends its traffic through a proxy server without the user responsible for that traffic noticing anything (or having to change their configuration). This is called "transparent proxying". In the case of the upside-downternet the Proxy server was Squid, an awesomely powerful, sprawling application. In this case Squid runs on its own machine; the router is configured to reroute its traffic through the Squid server before letting it out onto the net. The Squid server keeps an eye on the URLs being requested and uses a custom script to rewrite any that look like images. The replacement URLs point at a web-accessible script on the Squid server that knows to fetch the original image, flip it upside down, then serve it back.

As I said, I wanted to do approximately the same thing. But I wanted to do it all on the router. And I don't mean router in the systems engineer sense of "router". I don't mean a box sitting in a datacenter with fiber channel running into the back. I mean a box sitting on a shelf in Best Buy with a peel-off coupon on the front.

This is possible thanks to the magic of OpenWRT, a Linux distribution designed to run on consumer-market routers. I've played around with custom firmwares a bunch, but this was my first foray into OWRT, which is both more awesomely powerful and more intimidating than projects like Tomato or DD-WRT — by default, it doesn't even have a web GUI. Installation is still about the same, though. The only real difference is that after flashing the new firmware you have to telnet in, set your password, then configure the thing via SSH. The config file system is logically laid out, though, and probably a pretty good model for learning how to do lightweight Linux network administration. If you've got a DHCP-using ISP (e.g. a cablemodem) getting the thing working as a typical home router is as simple as commenting out one line (to enable wireless).

I ponied up for a Linux-friendly WRT54GL, not wanting to muck around with less-than-ideal hardware for what I expected to be an already sufficiently complex task. And it was. There are really three parts to the system I was trying to build: iptables (already somewhat installed) to forward traffic to the proxy; the proxy software; and a script to rewrite the URLs. Yeah, that's right: I'm not modifying the images locally. That would be a bit much for a poor li'l router's brain to handle. Besides, while there are good (or inescapable) reasons for keeping the aforementioned three pieces within the local network, once the new URL is composed it's just as easy to flip images on a beefier server sitting elsewhere.

There are two big problems, though. The first is space: after you install the latest build of OpenWRT (Kamikaze), you'll find that you only have 2 megs of free flash memory to play with. Worse, for somewhat esoteric reasons, you can't delete anything to reclaim space, or even trust the amount of free space reported by df. Reformatting the flash is the only way back — and something I had to do quite a lot of.

This is particularly problematic because of the size of Squid. Software for OpenWRT is installed through the ipkg system, a modular and easy-to-use means of adding capabilities to your vanilla OWRT installation. You can find a list of available Kamikaze packages for the WRT54GL's mipsel architecture here. And Squid is among them! But at 446k, it's a bit big. In fact, it's really big: after installing it there's no room left to get Microperl, Ruby or Python onto the router. I began to think about scaling back my ambitions and relying on sed to rewrite my URLs.

But salvation arrived in the form of a catastrophic stumbling block: Squid wouldn't work. There's something wrong with the currently compiled package; it won't run on OWRT. I'm sure somebody will fix it eventually, but for now it's a no-go for someone of my limited router knowledge.

So what are the alternatives? There's Tinyproxy, available as an OWRT package. It's a nice piece of software, and it can handle transparent proxying, but it can't rewrite URLs. I posted my problem to the OpenWRT mailing list and received a helpful reply from Stefan Monnier, who mentioned Polipo, a lesser-known piece of software that wasn't in the ipkg list, but which is available as a precompiled binary for the WRT54GL's architecture. Polipo can rewrite URLs, but it doesn't work as a transparent proxy. So I had two candidate proxies, each of which had half the functionality I needed. It was quite the conundrum.

Another user on the list suggested a solution that should have been obvious to me already: use both. And it works! Iptables sends all the outbound web traffic to Tinyproxy, which sits on port 8888 in transparent mode. Tinyproxy allows the use of "upstream" proxies, and, even better, can optionally restrict their use to certain domains. When it finds a request for a URL that matches a specified domain it'll forward the traffic to Polipo, which runs on port 8123. That software then rewrites the URL as necessary. As you can see, if your intended rewrite rule is specific to a particular domain, irrelevant requests won't even incur the overhead of Polipo. Best of all, the two packages leave enough room for the installation of Microperl to handle the rewrite script — a good thing, since Polipo didn't seem to like using sed for its rewrite script.

So! Here are the relevant files and iptables incantations in all their glory. As shown, it doesn't do anything but replace attempts to reach *.microsoft.com with the sourceforge.net homepage — but hey, it's just a proof of concept. I don't want to spoil the surprise of my real idea. If you feel like playing your own joke on your LAN's users, the original upside-downternet writeup should provide sufficient inspiration and code samples.

All of these files make some assumptions about where to put things — it should be pretty simple to figure out, though. They also assume that you're using most of Kamikaze 7.09's defaults — if you do something like, say, use a different local IP pool, you'll have to make some adjustments. As I mentioned the ipkges that need to be installed are Tinyproxy and Microperl, and you need to copy the compiled Polipo binary directly onto the router. You'll need the iptables-mod-nat and kmod-ipt-nat ipkges installed to make iptables capable of rerouting outbound traffic to the proxies. You'll also need to enable the init.d script; you can find details on that here.

iptables rule (add this to /etc/firewall.user):

iptables -A PREROUTING -t nat -p tcp --destination-port 80 -j REDIRECT --to-ports 8888

UPDATE: Whoops! Having used this solution a bit more, a problem has emerged: the system slows to a crawl if a number of successive calls to polipo-enabled (ie rewritten) URLs are made quickly. It looks to me like the suggested memory cap on Polipo was made by its author with the idea that no other proxies would be running side by side. So far halving that memory cap -- chunkHighMark in polipo.conf -- seems to correct the problem. I'll continue to make updates here if I discover otherwise.

AttachmentSize
/etc/init.d/proxies356 bytes
/etc/polipo/redirector.pl112 bytes
/etc/tinyproxy/tinyproxy.conf6.44 KB
/etc/polipo/polipo.conf174 bytes

Hi, this blog helped me a

Hi,

this blog helped me a lot in setting up a similar configuration!

I just currently have the problem that tinyproxy doesn't see the redirection that polipo does; i.e. tinyproxy serves me the original website instead of the modified/redirected one.

When using a local squid proxy which I connect to polipo it all works fine.

Have you changed anything special in your tinyproxy.conf file? (besides the upstream..) The link of your file just points to a non-existing page.

Thanks a lot,

rn

rn: nope, aside from the

rn: nope, aside from the upstream stuff it's all just the default. I also played with the number of threads/memory stuff, but that was done later and shouldn't affect the chaining of proxies.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockcode>
  • Lines and paragraphs break automatically.
  • You may post block code using <blockcode [type="language"]>...</blockcode> tags. You may also post inline code using <code [type="language"]>...</code> tags.

More information about formatting options

Captcha
Are you a robot? We usually like robots, but not in our comments.