Analyzing text protocols with a TCP proxy

To debug the Memcache server (memcached) on my localhost I needed an application that would log the in and output to a specific port on my local machine. In  the config in PHP I changed the memcache port (from 11211) to 11212. Then I ran the TCP proxy software to forward all connections on port 11212 to 11211. I know I could have used wireshark (and/or tcpdump) to just look at the traffic, but I felt like trying a more light-weight tool. I ran into two nice little TCP proxy programs: One written in Perl and one written in C++ with the Boost library.

Perl based TCP proxy

Torsten Raudssus wrote an application that has the following output:

tcpproxy

With the following commands you can run the TCP proxy:

git clone git@github.com:Getty/p5-app-tcpproxy.git
cd p5-app-tcpproxy/
sudo apt-get install cpanminus
sudo cpanm --installdeps .
perl bin/tcpproxy.pl 11212 127.0.0.1 11211

It is a lovely little project that definitely serves a niche. The only downside I see is that is has two CPAN dependencies. Perl is always available on Linux, but the dependencies certainly not. This makes it maybe a little harder to run when you are on a random machine debugging a nasty problem. If it would not have those it would become my next favorite (text) protocol analyzer.


C++ (Boost) based TCP proxy

Arash Partow also wrote a TCP proxy application in C++. It originally had no output, but I changed that. After my modifications the output looks like this:

...
56258 ==> delete memc.sess.key.lock.s5p5eh8fhvfe6iq06ot6nuim66

56258 <== DELETED

56258 ==> quit

56276 ==> add memc.sess.key.lock.s5p5eh8fhvfe6iq06ot6nuim66 0 1421275851 1
1

56276 <== STORED

56276 ==> get memc.sess.key.s5p5eh8fhvfe6iq06ot6nuim66

56276 <== END

56276 ==> set memc.sess.key.s5p5eh8fhvfe6iq06ot6nuim66 0 4 1331
debugger|a:1:{i:0;a:12:{s:3:"log";a:0:{}s:7:"queries";a:0:{}s:7:"session";a:2:{s:6:"before";
...

With the following commands you can run the TCP proxy:

git clone git@github.com:mevdschee/proxy.git
cd proxy/
sudo apt-get install build-essential
sudo apt-get install libboost-all-dev
make
./tcpproxy_server 127.0.0.1 11212 127.0.0.1 11211

As you can see I forked the original Github project to add some logging:

tcpproxy_cpp

It works like a charm, but I prefer the colored and smarter output of the Perl application. If I find some time I might copy the way the Perl proxy shows the output to C++. If you feel like it and you think you know how to do that, than I would be very happy with a PR!

NB: Arash Partow also wrote a variation to the code that does logging, it is on Google Code.

What is your favorite TCP proxy for analyzing text protocols? Let us know in the comments!

Tutorial: Apache 2.4 as reverse proxy

This post explains how to configure Apache 2.4 (the version that comes with Ubuntu 14.04) as a fully transparent reverse proxy. If you have a single website that has multiple paths that are actually run by different web applications then this tutorial may be for you.

reverse_proxy

The proxy will serve both web applications from their own virtual host configuration. These may be on the same machine as shown below using the loop-back addresses 127.0.0.1 and 127.0.0.2 or on different machines if you use their (internal) IP addresses.

Site: http://www.yourwebsite.com/
App1: http://www.yourwebsite.com/app1 = http://127.0.0.1/app1
App2: http://www.yourwebsite.com/app2 = http://127.0.0.2/app2

This is the directory structure in which I want to load the various web apps:

maurits@nuc:/var/www/html$ ll
total 28
drwxr-xr-x 4 root root  4096 Dec  1 21:43 ./
drwxr-xr-x 3 root root  4096 Apr 21  2014 ../
-rw-r--r-- 1 root root 11510 Apr 21  2014 index.html
drwxr-xr-x 2 root root  4096 Dec  1 21:45 app1/
drwxr-xr-x 2 root root  4096 Dec  1 21:45 app2/

In this tutorial we run the web applications on the same paths as on the proxy. This means that the web apps run in a subdirectory, even on the machines behind the proxy. This avoids the need of rewriting and thus keeps this setup simple and easy to debug.

Setting up the reverse proxy in Apache 2.4

What we are going to do is setup a reverse proxy. First we load the “proxy_http” module in Apache 2.4 using:

sudo a2enmod proxy_http
sudo service apache2 restart

Let’s setup the reverse proxy virtual host configuration in “/etc/apache2/sites-available/yourwebsite-proxy.conf” like this:

<VirtualHost *:80>
ServerName www.yourwebsite.com
DocumentRoot /var/www/html
ProxyPreserveHost On
ProxyPass /app1 http://127.0.0.1/app1
ProxyPass /app2 http://127.0.0.2/app2
</VirtualHost>

The virtual host configuration of app1 in “/etc/apache2/sites-available/yourwebsite-app1.conf” looks like this:

<VirtualHost 127.0.0.1:80>
ServerName www.yourwebsite.com
DocumentRoot /var/www/html
...
</VirtualHost>

And the virtual host configuration of app2 in “/etc/apache2/sites-available/yourwebsite-app2.conf” looks like this:

<VirtualHost 127.0.0.2:80>
ServerName www.yourwebsite.com
DocumentRoot /var/www/html
...
</VirtualHost>

Lets enable all sites and reload Apache using:

sudo a2ensite yourwebsite-proxy yourwebsite-app1 yourwebsite-app2
sudo service apache2 reload

Note that this works as the virtual host configurations with a specified IP address will be matched first. The “ProxyPreserveHost” will make sure the “Host” header in the request is not rewritten. The lack of a “ProxyPassReverse” will make sure that there is no rewriting done on the response.

Showing the correct remote IP address

It is important to understand that in the above setup, the proxied web application will only see a different “REMOTE_ADDR” environment variable, since there is absolutely no rewriting going on. The real visitor address is passed along in “X-Forwarded-For” header. This is a comma separated list and the last entry holds the real client IP address.

If you are on Apache 2.4, like in Ubuntu 14.04, you can correct the reported remote address by loading the “remoteip” module like this:

sudo a2enmod remoteip
sudo service apache2 restart

Add the “RemoteIPHeader” and “RemoteIPInternalProxy” directives to the virtual host configurations:

<VirtualHost 127.0.0.1:80>
ServerName www.yourwebsite.com
DocumentRoot /var/www/html
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.0/8
...
</VirtualHost>

Note that the “RemoteIPInternalProxy” you must specify the internal IP address of the proxy. To test if you did it right you can run a PHP script that calls “phpinfo()”. If you see that the “REMOTE_ADDR” value is not set to the proxy, then it is working.

Adding headers to the upstream request

We want to make Apache2 add upstream headers and therefor we need to load the “headers” module in Apache 2.4 using:

sudo a2enmod headers
sudo service apache2 restart

Next, we have to adjust the reverse proxy virtual host configuration in “/etc/apache2/sites-available/yourwebsite-proxy.conf” like this:

<VirtualHost *:80>
ServerName www.yourwebsite.com
DocumentRoot /var/www/html
ProxyPreserveHost On
RewriteEngine On
RequestHeader add X-SSL off
RewriteRule ^/app1/(.*) http://127.0.0.1/app1/$1 [P,L]
RewriteRule ^/app2/(.*) http://127.0.0.2/app2/$1 [P,L]
</VirtualHost>

In this example we add a “X-SSL” header with the value “off” to the proxied request. If you want to add headers to the response you can use the “Header” directive.

If you have any questions, please use the comments below.

Use Ubuntu’s “hostapd” to monitor your smartphone

I don’t like smart-phones at all. I do not like how people use them in bars and restaurants. I also don’t like that the phone is always online. Especially not since all kinds of “apps” and background processes are constant leaking information about me. Call me a fool, but I’m worried about my privacy. Since my friends nowadays refuse to send me SMS (they solely rely on WhatsApp) I was getting socially isolated (showing up at canceled events and so on). That is why I recently gave up my stubbornness and decided to buy a smartphone as well. Still everyday I am wondering what (and how) my smartphone is communicating over the Internet. To get an answer to this question I decided to investigate this.

Parts

SitecomWL113WirelessNetworkUSBAdapter wireshark

I had the above Sitecom (WL-113) USB wifi dongle laying around that could serve as an access point for my phone so that I could peek into the communication on my PC using the excellent open source Wireshark software. This is a diagram of the infrastructure:

wl-113_network

I am running Xubuntu 14.04 and I connected my USB dongle.

Preparation

First I ran “lsusb” to confirm the adapter was identified.

maurits@nuc:~$ lsusb
...
Bus 002 Device 024: ID 0df6:9071 Sitecom Europe B.V. WL-113 rev 1 Wireless Network USB Adapter

And yes it was. Great! Now to see what the system says about it when I connected it. Running “dmesg” showed me the driver that was loaded:

maurits@nuc:~$ dmesg
...
[20068.576242] usb 2-1.4: new high-speed USB device number 24 using ehci-pci
[20068.669492] usb 2-1.4: New USB device found, idVendor=0df6, idProduct=9071
[20068.669498] usb 2-1.4: New USB device strings: Mfr=16, Product=32, SerialNumber=0
[20068.669501] usb 2-1.4: Product: USB2.0 WLAN
[20068.669504] usb 2-1.4: Manufacturer: Sitecom
[20068.744236] usb 2-1.4: reset high-speed USB device number 24 using ehci-pci
[20068.837283] ieee80211 phy12: Selected rate control algorithm 'minstrel_ht'
[20068.837521] zd1211rw 2-1.4:1.0: phy12
[20068.855382] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready

To see whether the adapter was really there I ran “ifconfig -a” and yes it was and it was named “wlan0”:

maurits@nuc:~$ ifconfig -a
...
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:5387 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5387 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:634228 (634.2 KB)  TX bytes:634228 (634.2 KB)

wlan0     Link encap:Ethernet  HWaddr 00:00:de:ad:be:ef
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

I did get a little curious of what the dongle would look like on the inside, so I Googled for “zydas wl-113”. I found the following image on Wireless-Forum.ch:

wl-113

I also found a guy who had a Sitecom WL-113 with a Ralink 2571WF chip inside (probably not a “rev 1” model). But I am pretty sure mine has a ZyDAS 1211 as in the above picture (but I did not open it up). Before we can do “nice” things with it we need to see whether it supports “master mode“. This means that the dongle goes into a mode in which it behaves as an access point. Ubuntu has a tool called “iw” (install it with “sudo apt-get install iw”) that allows you to list the supported modes (amongst many other things) like this:

maurits@nuc:~$ iw list
Wiphy phy12
    ...
    Supported interface modes:
         * IBSS
         * managed
         * AP
         * AP/VLAN
         * monitor
         * mesh point

Bingo! Our dongle supports “AP” mode (many devices do not). You may want to try to put the adapter in master mode with the following command:

maurits@nuc:~$ iwconfig wlan0 mode master
Error for wireless request "Set Mode" (8B06) :
    SET failed on device wlan0 ; Operation not permitted.

But that fails. After reading the web a little I found that this does not mean that the dongle does not support it.

Installing “hostapd” the host access point daemon

You just need to install “hostapd” program using “sudo apt-get install hostapd”. Before you can start the hostapd application you need to take a few steps. First I had to create the “/etc/hostapd/hostapd.conf” file with the following contents:

interface=wlan0
bridge=br0
driver=nl80211
ssid=MyNetwork
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=YourPassPhrase
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Now edit the file “/etc/default/hostapd” and uncomment the “DAEMON_CONF” line and make it:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

If we want the PC to temporarily act like a router we need to enable IPv4 forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

Now you can start the “hostapd” access point software with:

sudo hostapd /etc/hostapd/hostapd.conf

If all goes well it should show:

maurits@nuc:~$ sudo hostapd /etc/hostapd/hostapd.conf
Configuration file: /etc/hostapd/hostapd.conf
Using interface wlan0 with hwaddr 00:00:de:ad:be:ef and ssid "MyNetwork"
wlan0: interface state UNINITIALIZED->ENABLED
wlan0: AP-ENABLED

If it does not work you may want to run the following:

sudo nmcli nm wifi off
sudo rfkill unblock wlan

This is because network manager has detected the wlan interface and grabbed it. If you need debug output you may run:

sudo hostapd -d /etc/hostapd/hostapd.conf

If you need even more debug output you may run:

sudo hostapd -dd /etc/hostapd/hostapd.conf

If this fails with the following message:

hostapd_free_hapd_data: Interface wlan0 wasn't started

Then execute:

sudo service hostapd stop

If it says it started (using “sudo hostapd”), but you actually don’t see the Wifi network on your smartphone then reconnecting the dongle and starting all over again may help. Note that the “hostapd” service will automatically be started on next boot.

Bridging to get Internet access

bridge_configuration

Now you may want to configure a bridge between eth0 (your Internet connection) and wlan0 (your dongle access point). First we remove the IP address from eth0 using. Then we add eth0 to bridge br0 (which already contains wlan0). After that we bring the bridge up, let it do DHCP and which also adds a default route to the gateway using:

sudo ifconfig eth0 inet 0.0.0.0
sudo brctl addif br0 eth0
sudo ifconfig br0 up
sudo dhclient br0

Now you should still be able to surf the Internet while you also have a software access point running on your computer. If you want to undo the bridge configuration you may run:

sudo ifconfig br0 down
sudo brctl delif br0 wlan0
sudo brctl delif br0 eth0
sudo ifconfig br0 down
sudo dhclient eth0

Permanent configuration (persist on reboot)

The IPv4 forwarding setting can be made permanent by uncommenting the following line in “/etc/sysctl.conf”:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

If you want to make the bridge configuration permanent you can add the following to “/etc/network/interfaces”:

manual wlan0
manual eth0

auto br0
iface br0 inet dhcp
        bridge_ports eth0

Note that this wont work since the network manager will still grab the wlan0 and execute “rfkill”. To avoid this you can turn off the network manager completely (and permanently) with:

sudo service network-manager stop
echo "manual" | sudo tee /etc/init/network-manager.override

To re-enable the network manager simply do the opposite:

sudo rm /etc/init/network-manager.override
sudo service network-manager start

Capturing with Wifi with Wireshark

Now we can start Wireshark on the wlan0 interface using:

sudo wireshark wlan0

And we get nice output:

wireshark_dump

Using this tool I can record and analyze the communication of the apps I installed on my smartphone.

Links/sources

Figuring all the above out was not possible without the following websites:

DD-WRT in Repeater Bridge mode

ddwrt

DD-WRT is a third party developed firmware, released under the terms of the GPL for many ieee802.11a/b/g/h/n wireless routers based on a Broadcom or Atheros chip reference design. — DD-WRT wiki

Today we are discussing DD-WRT and specifically how you can do some cool stuff that you would not be able to do with your current wireless router. Chances are that your home router is compatible with DD-WRT. You can find this out by checking the DD-WRT router database. With DD-WRT firmware loaded, your router is able to do some tricks it might not be able to do before. One of these things might involve the repeater bridge mode, which can improve your WiFi range at home. Since devices are automatically switching between WiFi and 3G, especially since the 3G prices (in the Netherlands) are quite high and/or low data traffic limits apply, this mode is a necessity.

So what is the plan? Let’s assume you have a living room with an (non wireless) Internet modem, a server, a printer and a laptop. In your study you have another three PC’s. You need a Mac, a Windows PC and a Linux computer right? Occasionally you bring your laptop from the living room. Let’s assume your wife (or husband) did not allow you to put a nice fast gigabit cable connection between your living room and the study, because he/she feels the cables do not match the interior design. Obviously there is no arguing and you need to go wireless. The fastest wireless connections you get now follow the N standard with a theoretical maximum of 300 Mbps. In reality you will probably only get a fraction of that, because of the distance you need to cover. In my house I get about 25 Mbit with going one floor up and passing a bathroom. But anyway, this would be the network layout you can build using DD-WRT on you router:

Repeater_Bridge

The funny poles are actually DD-WRT routers and one is configured as the primary. If your modem has wireless and a switch you can just leave that primary router out, since it is just configured as a standard access point. The secondary is actually a DD-WRT router in repeater bridge mode. This means it connects to the access point by wireless and then announces it’s own SSID (e.g. “wifi-study”) whereas the primary announces the “wifi-living”. Now you can use your laptop in the study as well, and connect the PC’s to the router through wired connections. Note that you can replace the antenna with a Yagi antenna and boost the transmission power to get a better reach and a higher wireless speed.

If you run the router in repeater bridge mode, there are a few settings you need to make sure you set correctly:

  1. You must set your encryption to “WPA2 personal” with “AES” encryption.
  2. You must set your wireless channel to a fixed one, so do NOT put it on “auto”.
  3. Please make sure you follow the instructions carefully.

If you do not yet own a DD-WRT capable router you might consider getting one of these new, very fast routers:

  • Netgear WNDR4300
  • Asus RT-AC66U
  • TP-Link TL-WDR4300
  • Cisco Linksys E4200

These very fast routers have awesome specifications and can run DD-WRT perfectly. I have the older, slower Cisco Linksys E2500 and even older and slower Cisco Linksys WRT54GL routers myself, but they also run DD-WRT fine.