All posts by #!/bin/blog

SSH firewall bypass roundup

So my SSH workflow has reached a turning point, where I’m going to clean up my ~/.ssh/config. Some entries had been used to leverage corporate firewall and proxy setups for accessing external SSH servers from internal networks. These are being archived here for the inevitable future reference.
I never use “trivial” chained SSH commands, but always want to bring up a ProxyCommand, so I have a transparent SSH session for full port, X11, dynamic and agent forwarding support.
ProxyCommand lines have been broken up for readability, but I don’t think this is supported in ~/.ssh/config and they will need to be joined again to work.
Scenario 1: The client has access to a server in a DMZ
The client has access to a server in an internet DMZ, which in turn can access the external server on the internet. Most Linux servers nowadays have Netcat installed, so this fairly trivial constellation works 95.4% of the time.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh host.dmz /usr/bin/nc -w 60 host.external 22

Scenario 2: As scenario 1, but the server in the DMZ doesn’t have Netcat
It may not have Netcat, but it surely has an ssh client, which we use to run an instance of sshd in inetd mode on the destination server. This will be our ProxyCommand.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh -A host.dmz ssh host.external /usr/sbin/sshd -i

Scenario 2½: Modern version of the Netcat scenario (Update)
Since OpenSSH 5.4, the ssh client has it’s own way of reproducing the Netcat behavior from scenario 1:

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand ssh -W host.external:22 host.dmz

Scenario 3: The client has access to a proxy server
The client has access to a proxy server, through which it will connect to an external SSH service running on Port 443 (because no proxy will usually allow connecting to port 22).

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand /usr/local/bin/corkscrew
   proxy.server 3128
   host.external 443
   ~/.corkscrew/authfile
# ~/.corkscrew/authfile
username:password

(Omit the authfile part, if the proxy does not require authentication.)
Scenario 4: The client has access to a very restrictive proxy server
This proxy server has authentication, knows it all, intercepts SSL sessions and checks for a minimum client version.

# ~/.ssh/config
Host host.external
ServerAliveInterval 10
ProxyCommand /usr/local/bin/proxytunnel
   -p proxy.server:3128
   -F ~/.proxytunnel.auth
   -r host.external:80
   -d 127.0.0.1:22
   -H "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0\nContent-Length: 0\nPragma: no-cache"
# ~/.proxytunnel.auth
proxy_user=username
proxy_passwd=password

What happens here:

  1. host.external has an apache web server running with forward proxying enabled.
  2. proxytunnel connects to the proxy specified with -r, via the corporate proxy specified with -p and uses it to connect to 127.0.0.1:22, on the forward-proxying apache.
  3. It sends a hand-crafted request header to the intrusive proxy, which mimics the expected client version.
  4. Mind you that although the connection is to a non-SSL service, it still is secure, because encryption is being brought in by SSH.
  5. What we have here is a hand-crafted exploit against the know-it-all proxy’s configuration. Your mileage may vary.

Super sensible discretion regarding the security of your internal network is advised. Don’t fuck up, don’t use this to bring in anything that will spoil the fun. Bypass all teh firewalls responsibly.

CentOS 7 on MD-RAID 1

Figuring this out took me quite a bit of time. In the end, I approached the starter of this hilariously useless CentOS mailing list thread, who assured me that indeed he had found a way to configure MD-RAID in the installer, and behold, here’s how to install CentOS 7 with glorious old-school software RAID.
In the “Installation Destination” screen, select the drives you want to install onto and “I will configure partitioning”. Then click “Done”:
20141025134323In the “Manual Partitioning” screen, let CentOS create the partitions automatically, or create your own partitioning layout. I will let CentOS create them automatically for this test. 20141025134926Apparently due to restrictions in the Installer, /boot is required, but can’t be on a logical volume, so it appears as primary partition /dev/sda1. The root and swap volumes are in a volume group named centos.
The centos volume group will need to be converted to RAID 1 first. Select the root volume and find the “Modify…” button next to the Volume Group selection drop-down. A window will open. In this window, make sure both drives are selected and select “RAID 1 (Redundancy)” from the “RAID Level” drop-down. Repeat this for all volumes in the centos volume group.  If you are using the automatic partition layout, note at this point, how, after this step, the file system sizes have been reduced to half their size.
20141025135637As the final step, select the /boot entry and use the “Device Type” drop-down to convert /boot to a “RAID” partition. A new menu will appear, with “RAID 1 (Redundancy)” pre-selected. The sda1 subscript below the /boot file system will change into the “boot” label once you click anywhere else in the list of file systems.
20141025140445Click “Done”, review the “Summary of Changes”, which should immediately make sense if you have ever configured MD-RAID, and the system will be ready for installation.

Overriding the Mozilla Thunderbird HELO hostname

I found that when connecting through a SOCKS proxy (e.g. SSH dynamic forward), Mozilla Thunderbird tends to leak its local hostname (including the domain of the place where you are at that moment) as a HELO/EHLO header to its SMTP submission server, who then writes it into the first Received-Header.
To avoid this, use about:config and create the following configuration key and value:

mail.smtpserver.default.hello_argument = some-pc

Or whatever hostname you prefer.
Reference: Mozillazine – Replace IP address with name in headers

What does the slash in crontab(5) actually do?

That’s a bit of a stupid question. Of course you know what the slash in crontab(5) does, everyone knows what it does.
I sure know what it does, because I’ve been a UNIX and Linux guy for almost 20 years.
Unfortunately, I actually didn’t until recently.
The manpage for crontab(5) says the following:
20141017150008
It’s clear to absolutely every reader that */5 * * * * in crontab means, run every 5 minutes. And this is the same for every proper divisor of 60, which there actually are a lot of: 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
However, */13 * * * * does not mean that the job will be run every 13 minutes. It means that within the range *, which implicitly means 0-59, the job will run every 13th minute: 0, 13, 26, 39, 52. Between the :52 and the :00 run will be only 8 minutes.
Up to here, things look like a simple modulo operation: if minute mod interval equals zero, run the job.
Now, let’s look at 9-59/10 * * * *. The range starts at 9, but unfortunately, our naive modulo calculation based on wall clock time fails. Just as described in the manpage, the job will run every 10th minute within the range. For the first time at :09, after which it will run at :19 and subsequently at :29, :39, :49 and :59 and then :09 again.
Let’s look at a job that is supposed to run every second day at 06:00 in the morning: 0 6 */2 * *. The implied range in */2 is 1-31, so the job will run on all odd days, which means that it will run on the 31st, directly followed by the 1st of the following month. The transitions from April, June, September and November to the following months will work as expected, while after all other months (February only in leap years), the run on the last day of the month will be directly followed by one on the next day.
The same applies for scheduled execution on every second weekday at 06:00: 0 6 * * */2. This will lead to execution on Sunday, Tuesday, Thursday, Saturday and then immediately Sunday again.
So, this is what the slash does: It runs the job every n steps within the range, which may be one of the default ranges 0-59, 0-23, 1-31, 1-11 or 0-7, but does not carry the remaining steps of the interval into the next pass of the range. The “every n steps” rule works well with minutes and hours, because they have many divisors, but will not work as expected in most cases that involve day-of-month or day-of-week schedules.
But we all knew this already, didn’t we?

Amazon AutoRip und die Wasserzeichen

Amazon hat ja heute angefangen, als CD gekaufte Alben im Rahmen des AutoRip-Service als MP3-Download anzubieten. Natürlich kommt da gleich wieder die Frage auf, ob “Wasserzeichen” im Spiel sind. Die Nutzungsbedingungen des Amazon Cloud-Player sagen dazu folgendes:

Einige Plattenfirmen verlangen von uns, Kennungen in die Metadaten einzufügen, die zu Musik von diesen Firmen gehören und die sie eindeutig als Musik, die Sie von uns erhalten haben, kennzeichnen (“eindeutige Kennung”). […] Diese eindeutigen Kennungen können Informationen enthalten, mit denen Sie als Inhaber […] identifiziert werden. Zum Beispiel können diese eindeutigen Kennungen eine Zufallszahl enthalten, die wir Ihrer Bestellung oder Ihrem Exemplar zuordnen, Datum und Zeit des Einkaufs, eine Anzeige, dass die Musik von Amazon heruntergeladen wurde, Codes, die das Album und den Song identifizieren (UPC und ISRC), die digitale Unterschrift von Amazon und eine Kennung, mit der sich feststellen lässt, ob das Audio modifiziert wurde, und eine Anzeige, ob die Musik im MP3-Shop erworben oder in den Cloud Player importiert wurde. Im Amazon MP3 Store verkaufte Songs, die diese eindeutigen Kennungen enthalten, sind auf der jeweiligen Produktseite gekennzeichnet. Diese eindeutigen Kennungen beeinträchtigen keinesfalls die Wiedergabequalität.

“Kennungen in die Metadaten einfügen” ist hier ein starker Hinweis darauf, dass keine steganographischen Wasserzeichen gemeint sind, die in der Musik selbst versteckt sind. Vielmehr legt diese Formulierung die Vermutung nahe, dass die Informationen über den Käufer in den MP3-Metadaten, den sogenannten ID3-Tags hinterlegt sind.
Wir erinnern uns in dem Zusammenhang an die Einführung DRM-freier AAC-Dateien durch Apple im Jahr 2007. Damals konnten wir bereits experimentell ermitteln, dass die Dateien zwar in den Metadaten mit Name und Mailadresse des Käufers getaggt sind, aber beim Brennen auf CD oder konvertieren in WAV identische Dateien entstehen. Damit konnte als erwiesen gelten, dass kein unsichtbares Wasserzeichen in der Datei enthalten war.
Um zu prüfen, wie das mit der Kennzeichnung heruntergeladener Dateien bei AutoRip funktioniert, habe ich mich erneut mit wildfremden Leuten aus dem Internet zusammengetan und in ungesetzlicher Weise ungeschützte MP3-Dateien zwecks Konvertierung in WAV ausgetauscht.
Schaut man sich die ID3-Tags eines AutoRip-MP3 an, sieht man folgende Tags, die zunächst keinen Hinweis auf den Käufer der Datei enthalten:

id3v1 tag info for 01 - Hört ihr die Signale.mp3:
Title  : H▒rt ihr die Signale            Artist: Deichkind
Album  : Arbeit nervt                    Year: 2008, Genre: Unknown (255)
Comment: Amazon.com Song ID: 20947135    Track: 1
id3v2 tag info for 01 - Hört ihr die Signale.mp3:
PRIV (Private frame):  (unimplemented)
TIT2 (Title/songname/content description): Hvrt ihr die Signale
TPE1 (Lead performer(s)/Soloist(s)): Deichkind
TALB (Album/Movie/Show title): Arbeit nervt
TCON (Content type): Dance & DJ (255)
TCOM (Composer): Sebastian Hackert
TPE3 (Conductor/performer refinement):
TRCK (Track number/Position in set): 1/14
TYER (Year): 2008
COMM (Comments): ()[eng]: Amazon.com Song ID: 209471352
TPE2 (Band/orchestra/accompaniment): Deichkind
TCOP (Copyright message): (C) 2008 Universal Music Domestic Rock/Urban, a division of Universal Music GmbH
TPOS (Part of a set): 1/1
APIC (Attached picture): ()[, 3]: image/jpeg, 244997 bytes

Die hier sichtbaren Informationen sind bei von anderen Kunden heruntergeladenen Dateien identisch. Der Aufmerksamkeit leicht entgehen kann jedoch das PRIV-Tag, das vom hier verwendeten Tool nicht decodiert werden kann. Schaut man in die MP3-Datei hinein, findet sich ein Stück XML:

<?xml version="1.0" encoding="UTF-8"?>
<uits:UITS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:uits="http://www.udirector.net/schemas/2009/uits/1.1">
<metadata>
<nonce>XXXXXXXXXXXXX</nonce>
<Distributor>Amazon.com</Distributor>
<Time>2010-05-XXXXXXXXXXXX</Time>
<ProductID type="UPC" completed="false">00602517860049</ProductID>
<AssetID type="ISRC">DEUM70806185</AssetID>
<TID version="1">XXXXXXXXXXXXX</TID>
<Media algorithm="SHA256">b10c5dc78e1d2228a2a435b8786f7cd73fe47f87230de75ee84250203d00a905</Media>
</metadata>
<signature algorithm="RSA2048" canonicalization="none" keyID="dd0af29b41cd7d6d82593caf1ba9eaa6b756383f">XXXXXXXXXXXXX</signature>
</uits:UITS>

Mit XXXXXXXXXXXXX habe ich hier die Stellen unkenntlich gemacht, die sich von Datei zu Datei unterscheiden. Dem UITS-Schema bin ich nicht weiter nachgegangen. Wer näheres wissen will, mag per Suchmaschine fündig werden.
Ärgerlich ist, dass hier sehr leicht, selbst von gut informierten Kunden, übersehen werden kann, dass eine Verknüpfung zum Kunden in der Datei eincodiert ist. Ganz im Gegensatz zu Apple, wo dem interessierten Kunden beinahe unmittelbar (iTunes -> Titel auswählen -> Kontextmenü -> Informationen) gezeigt wird, dass sein Name mit der Datei in Verbindung steht.
Positiv ist, dass die Konvertierung von MP3-Dateien aus verschiedenen Quellen in WAV zu binär identischen Dateien führt. Die mit unsichtbaren steganographischen Wasserzeichen versehene Datei bleibt damit weiter ein Schreckgespenst, das noch keiner gesehen hat. Meine eigenen diesbezüglichen Befürchtungen sind also nach wie vor nicht eingetreten, und selbst das Fraunhofer-Institut spricht heute vom “psychologischen Kopierschutz”.
Ein unsichtbares und unhörbares Wasserzeichen scheint bis heute nicht im großen Maßstab machbar zu sein. Es bleibt beim “psychologischen Kopierschutz”, oder, wie manche Leute das nennen, einer Deppenbremse.

[2013] app.net – Die spießige Sehnsucht nach Ruhe

Ich bin ja nicht der älteste, und so habe ich Anfang der 1990er Jahre als armer Schüler und Azubi noch CB-Funk gemacht. Da kaufte man sich Hardware, schraubte die Antenne aufs Haus- oder Autodach und konnte ohne jede Zugangsbeschränkung (die Anmeldepflicht beim Amt war bereits abgeschafft) in die Kommunikation mit anderen einsteigen. Vollkommen anonym übrigens, denn das Ausplaudern von Klarnamen war praktisch geächtet.
So etwa Anfang 1993 habe ich dann von einem Computerflohmarkt ein 2400-Baud-Modem mitgebracht. Ab da ging es ganz schön rund. Von heute betrachtet, ist es fast unvorstellbar, wie schnell sich die Dinge damals für mich weiterentwickelten und änderten.
Zu der Zeit hatte ich schon 10 Jahre in Zeitungen von diesen Mailboxen gelesen, aber jetzt konnte ich mich endlich selbst einwählen. Mein Zuhause waren bald das MausNet, und FidoNet, das damals eben gerade den großen Fido-Putsch hinter sich hatte und in Deutschland in zwei bis aufs Blut verfeindete Netze gespalten war. Das war eine ziemlich gesellige Zeit mit wirklich großen regelmäßigen Mailboxtreffen der beiden MausNet-Mailboxen aus Wiesbaden und der Mailbox aus dem Rhein-Lahn-Kreis, bei der ich FidoNet-Point war.
Nach dem Ende meiner Lehre hatte ich ein Einkommen und bald auch meine eigene FidoNet-Mailbox. Das müßte so Ende 1994 gewesen sein. Der Putsch wirkte noch nach. Es gab zahlungskräftige Mailboxbetreiber, die per Ferngespräch nachts das Routing in andere Länder abwickelten und von den in der Hierarchie unterhalb von ihnen angesiedelten Mailboxen wahlweise Anerkennung oder Geld forderten, eigentlich aber beides. Kürzlich habe ich auf meinem Fileserver die Digitalfotos von einem Treffen in Frankfurt-Bockenheim im Jahr 1995 wiedergefunden, wo es genau um dieses Thema ging.
Parallel hatte ich im Frühjahr 1995 mit Compuserve angefangen. Im “Compuserve Information Manager”, der proprietären Zugangssoftware, hatte man themenbezogene sogenannte “Foren” (etwa: “Deutschland” oder “Filme”), die aus einem Chatbereich, einem Messagebereich und einem Download-Bereich bestanden. In Compuserve herrschte Ruhe. Anders als im nervigen FidoNet gab keine Diskussionen darüber, wer Geber und Nehmer war, sondern alle bezahlten in einer Richtung ihre monatlichen und stündlichen Beiträge an Compuserve und ihre Telefongebühren an die Post.
Nachdem ich per Compuserve die ersten Schritte ins WWW gemacht hatte, tauchte die erste Reklame eines örtlichen ISP auf, bei dem ich Kunde wurde. Das Mailboxthema habe ich dann bald an den Nagel gehängt. Nach den Querelen der FidoNet-Zeit empfand ich es als Erleichterung, die Infrastruktur nicht mehr nach Gutsherrenart vom lokalen Netzfürsten zu bekommen, sondern einfach dafür zu bezahlen. Wie es weiterging, kann man sich ausrechnen: Noch 1995 die erste Homepage, 1996 die erste eigene Domain, bei meinem Arbeitgeber das Internetthema komplett betreut, 1997 selbständig mit meiner eigenen Firma.
Das Social Networking lief in dieser Zeit per Mailinglisten, IRC und Newsgroups. Wer einen Internetzugang hatte, konnte ohne jede Zugangsbeschränkung in die Kommunikation mit anderen einsteigen.
Als es Anfang der 2000er Jahre mit den Blogs losging, dachte ich ernsthaft, wir hätten es geschafft und hätten die öffentliche Meinung im Internet wirklich befreit. Die Grenzen von Mailboxen oder Uni-Rechnern waren gesprengt, jeder konnte frei sein Ding machen und seine Meinung veröffentlichen. Man hatte das Gefühl, richtig was bewegen zu können, aber die realistischeren Mitglieder der Szene wussten ehrlich gesagt immer, dass es außerhalb der “Bloggeria” eigentlich gar keine Anteilnahme an unseren großen Aufregern gab.
Und dann kamen Facebook und vor allem Twitter. Gerade Twitter, am Anfang noch aufgrund seines speziellen Funktionsumfangs belächelt, wurde zum Zentralorgan der engagierten Netzbewohner. Der CB-Funk des Netzes. Wer es schaffte, sich vor einen Rechner mit Internetzugang zu setzen, oder ein Smartphone in die Hand zu nehmen, hatte plötzlich ein weltweites Publikum und konnte ohne Zugangsbeschränkung in die Kommunikation mit anderen einsteigen. Als 2009 das Flugzeug im Hudson gewassert war, stammelte der Nachrichtensprecher in den deutschen Abendnachrichten noch, während die Bilder der geretteten Passagiere bereits seit einer halben Stunde per Twitter um die Welt gingen. Von 2010-2012 rollte eine Welle von Revolutionen  durch Nordafrika, auch getragen durch Twitter und Facebook. 2012 hat Twitter es geschafft, tausende für Occupy und gegen ACTA auf die Straße zu bringen.
Mahnende Stimmen wegen dieser kostenlosen Dienste hatte es schon länger gegeben: “Wenn ihr für das Produkt nichts bezahlt, seid ihr selbst das Produkt.” Ob das stimmt? Es fällt mir schwer, es abschließend zu beurteilen. Aber gerade in 2012 wurden mehrere vermeintlich seriösere, offenere und verteiltere Twitter-Alternativen mit ungeheuer großem Enthusiasmus angekündigt und frenetisch begrüßt, die anschließend in Rekordgeschwindigkeit vergessen wurden. Eine kam durch, und die war weder offen noch verteilt: Das kostenpflichtige app.net will eine vielfältig benutzbare Plattform sein, und kein reiner Dienst fürs Microblogging. Für 3 US-Dollar im Monat schmorten ein halbes Jahr lang die ausgewiesensten Spezialisten für Social Networking im exklusiven eigenen Saft.
Dass app.net mit diesem reinen Bezahlsystem lebensunfähig geboren war, wurde nur von wenigen erkannt, jedoch immerhin von app.net selbst. Und so wurden die Tore Anfang 2013 geöffnet und es durften auch nicht-zahlende Benutzer mitspielen, jedoch nicht ohne Zugangsbeschränkungen, sondern zu bestimmten Bedingungen, die die Möglichkeiten zur Kommunikation mit anderen reglementieren. Das war der Tag, an dem app.net für mich interessant wurde und ich meine 36 US-Dollar für 12 Monate bezahlt habe, um mir die Sache anzuschauen. Gleich nach dem ersten Anmelden war erkennbar, dass diese Freigabe für reichlich Aufruhr bei den zahlenden Usern der ersten Stunde sorgte. Viele waren sichtlich nicht begeistert waren vom Anblick der einfallenden Usermengen. Der Untergang der Diskussionskultur und eine Welle an Fernseh- und Fussballtweets wurden herbeibeschworen.
Viele halten app.net für das nächste große “Ding”, das die Netzwerkkommunikation revolutionieren wird. Ich melde Zweifel an. Und ich habe die Geduld in dem Moment verloren, als ich einen Chat-Dienst auf Basis von app.net gesehen habe. Hier gibt es in der Außenwelt Protokolle wie XMPP und IRC, die bereits für Millionen von Nutzern etabliert sind – teils seit Jahrzehnten – und deren Benutzung jedermann offensteht. Die hier erkennbare Tendenz, sich nach der totalen Offenheit von Twitter in ein geschlossenes Netzwerk zurückziehen zu wollen, um den Anblick des Pöbels nicht mehr ertragen zu müssen, erschreckt mich. App.net ist für mich ein Rückschritt um 20 Jahre, in die abgeriegelte Umgebung von Compuserve. Aus Angst vor der Kränkung, vermeintlich das Produkt zu sein, verkriechen sich vermeintlich erleuchtete Experten in einen kostenpflichtigen privaten Zirkel.
Bereits heute klafft die Schere weit auseinander: Auf Twitter werden Menschenrechtsdemos organisiert, während sich auf dem intellektuell ausgebluteten Facebook schonmal Lynchmobs bilden. Als die erfahrensten Netznutzer müssen wir das verstehen, handeln und Verantwortung übernehmen. Die freie Kommunikation für jedermann muss geschützt werden.
Wie sollen sich ein Schüler aus einfachen Verhältnissen, ein arbeitsloser junger Mensch oder ein Rentner am Rand des Existenzminimums gut vernetzen, wenn alles, wo sie gehört werden würden, app.net mit seinen rigiden Limits für kostenlose User ist? Welcher Sache ist gedient, wenn sich eine selbsternannte netzintellektuelle Oberschicht in ihrem Club einsperrt, vom dem aus die normalen Menschen nicht mehr sichtbar sind? Und selbst wenn kostenlose User mit viel mehr Möglichkeiten ausgestattet werden: Was, wenn ein solcher Bezahlservice pleite geht, oder wir ihm aufgrund der Rechtslage in seinem Land nicht mehr vertrauen können? Ein “Fork” wie er zur Zeit des unseligen Fido-Putsch möglich war, wird dann undenkbar sein.
Jedermann sollte ohne Zugangsbeschränkung mit anderen kommunizieren können. Freie Software für verteilte soziale Netze ist seit Jahren verfügbar und wird aktiv entwickelt. Der Weg zurück in die Steinzeit der sozial undurchlässigen bezahlten Datennetze ist der falsche.

FTPS vs. SFTP, once and for all.

I had to provide an explanation about the differences between FTPS and SFTP today, which sound so similar, but are in reality extremely different and can easily confused by those who don’t spend lots of quality time with them.

SFTP (“SSH FTP”) is based on SSH (Secure Shell) version 2. It uses the same communication channels and encryption mechanisms as SSH.

FTPS (“FTP over SSL”) is based on the the legacy FTP protocol, with an additional SSL/TLS encryption layer. There are several implementations of FTPS, including those with “implicit SSL” where a distinct service listens for encrypted connections, and “explicit SSL” where the connection runs over the same service and is switched to an encrypted connection by a protocol option. In addition, there are several potential combinations of what parts of an FTPS connection are actually being encrypted, such as “only encrypted login” or “encrypted login and data transfer”.

FTPS uses the same communication channels as legacy unencrypted FTP, including dynamically negiotiated side-band connections. Due to these side-band connections, FTP has always been problematic with firewalls. The encryption layer further exacerbates these issues.

Due to this rather long list of ins-and-outs, FTPS can be considered an exotic protocol, while SFTP has widespread acceptance due to the omnipresence of SSH servers on all Linux or UNIX servers.

The only objective advantage of FTPS is that FTPS uses an SSL certificate that is signed by a trusted third party and can be used in an opportunistic way, similar to HTTPS encryption in web browsers. However, if password authentication is not enough and mutual authentication using X.509 client certificates comes into play, this advantage loses part of its validity, because mutual authentication nearly always requires manual intervention from both sides.

Wired, Juli 1997: The Long Boom

Beim Umziehen und Aufräumen fielen mir die Ordner mit archivierten Zeitschriften in die Hand. Zentnerweise Altpapier habe ich weggeschmissen. Ich wusste aber, dass sich irgendwo ein ganz besonderes Schätzchen verstecken müßte. Und tatsächlich:
thelongboom
Wir hatten 1997 ja nichts. Es gab kein Slashdot, kein Digg, keine Blogs, kein Twitter, keine Wikipedia. Na gut, wir hatten das Usenet. Google gab es übrigens auch noch nicht. Aber für den echt allerheißesten und visionären Shice gab es das Leitmedium WIRED. Erhältlich als Import am Bahnhofskiosk für 17 Deutsche Mark.

Im Juli 1997 werden in WIRED sensationelle technische Neuerungen beworben, wie z.B. der Apple Powermac 9600/200MP mit 2x200MHz. Auf vielen Werbebildern (und die gab es in WIRED wirklich im Überfluss) sieht man Röhrenmonitore, bei denen man sich fragen muss, wie die Statik gängiger Wohnungen das jemals ausgehalten haben kann.

WIRED stand auf jeden Fall an der Speerspitze so einer Art digitaler Revolution. Und WIRED sagte damals im Essay “The Long Boom” eine digitale Revolution voraus, die der Menschheit über Jahrzehnte Freiheit, Frieden und Wohlstand bringen würde.

Der Boom fällt aus. Das wissen wir hier in der “zivilisierten” Welt, und das wissen auch die ganzen armen Schweine in der dritten Welt, die heute so wenig zu beißen haben, wie vor 12 Jahren. Aber es kann ja auch sein, dass die ganzen Afrikaner eh nicht gemeint waren, als von “a better environment for the whole world” die Rede war. Davon, dass für jedes neue Gadget, das man sich kauft, ein Gorillababy abgemurkst wird, will ja auch keiner was wissen.

Auch WIRED wusste natürlich, dass möglicherweise doch nicht alles nach Plan laufen könnte und so wurden gleich “10 Scenario Spoilers” umrissen, die so genau den Nagel auf den Kopf treffen sollten, dass es heute schon fast erschreckend wirkt. Ich zähle mal nur die auf, die eingetreten sind:

2.
New technologies turn out to be a bust. They simply don’t bring the expected productivity increases or the big economic boosts.
3.
Russia devolves into a kleptocracy run by a mafia or retreats into quasicommunist nationalism that threatens europe.
6.
Major rise in crime and terrorism forces the world to pull back in fear. People who constantly feel they could be blown up or ripped off are not in the mood to reach out and open up.
8.
Energy prices go through the roof. Convulsions in the Middle East disrupt the oil supply, and alternative energy sources fail to materialize.
10.
A social and cultural backlash stops progress dead in its tracks. Human beings need to choose to move forward. They just may not…

Die Vorhersage über den “Long Boom” ist nicht eingetreten, aber die “Scenario Spoilers” haben den Nagel wirklich auf den Kopf getroffen. Herzlichen Glückwunsch dazu. 🙁

OpenSSH connection multiplexing

The Challenge
I was in touch with a developer the other day who used SSH to programmatically connect to a remote machine where he would start some kind of processing job. Unfortunately, he was in trouble when he wanted to kill the remote process. Killing the local SSH client would leave his job active. He claimed that there used to be some sort of signal forwarding feature in OpenSSH on the machine where he had developed his application in OpenSSH 3.x days, but this feature seems to have been removed by now.
I wasn’t able to confirm anything of this, but this gentleman’s problem got me curious. I started to wonder: Is there some kind of sideband connection that I might use in SSH to interact with a program that is running on a remote machine?
The first thing I thought of were port forwards. These might actually be used to maintain a control channel to a running process on the other side. On the other hand, sockets aren’t trivial to implement for a /bin/ksh type of guy, such as the one I was dealing with. Also, this approach just won’t scale. Coordination of local and remote ports is bound to turn into a bureaucratic nightmare.
I then started to skim the SSH man pages for anything that looked like a “sideband”, “session control” or “signaling” feature. What I found, were the options ControlMaster and ControlPath. These configure connection multiplexing in SSH.
Proof Of Concept
Manual one-shot multiplexing can be demonstrated using the -M and -S options:
1) The first connection to the remote machine is opened in Master mode (-M). A UNIX socket is specified using the -S option. This socket enables the connection to be shared with other SSH clients:

localhost$ ssh -M -S ~/.ssh/controlmaster.test.socket remotehost


2) A second SSH session is attached to the running session. The socket that was opened before is specified with the -S option. The remote shell opens without further authentication:

localhost$ ssh -S ~/.ssh/controlmaster.test.socket remotehost


The interesting thing about this is that we now have two login sessions running on the remote machine, who are children of the same sshd process:

remotehost$ pstree -p $PPID
sshd(4228)─┬─bash(4229)
           └─bash(4252)───pstree(4280)


What About The Original Challenge?
Well, he can start his transaction by connecting to the remote machine in Master mode. For simplicity’s sake, let’s say he starts top in one session and wants to be able to kill it from another session:

localhost$ ssh -t -M -S ~/.ssh/controlmaster.mytopsession.socket remotehost top


Now he can pick up the socket and find out the PIDs of all other processes running behind the same SSH connection:

localhost$ ssh -S ~/.ssh/controlmaster.mytopsession.socket remotehost 'ps --ppid=$PPID | grep -v $$'
  PID TTY          TIME CMD
 4390 pts/0    00:00:00 top


This, of course, leads to:

localhost$ ssh -S ~/.ssh/controlmaster.mytopsession.socket remotehost 'ps --no-headers -o pid --ppid=$PPID | grep -v $$ | xargs kill'


Then again, our shell jockey could just use PID or touch files. I think this is what he’s doing now anyway.
Going Fast And Flexible With Multiplexed Connections
With my new developer friend’s troubles out of the way, what else could be done with multiplexed connections? The SSH docs introduce “opportunistic session sharing”, which I believe might actually be quite useful for me.
It is possible to prime all SSH connections with a socket in ~/.ssh/config. If the socket is available, the actual connection attempt is bypassed and the ssh client hitches a ride on a multiplexed connection. In order for the socket to be unique per multiplexed connection, it should be assigned a unique name through the tokens %r (remote user), %h (remote host) and %p (destination port):

ControlPath ~/.ssh/controlmaster.socket.%r.%h.%p
# Will create socket as e.g.: ~/.ssh/controlmaster.socket.root.remotehost.example.com.22


If there is no socket available, SSH connects directly to the remote host. In this case, it is possible to automatically pull up a socket for subsequent connections using the following option in ~/.ssh/config:

ControlMaster auto


So Where’s The Actual Benefit?
I use a lot of complex proxied SSH connections who take ages to come up. However, connecting through an already established connection goes amazingly fast:

# Without multiplexing:
localhost$ time ssh remotehost /bin/true
real    0m1.376s
...
# With an already established shared connection:
localhost$ time ssh remotehost /bin/true
real    0m0.129s
...


I will definitely give this a try for a while, to see if it is usable for my daily tasks.
Update, 2009/05/04: No, it isn’t. Disconnecting slave sessions upon logout of the master session are too much of a nuisance for me.

Using the SSH agent from daemon processes

One of my more recent installations, the BackupPC server I wrote about earlier, needs full access as the user root to his clients in order to retrieve the backups. Here’s how I implemented authentication on this machine.
BackupPC runs as its own designated user, backuppc. All authentication procedures therefore happen in the context of this user.
The key component in ssh-agent operation is a Unix domain socket that the ssh client uses to communicate with the agent. The default naming scheme for this socket is /tmp/ssh-XXXXXXXXXX/agent.<ppid>. The name of the socket is stored in the environment variable SSH_AUTH_SOCK. The windowing environments on our local workstations usually run as child processes of ssh-agent. They inherit this environment variable from their parent process (the agent) and therefore the shells running inside our Xterms know how to communicate with it.
In the case of a background server using the agent, however, things are happening in parallel: On one hand, we have the daemon which is being started on bootup. On the other hand, we have the user which the daemon is running as, who needs to interactively add his SSH identity to the agent. Therefore, the concept of an automatically generated socket path is not applicable and it would be preferable to harmonize everything to a common path, such as ~/.ssh/agent.socket.
Fortunately, all components in the SSH authentication system allow for this kind of harmonization.
The option -a to the SSH agent allows us to set the path for the UNIX domain socket. This is what this small script, /usr/local/bin/ssh-agent-wrapper.sh does on my backup server:

#!/bin/bash
SOCKET=~/.ssh/agent.socket
ENV=~/.ssh/agent.env
ssh-agent -a $SOCKET > $ENV


When being started in stand-alone mode (without a child process that it should control), ssh-agent outputs some information that can be sourced from other scripts:

SSH_AUTH_SOCK=/var/lib/backuppc/.ssh/agent.socket; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1234; export SSH_AGENT_PID;
echo Agent pid 1234;


This file may sourced from the daemon user’s ~/.bash_profile:

test -s .ssh/agent.env && . .ssh/agent.env


However, this creates a condition where we can’t bootstrap the whole process for the first time. So it might be somewhat cleaner to just set SSH_AUTH_SOCK to a fixed value:

export SSH_AUTH_SOCK=~/.ssh/agent.socket


Here’s the workflow for initializing the SSH agent for my backuppc user after bootup:

root@foo:~ # su - backuppc
backuppc@foo:~ $ ssh-agent-wrapper.sh
backuppc@foo:~ $ ssh-add


In the meantime, what is happening to the backuppc daemon?
In /etc/init.d/backuppc, I have added the following line somewhere near the top of the script:

export SSH_AUTH_SOCK=~backuppc/.ssh/agent.socket


This means that immediately after boot-up, the daemon will be unable to log on to other systems, as long as ssh-agent has not been initialized using ssh-agent-wrapper.sh. After starting ssh-agent and adding the identity, the daemon will be able to authenticate. This also means that tasks in the daemon that do not rely on SSH access (in the case of BackupPC, things like housekeeping and smbclient backups of “Windows” systems) will already be in full operation.