domingo, 28 de diciembre de 2014

After using haproxy at work for some time I realized that it can be configured for a lot of things, for example: it knows about SNI (on ssl is the method we use to know what host the client is trying to reach so that we know what certificate to present and thus we can multiplex several virtual hosts on the same ssl IP:port) and it also knows how to make transparent proxy connections (the connections go through haproxy but the ending server will think they are arriving directly from the client, as it will see the client's IP as the source IP of the packages).

With this two little features, which are available on haproxy 1.5 (Jessie's version has them all), I thought I could give it a try to substitute sslh with haproxy giving me a lot of possibilities that sslh cannot do.

Having this in mind I thought I could multiplex several ssl services, not only https but also openvpn or similar, on the 443 port and also allow this services to arrive transparently to the final server. Thus what I wanted was not to mimic sslh (which can be done with haproxy) but to get the semantic I needed, which is similar to sslh but with more power and with a little different behaviour, cause I liked it that way.

There is however one caveat that I don't like about this setup and it is that to achieve the transparency one has to run haproxy as root, which is not really something one likes :-( so, having transparency is great, but we'll be taking some risks here which I personally don't like, to me it isn't worth it.

Anyway, here is the setup, it basically consists of a setup on haproxy but if we want transparency we'll have to add to it a routing and iptables setup, I'll describe here the whole setup

An example of a transparent setup can be found here but lacks some details, for example, if you need to redirect the traffic to the local haproxy you'll want to use the xt_TPROXY, there is a better doc for that at squid's wiki. Anyway, if you are playing just with your own machine, like we typically do with sslh, you won't need the TPROXY power, as packets will come straight to your 443, so haproxy will be able to get the without any problem. The problem will come if you are using transparency (source 0.0.0.0 usesrc clientip) because then packets coming out of haproxy will be carrying the ip of the real client, and thus the answers of the backend will go to that client (but with different ports and other tcp data), so it will not work. We'll have to get those packets back to haproxy, for that what we'll do is mark the packages with iptables and then route them to the loopback interface using advanced routing. This is where all the examples will tell you to use iptables' mangle table with rules marking on PREROUTING but that won't work out if you are having all the setup (frontend and backends) in just one box, instead you'll have to write those rules to work on the OUTPUT chain of the mangle table, having something like this:

Take that just as an example, better suggestions on how to know what traffic to send to DIVERT are welcome. The point here is that if you are sending the service to some other box you can do it on PREROUTIING, but if you are sending the service to the very same box of haproxy you'll have to mark the packages on the OUTPUT chain.

Once we have the packets marked we just need to route them, something like this will work out perfectly:

And that's all for this crazy setup. Of course, if, like me, you don't like the root implication of the transparent setup, you can remove the "source 0.0.0.0 usesrc clientip" lines on the backends and forget about transparency (connections to the backend will come from your local IP), but you'll be able to run haproxy with dropped privileges and you'll just need the plain haproxy.cfg setup and not the weird iptables and advanced routing setup.

Hope you like the article, btw, I'd like to point out the main difference of this setup vs sslh, it is that I'm only sending the packages to the ssl providers if the client is sending SNI info, otherwise I'm sending them to the ssh server, while sslh will send ssl clients without SNI also to the ssl provider. If your setup mimics sslh and you want to comment on it, feel free to do it.

jueves, 11 de diciembre de 2014

Debian does all the work that Ubuntu bases its system on, so... if you want to add our latest Debian source package repository to ubuntu, so that you can compile and use it under Ubuntu, that should be as easy as to add to your /etc/apt/sources.list file:

Well, just the line you want, if you want the future version of Debian (currently Jessie) use the testing one, if you want current develpment, use unstable, and sometimes you even get a experimental version if you want to test really bleeding edge versions.

The problem here is that after you add the lines you want to your sources.list file and you run your

apt-get update

You will end with a GPG error because the ubuntu's apt-key keyring doesn't know about Debian's keys, so... we'll have to run a few commands to get rid of this, but first we must locate the needed key for example here

A long time ago I was trying to have a transparent proxy setup by using squid, but squid traditionally only knows about http, ftp and https in explicit proxy mode. There is no way to handle non http (for example https) transparently on a traditional setup, so that setup was not what I was looking for.

After looking into TLS SNI and other things, trying even to implement things like that on some tools like socat that would proxify things for squid, I discovered ssl bump on squid3, which just does all the magic I was looking for.

Squid traditionally has several ways of listening to requests, one of which is the explicit proxy port (http_port 3128) and the other typical ones are for transparent proxy, this is indicated by flags:

transparent: used to intercept server queries and parse http host headers to forward them through squid to the servers

tproxy: used to spoof outgoing address to that of the client, so that squid is really transparent

Well, none of this allows us to forward https or tcp requests (say for example ssh, imap, ...) for a client that doesn't have explicit proxy support. Unluckily this means that a transparent proxy using this technology nowadays is of no use.

This is where ssl bump comes to the rescue, the old transparent mode of squid, which is currently called intercept, on squid3 has an extra flag: ssl-bump, which has the power of being able to intercept ssl traffic and things like that, allowing squid to cache https webs, but to do this, one has to create a Certificate Authority and the clients must trust this CA that squid uses to issue certificates for the web sites we want to visit.

However ssl-bump can work without issuing these certificates and in this case squid won't mess with https requests, but it will still allow us to do a pretty neat thing, which is to forward all tcp connections from any client (doesn't even have to know what a proxy is) transparently. In this case what squid does is to ask netfilter (iptables) where was the connection that squid is handling supposed to go, and squid makes this connection for the client so that it starts talking to the other end with all the traffic going through squid.

One might ask himself why would he want this traffic on squid, well, you'll have all of squid features, you can control the speed, you get all the typical logs and acls, ...

Of course that if you don't want this you can go with iptables and traffic shaper and that's good as well.

So... you like this idea? Well, then if your distro has squid compiled with ssl support you can read the config section, but if you are (like me) using Debian, you must recompile your squid3 with ssl support. Debian doesn't compile squid3 with ssl support as there are problems between openssl license and squid3 one (squid developers are looking forward to somebody porting the code to gnutls :-)

Rebuilding squid3 with ssl-bump

Well, to rebuild the squid3 package with ssl support you must install the needed packages:

apt-get install fakeroot libssl-dev
apt-get build-dep squid3

There you may find that your distro doesn't have all the packages needed to compile, like for example libecap2-dev, in this case you'll have to apt-get source these packages, compile and install them like we'll do with squid3

And then do a few things as user (we'll use fakeroot which we have just installed) I've tested this using squid3 from Debian testing (the next version, which will be Jessie)

Start with:

apt-get source squid3

And then we'll edit a couple of files on the source, so cd into the source dir and in the debian/control file you must add to the build-depends: libssl-dev and in the debian/rules file you must add this configure options:

--enable-ssl \
--enable-ssl-crtd \

One can then run debchange -i and add something like this on the changelog:

Build with --enable-ssl and --enable-ssl-crtd.

Now the source is ready to build using your favourite command, like for example:

dpkg-buildpackage -rfakeroot

and at last install the needed packages using dpkg -i

Configuration

The main configuration file is stored at /etc/squid3/squid.conf, even though it can be split into separate files. On these files we must set as SSL_ports all the ports for the protocols that we want to allow through squid using an acl like this:

The direct thing is to force the squid server to send ssl-bump requests directly and not through other caches, as this wouldn't work at all. The certificate is needed even though we won't be using it, just generate one using make-ssl-cert from the ssl-cert package or plain openssl x509 power.

Make sure we have all our client networks listed on our localnet acl and that they are allowed to use the proxy:

Several misc settings like: make sure that ssl-bump doesn't generate certificates for any host at all (just in case), set the language for the errors and allow a good number of filedescriptors so that we don't run out of them

ssl_bump none all
error_default_language es
max_filedescriptors 8192

And that is pretty much what is needed on the squid configuration, of course you can do this and more writing it all in different ways. I have found out that the directory for the ssl certs is not created by default, we must run: /usr/lib/squid3/ssl_crtd -c -s /var/lib/ssl_db

Routing it all through squid

You may be wondering how does all the traffic that we are going to allow through squid get to it. Well, the answer is easy if you have ever configured some kind of transparent proxy or similar, we do it through iptables, in the PREROUTING chain of the nat table we send things to the ssl-bump port or to our transparent proxy port as we like and then we open the ports on which we are serving all this on the INPUT chain of the filter table with something like this which can be loaded with iptables-restore myiptables.cfg:

I believe that's all, of course this is generally speaking and you'll have to adapt it to fit your needs, but there it is. Just add a dhcp server for convenience and ntp and dns servers so that you don't need to forward those protocols and in order to save more bandwith using the dns server cache and local ntp answers and you're done.

Note that these iptables are dropping all forwarding as in the example the kernel doesn't need to forward anything, squid does it, and for dns and ntp we are using local servers. Of course that if you want to forward some udp traffic, you'll need to add forwarding rules for that.

domingo, 6 de julio de 2014

It's been years since I started hibernating my machine by pressing the power button instead of halting it. This started at work, my mate Ramón wanted to get all machines automatically hibernated through the night and was doing some tests on the old Windows XP, I didn't knew how to hibernate at Linux at that time, so I started taking a look at it, saw it was easy and worked flawlessly, and so I've been doing it since then (how the Windows thing ended is another story with another end).

Lately what I had done was install acpi-support package and at /etc/acpi/events/powerbtn-acpi-support file I changed its action to: action=/etc/acpi/sleep_suspend.sh suspend
Which basically means when you press the power button hibernate (suspend to disk).

This used to work ok on most of my devices, however an old AMD socket 939 board did two hibernations each time the power button was pressed, and you could see the machine go to hibernate when you were waking it up. It seems I even had blogged about this here.

My latest solution for this problem seems that it was as simple as to do this little change to /etc/acpi/sleep_suspend.sh:
29c29
< pm-hibernate
---
> (sleep 1;pm-hibernate) &
I don't remember how I ended up with this solution instead of my first locking solution, but it did work for my desktop until it left sysvinit in favour of upstart but that's another story.

The thing is that ever since kernel 3.14 started to hit Debian I found the same sleep two times problem on my old laptop as well, and this still happens on 3.15.3. I have applied my solution to sleep_suspend.sh and it still works, but... I think I'll have to pick the details on this and file a bug, the question is... against Debian kernel? or try to post again to the linux-acpi mailing list like I did on 2011 and see if we get better results this time?

domingo, 20 de abril de 2014

It is a long time since I last "repeated" a radio using my laptop as I typically use a OpenWRT small device, so... I had to look it all up again, hey, we are on the nl80211 days.

So... I tried to look this up starting from one of my working setups, a OpenWRT device, and what did I find there? I found they are using a patched wpa_supplicant which says:

-H = connect to a hostapd instance to manage state changes

However this patch doesn't seem to have reached upstream, so... is it needed? Well I don't think it is, at least one can make a setup which works without it. BTW, if somebody can clarify on this option and why it hasn't reached upstream it would be great.

Well, here is my setup which seems to work OK on my Debian Jessie.

I'll be using hostapd and dnsmasq, what I do is disable them so that they are not started on boot and I start them whenever I need them (use update-rc.d for this or any other method you like).

I have defined an interface (ap0) which is not automatic or hotplug and which I ifup manually when I want to repeat a wifi:iface ap0 inet static
hwaddress XX:XX:XX:XX:XX:XX
address XX.XX.XX.XX
netmask 255.255.255.0
pre-up iw phy phy0 interface add ap0 type __ap || true
up cp /etc/hostapd/hostapd.conf.nochannel /etc/hostapd/hostapd.conf
up iw dev ath0 info|sed -n "s/.*channel \([^ ]*\) .*/channel=\1/p" >> /etc/hostapd/hostapd.conf
up /etc/init.d/hostapd start
up /etc/init.d/dnsmasq start
up iptables-restore /etc/iptables.masq
up echo 1 > /proc/sys/net/ipv4/conf/ap0/forwarding;echo 1 > /proc/sys/net/ipv4/conf/ath0/forwarding
down echo 0 > /proc/sys/net/ipv4/conf/ap0/forwarding;echo 0 > /proc/sys/net/ipv4/conf/ath0/forwarding
down /etc/init.d/dnsmasq stop
down /etc/init.d/hostapd stop
post-down iw dev ap0 del || true
On the interfaces file what I do is: I create the new AP interface, set up a hostapd.conf file adding the current channel for my client interface (ath0), start hostapd and dnsmasq and set up masquerading and forwarding.

The /etc/hostapd/hostapd.conf.nochannel file is a simple config file, something like this works:
interface=ap0
ctrl_interface=/run/hostapd-phy0
driver=nl80211
ssid=Whatever
hw_mode=g
wpa=2
wpa_pairwise=CCMP
wpa_passphrase=BlaBlaBla
country_code=ES
ignore_broadcast_ssid=0
And of course you can add all the parameters you want, for example, for my 802.11N radio I use:
wmm_enabled=1
ieee80211n=1
ht_capab=[HT40+][SHORT-GI-40][DSSS_CCK-40]
I won't get to dnsmasq details, I don't use it much, but I think I should know it better, I only added this couple of lines to the default config:
interface=ap0
dhcp-range=StartingIP,EndingIP,12h
Well, I guess that pretty much is it, as for the iptables rules... you know, allow forwarding from your AP to your client wifi and add a POSTROUTING with -j MASQUERADE to traffic going out and that's it.

Hope you find this usefull, and if you want to enlighten the -H parameter history feel free to comment.

What I think after reading the commit (https://dev.openwrt.org/browser/trunk/package/network/services/hostapd/patches/453-ap_sta_support.patch?rev=37738) is that they are having wpa_supplicant reload any time the client reconnects or whatever, but this can also be done on wpa_cli, so that must be why it hasn't reached upstream (but that's just what I'm guessing, any light out there?).