They are following you!

Recently there was a discussion with the privacy officer of Hamburg. He was arguing about people using Google-Analytics, but he also tracks his visitors on his public website. So are you anonymous? Of course not! Lets have a look at the why.

What's the problem?

Many webmasters analyze their website with Google-Analytics. This is a service of Google, very easy to use. All you need to do is insert a small script somewhere into your HTML-code:

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'SOME_ID']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

This code tells the visitors browser to download a script from http://www.google-analytics.com/. That is while you visit this website, you additionally visit Google’s website in the background. Google of course recognizes this visit and knows which website you accessed. That is of course very cool for webmasters, they’ll get very detailed statistics about their visitors without any own work. Which article is favored most, should articles be published in the morning or in the evening, where do the visitors come from, how much time do they spend on the site and so on. Visitors don’t even know that Google follows them on nearly every website they visit. So Google is able to create very extensive profiles of every web user. Where do I come from? Am I interested in technical or political topics? Which videos do I like at YouTube? How frequently do I visit YouPorn? Based on my clicks it’s easy to guess my gender (shoes or cars?), my age (SpongeBob or cure), my professional (stock market news or music)… Do you have an account at Twitter? Google-Analytics also tracks user generated content. Together with some personal sites at Xing or LinkedIn or a blog at bloggers.com it’s easy to get a comprehensive profile of a single web user.

So Google is the bastard?

Oh not in the slightest! There are a lot of these companies. The previous mentioned privacy officer for examples tracks it’s users with IVW. The IVW uses a similar technique, you add a small image, a so called web bug, to your site:

<img id="ivw_pixel" src="http://heise.ivwbox.de/cgi-bin/ivw/SOMEID">

Since it is exactly 1 pixel it is not visible to the user, but your browser nevertheless loads it from ivwbox.de and so they get notified if you visit this specific website. Prominent customers are also Heise, Playboy, Xing, Ebay, Bild.de and a lot more (click the links to get some statistics). So IVW also creates extensive profiles of you! Do you really want to connect you professional Xing profile with Bild.de or Playboy? ;-)

But not enough, you know these funny pictures:

How often did you see one of these buttons today? Do you know a website that doesn’t have a like button (except mine)? Lets have a look to the HTML code:

<iframe src="https://plusone.google.com/u/0/_/+1/SOMESTUFF" allowtransparency="true" hspace="0" id="SOMEID" marginheight="0" marginwidth="0" name="SOMENAME" style="STYLE" tabindex="-1" vspace="0" scrolling="no" width="100%" frameborder="0"></iframe>
[...]
<iframe src="http://platform.twitter.com/widgets/tweet_button.html#_=ID" title="TITLE" style="STYLE" class="CLASS" allowtransparency="true" scrolling="no" frameborder="0"></iframe><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
[...]
<iframe src="http://www.facebook.com/plugins/like.php?href=ID" style="STYLE" allowtransparency="true" scrolling="no" frameborder="0"></iframe>
[...]
<script src="http://www.stumbleupon.com/hostedbadge.php?s=1"></script><iframe src="http://www.stumbleupon.com/badge/embed/1/?url=ID" style="STYLE" allowtransparency="true" scrolling="no" frameborder="0"></iframe>

Wow, while we visit one single website, our browser notifies Google, Twitter, Facebook and StumbleUpon about our short visit. Crazy, isn’t it? And there are much more networks that offer such buttons. Or have a look at this picture:

Each button is loaded from foreign webservers. I hardly can see any benefit for the user or the webmaster!?

How to defend?

There is no protection, power off all your electronics and go back to the stone age! (Or get amish) Ok, that’s hard and somewhat impossible these days. But there are some possibilities to minimize the tracking.

For example some Firefox extensions like NoScript prevent your browser loading scripts from foreign servers (see Google-Analytics). But you’ll also load these buttons and iframes, because this is simple HTML. Here you need another extension like AdBlockPlus. This allows you to define rules for blocking specific content, e.g. everything that comes from facebook. But keep in mind that these companies own different domains, like facebook.com, facebook.net or fbcdn.net. And even if you think you got all of them, there are a lot more. There is also a filter list for social media stuff available at Chrome Adblock (yes, comes from Google, but does its job…). If you are not running Firefox or you don’t want to install a bunch of plugins, you can also send these request to nirvana. For example unix-guys might add lines like this to their /etc/hosts :

192.168.23.23 facebook.com

Every time your browser wants to load a script from facebook.com he sends a request to 192.168.23.23 , which hopefully doesn’t exists. Do the same for all the other profiler.

Fear?

Don’t be frightened now, but be aware! You should carefully decide what to publish about yourself and others around you. And of course take care of your privacy. Some days ago we went to Berlin for a meeting, when a colleague received a message via facebook on his BlackBerry from a friend asking what he’s doing in Berlin!? Looks like his smart-phone told facebook its GPS position without his approval!? That’s scary, isn’t it!

So think twice while exploring the world wide web ;-)

Hacking Havag

Ihr kennt vielleicht die Havag (Hallesche Verkehrs-AG)? Das ist das Verkehrsunternehmen in Halle, befördert uns zu maximalen Preisen bei dürftiger Qualität. Wie auch immer.

Das Unternehmen bietet seinen Kunden ein Widget an, mit dem man vom Wohnzimmer das Eintreffen der Bahnen an der nächstgelegenen Haltestelle monitoren kann. Das ganze nennt sich mobile@home (siehe Bild 1) und ist in Java geschrieben. Ist eigentlich eine feine Sache, man muss nicht mehr nach Bauchgefühl das Haus verlassen, wenn ja doch gerade keine Bahn kommt. Das Fenster nervt jedoch tierisch. Ich hab seit langen auf meinem Schedule einen Eintrag, der mich daran erinnert eine bessere Lösung zu finden. Heute Nacht hab ich mich nun endlich an die Arbeit gemacht.

Das Problem ist wie üblich eine geschlossene Software, keine Dokumentation für jemanden wie mich. Ja es ist Java, also wäre es ein Leichtes die Binaries zu dekompilieren, deren Projekt besteht jedoch aus >1000 Klassen (öhm overhead!) und über den rechtlichen Aspekt bin ich mir da auch nicht sicher. Aber was wird das Tool wohl machen? Es wird einen zentralen Server nach den nächsten Stopps an einer von mir gewählten Haltestelle fragen. Der Server wird dann sicherlich mit den jeweiligen Bahnen antworten. Soweit Client und Server kein kryptisches Protokoll sprechen kann ich also einfach den Netzwerkverkehr der über meine Interfaces geht mitschneiden und nachbauen. Also fix den Sniffer meines Vertrauens und das tolle Tool gestartet. Schnell wurde klar um welchen Server es sich handelt: 83.221.237.42 auf Port 20010 . Und die Sache war auch schon so gut wie gegessen als ich folgende Pakete an mir vorbei rauschen sah:

usr@srv % tcpdump -A -n src 83.221.237.42 or dst 83.221.237.42 and tcp port 20010
[...]
03:19:29.177630 IP 192.168.9.55.39453 > 83.221.237.42.20010: Flags [P.], seq 231:443, ack 108, win 35, options [nop,nop,TS val 28628068 ecr 367433884], length 212
E....2@.@.....  7S..*..N*..["..:~...#.......
...d....POST /init/rtpi HTTP/1.1
Content-Type: text/xml
User-Agent: Java/1.6.0_26
Host: 83.221.237.42:20010
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 47


03:19:29.177676 IP 192.168.9.55.39453 > 83.221.237.42.20010: Flags [P.], seq 443:490, ack 108, win 35, options [nop,nop,TS val 28628068 ecr 367433884], length 47
E..c.3@.@..z..  7S..*..N*..[...:~...#.=.....
...d....c..m..getDeparturesForStopS..An der Feuerwachez
03:19:29.229795 IP 83.221.237.42.20010 > 192.168.9.55.39453: Flags [.], ack 490, win 65488, options [nop,nop,TS val 367433990 ecr 28628068], length 0
E..4..@.r.}.S..*..      7N*....:~..\\%....s......
.......d
03:19:29.234736 IP 83.221.237.42.20010 > 192.168.9.55.39453: Flags [.], seq 108:1556, ack 490, win 65535, options [nop,nop,TS val 367433992 ecr 28628068], length 1448
E.....@.r.x1S..*..      7N*....:~..\\%....h......
.......dHTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 1869
Date: Tue, 09 Aug 2011 01:19:29 GMT

S..9S..Soltauer Stra..eS..2011.08.09.03:46:00S..2011.08.09.03:46:00S..trueS..38150S..651S..falseS..falseS..38150:12840S..A FeuerwacheS..falseS..falsezVt..[stringl...l...ingl...
[...]

An der Feuerwache ist die Haltestelle, für die meine Anfrage raus ging, und ein POST -connect mit den Daten ...d....c..m..getDeparturesForStopS..An der Feuerwachez sieht stark nach dem aus, was ich gesucht habe. Kurz darauf kommt auch gleich die Antwort S..9S..Soltauer Stra..eS..2011.08.09.03:46:00S..2011.08.09.03:46:00S..true[..] , und tatsächlich fährt eine Linie 9 in kürze zur Soltauer Straße . Dedüm!! Der Rest ist simpel. Nur noch mit ‘nem Hexeditor (ich empfehle hexcurse) in die Pakete hinein geschaut um zu sehen was genau übermittelt werden muss (die . zwischen den Daten stehen für Zeichen, die in meinem Terminal nicht für mich sichtbar dargestellt werden können. Deren Hexadezimal-Code gibt aber Aufschluss über ihren Wert). Mit ein wenig Trial&Error ist die Geschichte vom Tisch.

Natürlich ist meine Alternative zu dem Widget für jedermann verfügbar:

Als Argument einfach die gewünschte Haltestelle angeben:

usr@srv % ./havag.pl Straßburger Weg
Frage http://83.221.237.42:20010/init/rtpi nach geplanten Stops für 'Straßburger Weg'...

 Zeit   Linie   Richtung
15:33       4   Kröllwitz
15:36       5   Bad Dürrenberg
15:42       5   Kröllwitz
15:44       S   Sonderfahrt
15:45       4   Hauptbahnhof
15:48       4   Kröllwitz
15:51       5   Ammendorf
15:57       5   Kröllwitz
16:00       4   Hauptbahnhof
16:03       4   Kröllwitz
16:06       5   Bad Dürrenberg
16:12       5   Kröllwitz
16:15       4   Hauptbahnhof
16:18       4   Kröllwitz
16:21       5   Ammendorf
16:27       5   Kröllwitz
16:30       4   Hauptbahnhof

Das Protokoll

Vielleicht hat ja jemand Lust weitere Tools zu schreiben, die die “Serverschnittstelle” der Havag benutzen. Daher hier eine kurze Dokumentation des inoffiziellen Protokolls, das mit dem Server gesprochen werden kann.

Eine Anfrage an den Server muss via HTTP-POST an 83.221.237.42:20010/init/rtpi geschehen und die folgenden Inhalte liefern:

[COMMAND]x00[LEN][FUNCTION]x00[LEN][FUNCTIONNAME]x53x00[LEN][ARGUMENT]x7A

Hierbei ist xAB das Zeichen für den Hexwert AB , LEN ist die Länge der darauf folgenden Zeichenkette. Um den Server nach den nächsten Stopps am Rennbahnkreuz zu fragen sendet man als Kommando ein c , als Funktion ein m , und die Funktion heißt getDeparturesForStop . Als Argument wird dann die Haltestelle erwartet. Die Anfrage in HalbHex sieht also wie folgt aus:

cx00x01mx00x14getDeparturesForStopx53x00x0dRennbahnkreuzx7a

und komplett Hexadezimal-kodiert:

x63x00x01x6dx00x14x67x65x74x44x65x70x61x72x74x75x72x65x73x46x6fx72x53x74x6fx70x53x00x0dx52x65x6ex6ex62x61x68x6ex6bx72x65x75x7ax7a

Als Antwort bekommt man die Abfahrtszeiten in den nächsten 60 min. Die Antwort beginnt mit einer Zeichenkette die ich nicht verstehe und vorerst nur verwerfe. Ein Eintrag für eine Bahn startet mit den Hexadezimalwerten x56x74x00x07x5Cx5Bx73x74x72x69x6Ex67x6Cx00x00x00x0D . Darauf folgen die einzelnen Informationen zu dieser Bahn. Eine einzelne Information ist wie folgt kodiert:

x53x00[LEN][INFO]

LEN gibt hier wieder die Länge der folgenden Information an, die Information selbst ist ASCII Klartext. Ein Bahneintrag wird abgeschlossen mit einem x7a (z). Folgende Daten werden übermittelt:

Linie   Endstation      Ankunft                 ???                     N       ???     ???     ???     ???     ???             Angefragte Haltestelle  ???     ???  z
91      Am Steintor     2011.08.09.02:42:35     2011.08.09.01:13:00     false   18824   0       false   false   18824:90120     An der Feuerwache       false   falsez

Das boolsche N gibt an, ob es sich um eine Niederflur-Straßenbahn handelt. Die mit ??? gekennzeichneten Felder verstehe ich (noch) nicht. Vielleicht etwas wie Wagennummer/Typ, ob es eine Verspätung gibt etc. Kann man sicher auch herausbekommen, da sie aber für mich vorerst nicht wichtig sind habe ich mich nicht weiter darum gekümmert.

Meine Beschreibungen sind natürlich alles andere als komplett, für die Korrektheit kann ich auch nicht garantieren. Vielleicht gehört das x00 vor der Längen-Kodierung auch mit zur Längenangabe und ist bei den kurzen Zeichenketten nur immer 0? Wer weiß, in der Praxis funktioniert mein Gehacktes aber (mindestens für mich) ;-)

Update: Wird getDeparturesForStop ohne Argumente gesendet, bekommt man eine Antwort mit allen Verfügbaren Stopps. (via @michas)

Damit ist also der Weg für coole neue Apps geebnet. Vielleicht hat ja jemand von euch eines dieser Smartphones (oder es findet sich ein Sponsor der mir eines zur Verfügung stellt)?

Übrigens flogen auch hin und wieder Pakete mit Inhalten wie diesem vorbei: Apache Tomcat/5.5.17 - Error report . Spricht nicht gerade für das Widget. :-P

Download: Perl: havag.pl (Please take a look at the man-page. Browse bugs and feature requests.)

WordPress WordCloud with R

These days one can frequently read about wordclouds created with R, initiated by the release of the wordcloud package by Ian Fellows on July 23rd. So here I am to put in my two cents.

I thought about creating a wordcloud of a complete blog history, so I build a script that connects to a MySQL database and grabs all published posts and pages. All articles are combined in an huge text, that, when purged from tags and special chars, is visualized as a wordcloud:

[cc lang=”rsplus” lines=”-1” file=”pipapo/R/wordpress-wordcloud.R”][/cc]

Enough code, here is the result for my slight blog:

Smart image, isn’t it? Unfortunately it takes about 30 secs to generate it, otherwise it would be cool to create such a cloud live, for example using rApache.

Download: R: wordpress-wordcloud.R (Please take a look at the man-page. Browse bugs and feature requests.)

Installing an HP ProLiant

I just installed a new server from HP, a ProLiant DL180 G6. Here are some notes about the setup.

To check the hardware status you need to install the ProLiant Support Package. Running a Debian/Ubuntu you should import the HP PSP mirror in your sources.list . It can be found here, you might include something like:

deb http://downloads.linux.hp.com/SDR/downloads/proliantsupportpack/Debian stable current/non-free

After an aptitude update you’ll find some new packages. I recommend to install hpaclui to speak to your raid-controllers and hp-health to interact with your hardware.

With hpaclui you can ask the raid-controllers for some information:

usr@srv % hpacucli ctrl all show status

Smart Array P123 in Slot 1
   Controller Status: OK
   Cache Status: OK
   Battery/Capacitor Status: OK

usr@srv % hpacucli ctrl slot=1 show config

Smart Array P123 in Slot 1                (sn: SOMESN  )

   array A (SAS, Unused Space: 0 MB)


      logicaldrive 1 (99.99 GB, RAID 1, OK)

      physicaldrive 1I:1:1 (port 1I:box 1:bay 1, SAS, 99 GB, OK)
      physicaldrive 1I:1:2 (port 1I:box 1:bay 2, SAS, 99 GB, OK)
      [...]

   array B (SAS, Unused Space: 0 MB)


      logicaldrive 2 (99.99 TB, RAID 5, OK)

      physicaldrive 1I:1:3 (port 1I:box 1:bay 3, SAS, 99 TB, OK)
      physicaldrive 1I:1:4 (port 1I:box 1:bay 4, SAS, 99 TB, OK)
      [...]

   Expander 250 (WWID: SOMESN, Port: 1I, Box: 1)

   Enclosure SEP (Vendor ID HP, Model SOMEMD) 248 (WWID: SOMESN, Port: 1I, Box: 1)

   SEP (Vendor ID SOMEVNDR, Model  SOMEMD) 249 (WWID: SOMESN)

So you get an idea of your storage.

The hp-health packages comes with a tool called hpasmcli . It’s used to query all the hardware states:

usr@srv % hpasmcli -s "SHOW"

Invalid Arguments
         SHOW ASR
         SHOW DIMM
         SHOW FANS
         SHOW HT
         SHOW NAME
         SHOW PORTMAP
         SHOW POWERMETER
         SHOW POWERSUPPLY
         SHOW SEL
         SHOW SERVER
         SHOW TEMP
         SHOW TPM
         SHOW UID

usr@srv % hpasmcli -s "SHOW POWERSUPPLY"

Power supply #1
        Present  : Yes
        Redundant: Yes
        Condition: Ok
        Hotplug  : Not supported
Power supply #2
        Present  : Yes
        Redundant: Yes
        Condition: Ok
        Hotplug  : Not supported

Both tools are very easy to use and give a great overview about the health. So I immediately developed a monitoring plugin that parses the output of those runs. I came to the point, that I wasn’t able to find some documentation about the hpasmcli tool. Most of its output was clear, but I don’t know what happens if a fan breaks. The output with working fans looks like:

usr@srv % hpasmcli -s "SHOW FANS"

Fan  Location        Present Speed  of max  Redundant  Partner  Hot-pluggable
---  --------        ------- -----  ------  ---------  -------  -------------
#1   SYSTEM          Yes     NORMAL  45%     Yes        0        No            
#2   SYSTEM          Yes     NORMAL  43%     Yes        0        No            
#3   SYSTEM          Yes     HIGH    100%    Yes        0        No            
#4   SYSTEM          Yes     HIGH    100%    Yes        0        No            
#5   SYSTEM          Yes     NORMAL  22%     Yes        0        No            
#6   SYSTEM          Yes     NORMAL  21%     Yes        0        No            
#7   SYSTEM          Yes     NORMAL  47%     Yes        0        No            
#8   SYSTEM          Yes     NORMAL  46%     Yes        0        No

So what if a fan is broken? Is it still Present and the Speed -string just changes to NONE or something like that? I send a support request to HP, but all they respond was a premium-rate number to call. Seems that my understanding of service differs from theirs. Since I don’t know how the output looks like in an error case (I don’t want to stick pencils into new machines) the plugin can’t decide whether the fans are OK. If you want to use my plugin you need to skip fan-checks until HP publishes a document with possible values. IMHO a public tool should be open source, so I can get those information on my own, or at least well documented!

Btw. HP if you read this, please include some permanent links to your web interface ;-)

Now I'm R-Blogging

Today a lot of great mails arrived at my inbox. In one of them I was reading I’ve just added your feed to the site.

Where did this mail come from?

The sender of the email was Tal Galili. He is a researcher in BioStatistics at the Tel Aviv University, very active around the internet. He also originated R-Bloggers and in this email he told me that I’m recruited ;-)

What is R-Bloggers

R-Bloggers is an aggregation of more than 200 bloggers writing about GNU’s R and some statistics/math/hacks that can be done using R. If you didn’t heard about R-Bloggers I strongly recommend to take a look at their website. I’m following this project since a while, it’s a great fusion of brainiacs! So I’m proud to have my modest R-related articles listed between them.

Btw. if you like R-Bloggers and/or have some R experiences yet you should also take a look at the ‘R’ programming Wikibook. Contributing your knowledge is greatly appreciated!

Let’s see what the future brings, happy hacking!

Rate My Po...

…sts (of course!). Yesterday I just installed a rating plugin, inspired by these stackexchange platforms.

Searching through the WordPress plugin directory didn’t make me happy. All existing plugins lack of desired features. After some tests I decided to modify UpDownUpDown of Dave Konopka. It’s a nice plugin, but still didn’t match my criteria. For example guests were not allowed to vote, there were some XHTML bugs and I didn’t like the style. So I created a patch (it’s attached..) and sent it to Dave (I don’t yet have a github account). He told me that he’ll take a look at it and might apply it to the official plugin, so if you also want to use this rating plugin with my additional features just keep the URL in mind and watch out for a new version.

The special version I’m using here right now has of course some more slight changes, to have it perfectly matched to my own blog. So you are now able to vote for articles, positive or negative, to give me a hint what my visitors like to read ;-)

I additionally installed a further page that lists my articles sorted by votes: top. So you can get a smart overview of best/worst content.

With this in mind: Happy voting! ;-)

Download: Patch: Patch for UpDownUpDown [03e9bb8017...] (Please take a look at the man-page. Browse bugs and feature requests.)

Build your own Network packets

Ever worried about these disgusting packets leaving your network interface!? Why not creating your own packets?

Of course it’s more than nonsense creating all packets on your own, but sometimes there might be a reason making you wish you could.. For ex. for my last article I searched for a possibility to modify some contents of a packet. First I thought about using iptables , but than I found a nice tool: scapy!

With scapy you can create your own packets, IP/TCP/UDP whatever! It is very heavy but comes with an user-friendly interface. Using Debian/Ubuntu you need to install python-scapy :

aptitude install python-scapy

To open the interface just run scapy . You can easily create an IP packet by typing something like this:

>>> ippacket=IP()
>>> ippacket.dst='binfalse.de'
>>> ippacket.ttl=12
>>> ippacket
<IP  ttl=12 dst=Net('binfalse.de') |>

So an IP packet is stored in the variable ippacket . This packet will be send to binfalse.de and has a ttl of 12 (if there are more than 12 network nodes between your machine and the target it will disappear and never arrive at the target). Let’s create some TCP stuff:

>>> tcpcrap=TCP()
>>> tcpcrap.sport=1337
>>> tcpcrap.dport=80
>>> tcpcrap
<TCP  sport=1337 dport=www |>

We stored some TCP information in tcpcrap . This packet will be send through your port 1337 and hopefully arrive at port 80 (in general a webserver is listening on port 80 ). That’s it for the networking part. Last but not least we will create some data to send:

>>> data='GET / HTTP/1.1 \\nHost: binfalse.de\\n\\n'
>>> data
'GET / HTTP/1.1 \\nHost: binfalse.de\\n\\n'

Combining all parts we’ll get a very nice packet, sending it will trigger my webserver to send the main page of my website (Sending exactly this packet won’t ever result in any website from my webserver. Why? Just think about…):

>>> whole=ippacket/tcpcrap/data
>>> whole
<IP  frag=0 ttl=12 proto=tcp dst=Net('binfalse.de') |<TCP  sport=1337 dport=www |<Raw  load='GET / HTTP/1.1 \\nHost: binfalse.de\\n\\n' |>>>
>>> send(whole)
.
Sent 1 packets.

Well done! Ok, that’s very much to do. But fortunately it’s just that much code for explanation, you can send the same packet in a single line:

>>> send(IP(ttl=12,dst='binfalse.de')/TCP(sport=1337,dport=80)/'GET / HTTP/1.1 \\nHost: binfalse.de\\n\\n')
.
Sent 1 packets.

Very smart, isn’t it? You can also sniff whooshing packets! But something like this I won’t explain, find out by yourself ;-)

Connecting through a NAT - the non-trivial direction

I often here people saying something like

SSH to your home PC? Sitting behind a NAT? A snowball's chance in hell...

But is it really impossible?

What is a NAT?

NAT (network address translation) is a technique to cover multiple clients behind one router. Kristian Köhntopp explained the technology very well in his article NAT ist kein Sicherheitsfeature (GER). But let me summarize some things. Here is a small image to visualize the topology of an example network:

You see, the NAT represents something like a bridge between it’s clients (in network 10.0.0.0/24 ) and the rest of the world. The connections of the clients are translated by this router. Assuming client 10.0.0.3 wants to speak to my webserver 87.118.88.39 , he sends a packet containing, among others, the following information:

Source:      10.0.0.3:39478
Destination: 87.118.88.39:80

So all machines on the way from 10.0.0.3 to 87.118.88.39 know whom to send the packet next. When this packet arrives at the NAT, the NAT will rewrite it. The NAT stores a table for all recent connections. Each entry consists of a client IP, client port and a local port on its public interface. For our example the table entry for this example might look like:

Source IPSource PortNAT IPNAT Port
10.0.0.33947888.66.88.661234

The resulting port on the NAT is arbitary, it’s just one free port.. Each packet arriving on port 1234 of the public interface of the NAT is forwarded to 10.0.0.3:39478 . Our rewritten packet 10.0.0.3->87.118.88.39 now contains the following informations:

Source:      88.66.88.66:1234
Destination: 87.118.88.39:80

and is send to the next node in the world wide web. Nobody out of 10.0.0.0/24 will ever know that there is a machine 10.0.0.3 requesting a website from 87.118.88.39 . The webserver on 87.118.88.39 will send it’s answer to the pretended source, 88.66.88.66:1234 , and the NAT will forward the traffic according to its table entry to 10.0.0.3 .

Why do NAT’s exists? The solely plausible reason seem to be the lack of IPv4 addresses. With a NAT an ISP just need to offer a single IP address for a huge bunch of clients. Hopefully this will change in times of IPv6!

Why does it seem to be impossible?

Since the private network 10.0.0.0/24 is not known by the outer world (it is simply not route-able in the Internet, see wikipedia), you cannot connect from outside 10.0.0.0/24 straight to 10.0.0.3 . The WWW will only see 88.66.88.66 as source for all the clients. That means all clients in 10.0.0.0/24 have the same public IP for each machine that is not in 10.0.0.0/24 . So how to access 10.0.0.3 ? Speaking to 88.66.88.66 will result in crap, you don’t know which port will be forwarded to whom!? If it is forwarded at all…

How is it nevertheless possible?

Method one...

…is not very nice, if you are looking for a real solution please skip this paragraph and continue with solutions two and three ;-) Since there is no entry in the NAT table that specifies an outside target, you can send packets from any location to 88.66.88.66:1234 and the NAT will forward them to 10.0.0.3:39478 (according to my example). So to create a path from outside to 10.0.0.3 ‘s SSH server you just need to send a packet from 10.0.0.3:22 to any server outside that informs you about the source IP and source port that was reported by the NAT (it’s the address that will be forwarded to the client). If you immediately connect to this address, and if a SSH server is listening on 10.0.0.3:22 , you should be able to establish a SSH session. Simple isn’t it ;-) To get this working you could try something like repeating the following commands frequently:

# stop SSH to free the port
/etc/init.d/ssh stop

# send a packet to somewhere that is configured to notify you about the NAT settings
# the foreign side should instantaneously close the connection
# so the netcat command doesn't block your script
netcat -p 22 binfalse.de 1337

# restart SSH to get ready for connections
/etc/init.d/ssh stop

Of course you can also install some iptables rules to rewrite the TCP packets. So you can send the packets from some other ports than 22 , iptables will rewrite them so the target machine (and the NAT) thinks they came from :22 . With this setup you don’t have to stop SSH, because you don’t need the free port… But just hack it your way ;-)

Method two...

…is much more comfortable. You can set up a reverse SSH tunnel! Again you need another machine outside the NAT, that has a SSH server running and will act as your gateway. Just connect to it from your local machine behind the NAT:

ssh -R 1337:localhost:22 you@your.server

That will open the port 1337 on your.server . All packets arriving at this port are transferred through the SSH tunnel to your home PC. Run something like screen or top on the server to always transfer packets (otherwise the connection will be closed after some time), with -o ServerAliveInterval=XXX you can adjust the threshold for closing the SSH connection. Surround it with a while loop and you’ll reestablish closed connections (network errors or something like that):

while [ 1 ]; do ssh -o ServerAliveInterval=60 -R 1337:localhost:22 you@your.server; done

By default the opened port is just bound to 127.0.0.1 (the servers loopback interface), so you can only send packets from the server itself (or need some more network hacking). To have this hack listening to 0.0.0.0 (all interfaces) add the following to your /etc/ssh/sshd_config on your.server :

GatewayPorts yes

and restart the daemon.

Method three...

…might be the most elegant. Set up a VPN! But that’s too much for now, request some explanations from 3dfxatwork, he’s your OpenVPN guy!, and take a look at Dirty NAT tricks to get a VPN to work with clients also numbered in the private address space

So you see, no hasty prejudices ;-)

2 applications for 1 port

One of my PC’s is covered behind a firewall and just one port is opened. I want to serve SSH and HTTPS, but as you know it’s not easy to get both listening on the same port, so what should I do?

Of course one possibility is to decide for the more important application and forget about the other. But there is another solution! But first of all let’s have a look at both protocols.

If you connect to a SSH server he immediately welcomes you with the running SSH-version, for example:

usr@srv % telnet binfalse.de 22
Trying 87.118.88.39...
Connected to binfalse.de.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.5p1 Debian-6

Here it is SSH-2.0-OpenSSH_5.5p1 Debian-6 . So your client connects and just waits for an answer from the server. In contrast The HTTP protocol doesn’t greet:

usr@srv % telnet binfalse.de 80
Trying 87.118.88.39...
Connected to binfalse.de.
Escape character is '^]'.

The server is programmed to just answer request. So if we ask for anything it will give some feedback:

usr@srv % telnet binfalse.de 80
Trying 87.118.88.39...
Connected to binfalse.de.
Escape character is '^]'.
GET / HTTP/1.1
host: binfalse.de

HTTP/1.1 200 OK
Date: Sun, 26 Jun 2011 15:17:00 GMT
Server: Apache
X-Pingback: /xmlrpc.php
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
[...]

You see, the web server responds with code 200 , indicating everything is fine.

These differences in both protocols can be used to set up a proxy. If the client starts to send something it seems to speak HTTP, otherwise the client seems to wait for some SSH greetings. Depending on the client behavior the proxy should forward the packets to the relevant application. There is a nice Perl module to implement this easily: Net::Proxy .

First of all both applications need to be configured to not use the open port. Without loss of generality let’s assume port 443 is opened by the firewall, SSH listens on it’s default port 22 and your webserver is configured to listen on 8080 . The following piece of code will split the requests:

#!/usr/bin/perl -w
###############################
#
#   Creating a dual proxy w Perl
#
#   written by Martin Scharm
#     see http://binfalse.de
#
###############################

use warnings;
use strict;
use Net::Proxy;

# for debugging set verbosity => dumping to stderr
# Net::Proxy->set_verbosity (1);

my $proxy = Net::Proxy->new (
	{
		in =>
		{
			# listen on 443
			type => 'dual', host => '0.0.0.0', port => 443,
			# if client asks for something direct to port 8080
			client_first => { type => 'tcp', port => 8080 },
			# if client waits for greetings direct to port 22
			server_first => { type => 'tcp', port => 22 },
			# wait for 2 seconds for questions by clients
			timeout => 2
		},
		# we don't use out...
		out => { type => 'dummy' }
	}
);

$proxy->register ();
Net::Proxy->mainloop ();

Some notes:

  • To listen on ports < 1024 you need to be root!
  • Debians need to install libnet-proxy-perl .
  • Some protocols that wait for the client: HTTP, HTTPS
  • Some protocols that greets the clients: SSH, POP3, IMAP, SMTP
Download: Perl: dual-proxy.pl (Please take a look at the man-page. Browse bugs and feature requests.)

Hallo VG WORT - hier Blogger

Ja, es ist Deutsch! Warum? Ich habe mich heute bei der Verwertungsgesellschaft WORT registriert ;-)

Was ist denn VG WORT?

Die VG WORT verwaltet die Tantiemen aus Zweitverwertungsrechten an Sprachwerken. Die Unternehmen, die Kopierer oder Drucker oder CD’s oder Ähnliches verkaufen, müssen einen gewissen Betrag an die VG WORT bezahlen. Die VG WORT sammelt das Geld und gibt es an Journalisten, Schriftsteller, Verleger etc. weiter. Publiziert also jemand etwas, das öffentlich zugänglich ist, kann er sich einen kleinen Beitrag von der VG WORT abholen. Das gilt natürlich nicht nur für große Arbeiten (Diplom, Dr. oder Journal-Beitrag), auch Blogger können mitmachen!

Wie geht das?

Als Blogger kann man für Texte mit mind. 1.800 Anschlägen eine Vergütung bekommen. Es gibt zwei Arten der Vergütung:

  • Teilnahme an der Sonderausschüttung
  • Vergütung basierend auf den Leserzahlen

Für die Sonderausschüttung gibt es sehr viel weniger Geld, sobald man Zugriff auf den Quelltext des Textes im Netz hat kann man auch nicht daran teilnehmen. So bleibt für uns Blogger nur die Vergütung basierend auf den Leserzahlen. Dazu bekommt man von der VG WORT sogenannte Zählmarken. Das sind nichts anderes als 1x1 Pixel, die man in seinen Artikel integriert. Ließt ein Besucher dann diesen Artikel, lädt er sich auch diese “Bild” vom Server der VG WORT und die zählen dann für diesen Beitrag eins hoch. So funktioniert übrigens auch der Facebook Like-Button: Wenn ihr den irgendwo seht könnt ihr davon ausgehen, dass Facebook weiß, dass ihr diese Seite besucht habt. Mir ist bewusst, dass ich damit die Privatsphäre meiner Leser einschränke, daher auch gleich die Lösung: Wenn ihr nicht wollt, dass die VG WORT euch trackt solltet ihr eurem Browser das Laden von Bildern verbieten, oder diverse Plugins so konfigurieren, dass sie die Bilder mit der URL http://vg\\d{2}.met.vgwort.de/.* blocken. Im Zweifel wisst ihr schon wie das läuft.

Wo gibt es das Geld?

Als Blogger muss man sich als erstes bei der VG WORT registrieren. Das kann man in der Oberfläche T.O.M. erledigen. Dann kommt ein wenig Bürokratie: Formulare ausfüllen, unterschreiben, abschicken… Ist dies erledigt, kann man sich diese Zählpixel bestellen, die kommen auch sofort per Mail. Gezählt wird immer vom 1. Januar bis zum 31. Dezember des selben Jahres. Im Folgejahr wird dann die Vergütung berechnet und man kann eine Auszahlung beantragen. Wenn das was ich so im Netz gelesen habe stimmt, gibt es für 1.500 Zugriffe 15 Euro, für 3.000 Besucher gibt es 20 Euro und sollten mehr als 10.000 Browser euren Artikel ausliefern gibt es 30 Euro. Die 10k werde ich wohl erst einmal nicht ins Auge fassen, 1500 Besucher sollte aber Möglich sein ;-)

Es werden im Übrigen nur Besucher aus Deutschland gezählt. Daher ist dieser Artikel auch auf Deutsch. Fragt mich nicht, wie die Leute festlegen ob ein Klick aus Deutschland kommt oder nicht, ich denke im Zweifel wird er nicht gezählt. Auch Pixel die in verschiedene Akregatoren wie den GoogleReader ausgeliefert werden zählen nicht. Daher wäre es nett wenn ihr auch hin und wieder einmal auf die Seite durch klickt.

All in all

Ich betrachte das als Experiment (dieses Jahr werde ich wohl nicht mehr als 20 Pixel verbauen) und erwarte keine größeren Einnahmen, aber wer weiß. Das Geld schüttet die VG WORT sowieso aus, warum soll ich also nicht auch die Hände aufhalten!? Wer sich seine Vergütung nicht abholt ist selbst Schuld ;-)

Result

Von den gelisteten Artikeln haben es 4 geschafft die Mindestbesucherzahl zu erreichen. Habe dafür von der VG WORT 40 € bekommen: Danke an alle Besucher :D Im Endeffekt hat sich das natürlich nicht wirklich rentiert, eher ein kleiner Bonus. Es war aber ein nettes Experiment, das mittlerweile auch schon beendet wurde. Alle Zählpixel wurden zugunsten der Privacy entfernt. Ihr dürft aber trotzdem fleißig weiter klicken!