Wir fahren nach Berlin! Vom Leiden einer Reisebuchung am ersten April.

Es ist BCIX Stammtisch und ich darf dabei sein. Hurra!

Anreise

Dazu muss eine Reise gebucht werden und schon kommt das erste Problem auf: Ich kann auf dem Bahn-Portal nicht bezahlen. Die Zahlung per Kreditkarte wird abgelehnt.

Anruf beim Support: "Das ist zu Ihrer Sicherheit! Sie haben schon so oft mit Kreditkarte Bahnfahrkarten gekauft, das könnte auch ein Betrüger sein, also ist das nun gesperrt. Gegen Sie zum Schalter!"

Genau genommen funktioniert mit der Commzerbank das 3D Secure Verfahren nie, weswegen jeder, der ein Konto dort hat es ausschaltet. Nun besteht die Bahn spontan auf der Einhaltung des Verfahren, auch wenn die Bank es direkt als unnötig ablehnt. Die Bahn kann mit der Ablehnung aber nicht umgehen und die Buchung scheitert.

Was auch nicht geht, ist ein Umstellung auf Lastschrift. Nicht, weil der Prozess per Post und Papier abläuft, sondern weil er aus Sicherheitsgründen seitens der Bahn abgebrochen wird. Es gab ja eben erst eine fehlgeschlagene Kreditkartenbuchung.

Auf eine öffentliche Beschwerde hin, antwortet die Bahn:

Aktuell sind verstärkt betrügerische Aktivitäten basierend auf sogenannten Phishing-E-Mails zu verzeichnen. Als eine vorsorgliche Maßnahme zum Schutz unserer Kunden können deshalb Sparpreis-Tickets auf bahn.de und im DB Navigator bis auf Weiteres nur

  • per "Sofort." (SOFORT Überweisung) und
  • Kreditkarte unter Abfrage des 3D-Secure-Passwortes

bezahlt werden. Dafür bitten wir um Verständnis.

https://www.bahn.de/p/view/home/info/sonderkommunikation-phishing.shtml

Der Betrüger darf also den teuren Flexpreis gern zu meinen Lasten in Anspruch nehmen, nicht aber die Sparpreise. Super, Deutsche Bahn!

Und nein, ich werde meine Online-Banking-Daten nicht irgendeinem fremden Unternehmen in die Hände drücken. Das fällt aus.

Übernachtung

Und nun zu Teil zwei: Ich brauch ein Hotel, weil nach der Veranstaltung nichts mehr nach Hause fährt.

Bei Booking alles soweit kein Problem, nur gibt's keinen Ausdruck der Buchung mehr direkt auf die Hand. Das neue Verfahren generiert das PDF offenbar aus einem C64-Font heraus:

2019-04-01-150217_1278x1022_scrot

Echt retro.

Eine unglückliche Platzierung eines Datenschutzlinks wird unfreiwillig komisch, wenn dann Fehler auftreten.

Bildschirmfoto vom 2019-02-26 10.18.10

Genau. Kein Kamerabild, weil ... ganz unten "Powered by Datenschutz" steht.

Eigentlich ist es ganz anders.

Im Rahmen der DSGVO wurde der Webseite ein Footer mit einem Datenschutzlink verpasst. Allerdings beißt sich das mit dem bisherigen Design, bei dem die Sponsoren als "Powered by" aufgeführt sind.

Als dann die Kamera kein Bild liefern konnte, entstand dieser Schnappschuß-.

A customer complained about network problems. An SMB/CIFS mount would always break down between two of his servers. Not that there were any noticeable problems, but there are still some error messages in the log.

Setup

The customer has a certain number of servers in his Layer2 segment. One of them is a Windows file server for a group of Windows computers. Another is the Linux monitoring system, which regularly tries to access the share.

The whole thing has a longer history, which led half a year ago to the recommendation to abandon SMB1. This part is not relevant, it is what followed the recommendation.
Since the transition, the monitoring Linux has had strange entries in the kernel log:

Feb 12 19:07:02 kernel: CIFS VFS: Server a.b.c.d has not responded in 120 seconds. Reconnecting...

Where do these 120 seconds come from? The man page does help:

echo_interval=n

sets the interval at which echo requests are sent to the server on an idling
connection. This setting also affects the time required for a connection to
an unresponsive server to timeout. Here n is the echo interval in seconds.
The reconnection happens at twice the value of the echo_interval set for
an unresponsive server. If this option is not given then the default value of
60 seconds is used.

That explains the 120 seconds: Every minute an SMB echo is sent and if no echo is answered twice, the connection is believed to be dead. Therefore, the customer (understandably) thinks that there would be packet loss in the network.

To prove this assumption wrong takes weeks. For this purpose, the data traffic is recorded on both sides and put next to each other packet by packet.

Unfortunately, this still doesn't solve the real problem.

Analysis

Again and again such a recording is examined, in order to discover any unusual phenomenon.

smb-tcp-flow

It's awesome to see each minute the keep-alive request-response game is happening. Then data is sent.

The communication comes to a sudden pause and the time-out stated in the log occurs. Between 19:05:01.99... and 19:07:02.25... there are a little more than 120 seconds. So far that seems to fit.

The transmission error (the one with the TCP keep-alive) is remarkable, because it hits the server directly before the connection is terminated. This must be investigated!

Why are the lines black? Because the keep-alive sends exactly one byte over again, which has been acked for a long time. It is a very unusual conversation. Wireshark colours such sequence errors in black.

  • At 19:05:01.949511 128 bytes are received.
  • At 19:05:01.997203 the reception of these 128 bytes is confirmed.
  • At 19:07:01.999481 the final of the 128 bytes is transmitted again (together with the keep-alive flag).

If the acknowledgement of the data reception (ACK) had not arrived, the entire 128 bytes would be sent again. But they are not.

Did a firewall gamble on the sequence numbers underway? But there is no firewall in between, both servers are in the same LAN and see each other directly. But the other side verifies that the acknowledgement has arrived completely.

So why should the kernel resend a single byte? It turns out that the Windows implementation of the TCP keepalive sends exactly one byte again, while the Linux implementation sends the keepalive without payload. This is apparently an adjustment of Windows to broken middleware, which drops TCP packets without payload.

So the part is fine. But what is it then?

Maybe there are some delays somewhere? So let's take a look at the round-trip times. Maybe there are outliers.

smb-tcp-rtt

There are no particular irregularities with the remote location. Everything looks nice.

smb-tcp-rtt2

Even the local processing is completely inconspicuous: Everything that the kernel can process directly is done in almost no time. If the application software is involved, it takes longer. One can see very clearly how regular the measurements are.

Nothing is striking here either. But what is it then?

A closer look reveals that an echo request should have been sent at 19:06:00. But that is missing!

Kernel Archaeology

The function cifs_echo_request is responsible for sending the echo requests in the Linux kernel. There it says:

static void
cifs_echo_request(struct work_struct *work)
{
 int rc;
 struct TCP_Server_Info *server = container_of(work,
     struct TCP_Server_Info, echo.work);
 unsigned long echo_interval;

 /*
  * If we need to renegotiate, set echo interval to zero to
  * immediately call echo service where we can renegotiate.
  */
 if (server->tcpStatus == CifsNeedNegotiate)
  echo_interval = 0;
 else
  echo_interval = server->echo_interval;

 /*
  * We cannot send an echo if it is disabled.
  * Also, no need to ping if we got a response recently.
  */

 if (server->tcpStatus == CifsNeedReconnect ||
     server->tcpStatus == CifsExiting ||
     server->tcpStatus == CifsNew ||
     (server->ops->can_echo && !server->ops->can_echo(server)) ||
     time_before(jiffies, server->lstrp + echo_interval - HZ))
  goto requeue_echo;

 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
 if (rc)
  cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
    server->hostname);

requeue_echo:
 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
}

The code is interesting in several ways:

  • On the one hand, an echo is sent only if there exists a real need to do so.
  • On the other hand, this is a daisy chain scheduling: Only after work has been done the next action is planned.

As far as the needs are concerned, no echoes are sent out as long as the last response was received earlier than one echo interval.

But what is a response? In the code, the server→lstrp is always set to the current time whenever a packet is received. Regardless wether it is an echo response or normal data.

Subtracting HZ (one second) is a countermeasure preventing the echo response to your own request from being interpreted as interesting traffic. So this hard-coded value is calculated assuming that the answer from the remote station comes always more quickly than in a second.

If such an SMB connection runs over a longer distance or against a slower server, every second echo request will be suppressed if no further traffic occurs. This directly leads to the fact that SMB only works in the LAN.

Due to the protocol architecture, all requests are processed sequentially. If an echo request is sent while another request is running on the server, the echo request will not be processed until the previous request has been completed. Asynchronous processing was abandoned with the transition from SMB1 to SMB2. Now the server should tell the client that a more complex request is still being processed.

In this case an answer was received at 19:05:01.91... from the server. The echo packet should have been sent around 19:06:00. That's a very precise mistake!

The second problem is the scheduling. Only when all the work has been done (sending the echo packet) the next echo is scheduled to be sent 60 seconds later. The entire processing time is missing from the planning. This means that the echo packets are not sent exactly after 60 seconds, but always a bit later.

The recording shows this very clearly: 19:01:55.05, 19:02:56.49, 19:03:57.94, 19:04:59.37, 19:06:00.90, 19:07:02.27. The intervals are about 61.5 seconds. So 1.5 seconds more than planned. In the last step the interval is shorter, because the echo packet was not sent.

Racecondition

But what really happens is explained quickly: Suppressing the planned echo request is faulty.

In detail:

smb-tcp-timing
  • Daisy chaining scheduling creates a gap.
  • If traffic comes unfortunate shortly after the last echo, the planned echo is suppressed.
  • Due to the gap, the next echo transmission is delayed until after the timeout, which is set hard to twice the echo interval.

It is particularly charming to realize that the final echo request is first sent and then the time-out strikes, because the first action when receiving the echo response is to check for a time-out and terminate it. Ironically, the successful echo triggered the abort.

Now the question arises since when the problem occurred and who is responsible for it:

  • The patch c740 will send permanently echo requests every 60 seconds if no other traffic occurred. (Jan 11, 2011)
  • The patch fda3 all these echoes are used to trigger a timeout at five times the interval (configurable) without traffic. (Jan 20, 2011)
  • The patch 6dae switches from the configurable 60s x variable(5) to variable(60s) x two. (Feb 21, 2012)

The gap and suppression was introduced on 11 January 2011. However, this has no effect, as the time-out starts at five times the interval.

With the changeover on 21 February 2012, the gap now takes effect, as the time-out was set hard to twice the interval.

Solutions

There are three options.

First, eliminate the gap by scheduling at fixed times (always add 60 seconds to the last schedule time). By the way, it is not enough to move the rescheduling to the beginning of the routine. This only shortens the gap, but it will not disappear.

Another possibility is to send the echo requests in any case regardless of other traffic. In other words, if traffic is already running, the additional request will not bother any more. There is a potential risk that a server will choke on an echo between other requests.

Furthermore, avoiding the entire problem by waiting at least three times the interval length seems plausible.

If you want a quick fix, you should choose the third approach: Change a 2 to a 3 in the code:

static bool
server_unresponsive(struct TCP_Server_Info *server)
{
 /*
  * We need to wait 2 echo intervals to make sure we handle such
  * situations right:
  * 1s  client sends a normal SMB request
  * 2s  client gets a response
  * 30s echo workqueue job pops, and decides we got a response recently
  *     and don't need to send another
  * ...
  * 65s kernel_recvmsg times out, and we see that we haven't gotten
  *     a response in >60s.
  */
 if ((server->tcpStatus == CifsGood ||
     server->tcpStatus == CifsNeedNegotiate) &&
     time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
  cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
    server->hostname, (2 * server->echo_interval) / HZ);
  cifs_reconnect(server);
  wake_up(&server->response_q);
  return true;
 }

 return false;
}

All that remains is the question of the TCP keepalive. Windows will wait exactly 120s until it sends a keepalive on a TCP session. Note that the Windows server sends the TCP keepalive first, because it transmitted the last packet before it arrived at Linux.

Acknowledgement

The entire analysis was done by my colleague Jens, who just asked me to write things together. This is what I did here.

The only thing left to do now is to send a bug report to the right place.

Microsoft stellt einen eigenen BGP Router für Windows bereit. Wir benötigen an einer Stelle, wo bisher nur ein paar Hyper-V fähige Kisten stehen einen unabhängigen Internetzugang. Was liegt also näher als alles aus einer Hand zu bauen?

Installation

Auf eine Windows VM kommt aus der RAS Rolle das Feature LAN Routing zum Einsatz. Damit kann die VM zwischen Interfaces routen.

Als nächstes wird die BGP Rolle installiert. Auch das ist problemlos, die benötigten Abhängigkeiten sind gleich dabei.

Alle folgenden Schritte benötigen die Powershell, was dem geneigten Admin sehr entgegen kommt. Zuerst also einen neuen BGP Router definieren.

PS> Add-BgpRouter -BgpIdentifier <IPAddress> -LocalASN <UInt32>

Man gibt also seine lokales AS Nummer an (zum experimentieren gibt private Nummern) und eine eindeutige IP Adresse, unter der der Router arbeiten wird. Am besten die IP eines Interfaces. Erfreulich ist die Verwendung eines UInt32, der auf die Unterstützung von 4-Byte ASNs hinweist.

Als nächstes kommt dann die Einrichtung eines BGP Peers, also eines Nachbar mit dem diese Maschine reden soll.

PS> Add-BgpPeer [-Name] <String> -LocalIPAddress <IPAddress> -PeerASN <UInt32> -PeerIPAddress <IPAddress>

Der Peer bekommt einen sprechenden Namen unter dem er später erscheinen soll. Des weiteren wird die AS-Nummer des Peers benötigt. Wenn diese die gleiche ist, wie die eigene, handelt es ich um ein i(nternal)BGP, sonst um ein e(xternal)BGP Peer.

Die Kommunikation erfolgt zwischen zwei IP Adressen, die auf beiden Seiten übereinstimmen müssen. I.d.R. werden da IP Adressen genommen, die sich im gleichen Netz befinden und direkt miteinander reden können. Die meisten eBGP Peers erwarten das. bei iBGP ist eine durchaus längere Routingstrecke zwischen den Peers nichts ungewöhnliches.

Cisco als Gegenstelle

Zum Test lasse ich den Server gegen einen normalen Cisco Router arbeiten.

router bgp 15725
 neighbor <WindowsIP> remote-as 65432
 address-family ipv4
  neighbor <WindowsIP> activate
  neighbor <WindowsIP> soft-reconfiguration inbound
  neighbor <WindowsIP> prefix-list from_windows in
  neighbor <WindowsIP> prefix-list to_windows out
 exit-address-family
!
ip prefix-list from_windows seq 5 deny 0.0.0.0/0 le 32
ip prefix-list to_windows seq 1 permit 185.98.236.0/22
ip prefix-list to_windows seq 5 deny 0.0.0.0/0 le 32

Für den Anfang gebe ich nur eine Route raus und nehme nichts an. Sicher ist sicher.

Die BGP Session kommt hoch und das Windows lernt eine Route!

Mit Get-BgpPeer und Get-BgpRouteInformation kann man sich die Ergebnisse ansehen. Die Route taucht sogar in der normalen Routing Tabelle auf.

Auffällig ist aber, dass die Cisco etwas seltsames anzeigt:

  Neighbor capabilities:
    Route refresh: advertised and received(new)
    Four-octets ASN Capability: advertised
    Address family IPv4 Unicast: advertised and received
    Graceful Restart Capability: advertised
    Enhanced Refresh Capability: advertised

Irgendwie fehlt da die 4-Byte ASN Funktionalität. Gleich mal ausprobieren.

PS> Add-BgpPeer test4byte -LocalIPAddress <IPAddress> -PeerASN 199932 -PeerIPAddress <IPAddress>
windows bgp 4byte asn

Oops. Das ist ein KO-Kriterium. Eigentlich müsste ich hier sofort aufhören zu evaluieren.

Full Table

Aber probieren wir mal was anderes. Was tut die Kiste, wenn sie der vollen Internet-Routingtabelle ausgesetzt wird?

(config)#ip prefix-list to_windows seq 2 perm 0.0.0.0/0 le 24

Die CPUs gehen auf Anschlag und bleiben dort eine ganze Weile. Trotzdem bleibt das System benutzbar. Der RAM Bedarf steigt um zwei GByte, was ziemlich okay ist.

Anschließend sind alle Kerne mit ca 50% CPU belastet ohne dass irgendeine Aktivität von außen rein kommt. Seltsam.

Ein Blick in die BGP Routingtabelle mit Get-BgpRouteInformation zeigt, dass alle knapp 750.000 Routen angekommen sind. Allerdings braucht die Maschine unter CPU Volllast für die Ausgabe geschlagene drei Minuten.

Die Überraschung gibt es aber mit dem Blick in die aktive Routing Tabelle:

windows bgp routing missing

Dies ist mit unvollständig nur unzureichend umschrieben.

Real fehlen abertausende Routen wie die folgenden:

B     206.0.0.0/15 [20/0] via 94.135.173.249, 4d15h
B     206.2.0.0/16 [20/0] via 94.135.173.249, 4d15h
B     206.2.76.0/24 [20/0] via 94.135.173.249, 00:36:24
B     206.3.0.0/19 [20/0] via 5.102.160.98, 4w0d
B     206.3.32.0/19 [20/0] via 94.135.173.249, 4d15h
B     206.3.42.0/24 [20/0] via 5.102.160.98, 19:43:50
B     206.3.64.0/18 [20/0] via 94.135.173.249, 4d15h
B     206.3.128.0/17 [20/0] via 94.135.173.249, 4d15h
B     206.4.0.0/14 [20/0] via 94.135.173.249, 4d15h
B     206.5.12.0/22 [20/0] via 94.135.173.249, 4d15h
B     206.8.0.0/14 [20/0] via 94.135.173.249, 4d15h
B     206.8.2.0/24 [20/0] via 94.135.173.249, 4d15h
B     206.8.88.0/24 [20/0] via 5.102.160.98, 19:43:49
B     206.8.120.0/24 [20/0] via 94.135.173.249, 4d15h
B     206.8.121.0/24 [20/0] via 94.135.173.249, 4d15h
B     206.8.122.0/24 [20/0] via 94.135.173.249, 4d15h

Das heißt, dass die Maschine nun nicht in der Lage die Pakete korrekt ans Ziel zuzustellen!

Das ist ein KO-Kriterium. Eigentlich müsste ich hier sofort aufhören zu evaluieren.

Wegräumen

Also nehme ich das Announcement der Routen wieder weg.

(config)#no ip prefix-list to_windows seq 2 perm 0.0.0.0/0 le 24

Nach erfreulich schnellen 40 Sekunden sinkt die CPU Last rapide auf nahe 0. Allerdings sind noch immer tausende von Routen im Kernel aktiv.

Als ich zur Kontrolle mir die BGP Routingtabelle mit Get-BgpRouteInformation anzeigen lassen will, behauptet das System, dass die betreffenden Dienste nicht laufen würden.

windows bgp rras dead

Erst im Ereignislog zeigt sich das ganze Ausmaß der Katastrophe:

windows bgp crash

Es hat so ziemlich jeden laufenden Dienst abgeschossen. Nicht nur Routing, sondern auch die Nutzerverwaltung, die Hardware Treiber etc. pp.

Das ist ein KO-Kriterium. Eigentlich müsste ich hier sofort aufhören zu evaluieren.

Zum Glück starten alle Services von alleine neu und ich kann Screenshots für den Blog machen.

IPv6 teste ich nicht mehr.

There is a much talking about quantum communication in wide area networks, but what quantum mechanics really means for networkers stays unclear. But the world's networkers know macroscopic quantum phenomena very well.

1280px-Schroedingers_cat_film_copenhagen.svg

Von Christian Schirm - Eigenes Werk, CC0, https://commons.wikimedia.org/w/index.php?curid=68587012

One interpretation of quantum mechanics involves the entanglement of different states, which collapse to the currently measured state during measurement. In essence, this interpretation means that the system is in the determined state immediately after the measurement. It says nothing about how the system will evolve.

Networkers are familiar with the problem of purchasing cable connections:

  • The terminations of the connection are part of the contract and therefore fixed boundary conditions. The route the wire will take is unknown.
  • It is possible to specify a certain route or to get an explicit promise. However, the operator reserves the right to change the route in case of failures or other difficulties.
  • The exact route of a connection can only be determined if a (dredger) fault has occurred.

In such a way each purchased connection is a macroscopic quantum effect:

  • The digger measuring tool detects the location of a pipeline at the time of measurement.
  • With the impact of the excavator damage, the location of the pipeline is reliably determined.
  • When the damage is fixed, a new functional state is achieved, which may have been repaired on site or relocated.
  • The new cable route is therefore a new macroscopic quantum phenomenon.

Die deutsche Wirtschaft besteht hauptsächlich aus kleinen, spezialisieren Unternehmen. Die meisten von ihnen haben nichts mit IT am Hut, brauchen es aber trotzdem. Also holen sie sich einen Bekannten als Dienstleister bis irgendwann mal aufgeräumt werden muss.

Der Auftrag

Ein typisches 10-Personen-Unternehmen wendet sich an uns, weil ein Bekannter uns empfahl.

Die Firma gibt es schon lange, hat in diese Gegend hier expandiert und nun diesen Teil abgespalten. Dieser Teil braucht also neue, eigenständige IT. Der Auftrag besteht darin, herauszubekommen, welche Dienste die Ex-Abteilung überhaupt benötigt, wo die bisher betrieben wurden und wie man die separiert. Natürlich muss die Umstellung im laufenden Betrieb stattfinden.

So weit, so gut.

Dass zu den meisten Dienstleistungen – weil bisher intern – keine Verträge existieren, ist nachvollziehbar. Dass die Mitarbeiter nur ihre Arbeit machen, so wie man es ihnen gesagt hat, ist nachvollziehbar. Dass bei der Hauptfirma keiner weiß, welche Dienste existieren und welche Verträge bestehen, ist schwierig aber eben auch nicht zu ändern. Dass die bisherigen Dienstleister nicht zwingend Lust haben zu helfen, ist nachvollziehbar.

Kurz und gut, der Auftrag besteht mehr aus Unternehmensberatung als aus Technik. Es gelingt, über mehrere Monate hinweg, Daten zu verlagern, Dienste wie Steuerbüro, Bank, Dokumentenverwaltung, E-Mails, Webauftritt neu aufzusetzen.

Branchensoftware

Was sich als wirklich schwierig gestaltet, ist die eingesetzte Branchenlösung.

Selbstverständlich gibt es online so gut wie keine Dokumentation, denn die Lösung wurde von einem anderen KMU entwickelt und ist nur regional von Bedeutung. Sie ist aber groß genug, um die Abwicklung ausschließlich über Partner (Systemhäuser) zu realisieren.

Selbstverständlich ist jede Installation eine individuell angepasste Vor-Ort-Installation, für die der Hersteller weder Auskunft gibt, noch davon Kenntnis hat. Die klassische Antwort ist da in der Regel: Diese Version ist völlig veraltet.

Es stellt sich heraus, dass die Mitarbeiter über ein VPN auf einem Terminalserver an einem anderen Firmenstandort arbeiten. Leider kann niemand etwas zu dem Server und der dortigen Software sagen. Der betreffende Mitarbeitet ist schon länger nicht mehr angestellt.

Bei einem Vor-Ort-Termin bekommen wir heraus, dass die Software offenbar nur ein Frontend ist, die ihrerseits ein Backend anspricht. Wo dieses Backend steht, weiß keiner.

Die Backend-IP führt zu einem Systemhaus in der Nachbarstadt. Dort weiß man zunächst nichts von dem Kunden oder gar einem Serverbetrieb. Mehr aus Neugier folgt man unseren Angaben und meldet zurück: Endlich wissen wir, was diese Maschine da soll. Wir konnten die bisher nicht zuordnen. Übernehmen Sie die?

Selbstverständlich gibt es weder Vertrag zwischen Firma und Systemhaus, noch irgendwelche Zahlungen, wobei man bei letztem allgemein unsicher ist.

Technik

Was dann bei uns ankam, waren drei Geräte.

Man sagte uns, ein Server habe viele Festplatten und sei echt schwer. Es steht APC drauf. Sie haben also die USV mit ausgebaut und versendet.

Ein Server ist ein Tower, der andere im 19" Einbaurahmen. Mal sehen, was da drauf ist.

Ja, die Erwartungen an das heutige Internet haben sich gewandelt. Es ist nicht mehr die vorgeblich heile Welt, in der man vertrauensvoll mit anderen kommunizieren konnte. Jeder Dienstleister, sei es die besuchte Webseite oder der eigne Provider, wird argwöhnisch unter die Lupe genommen. Über all diesem steht die Furcht vor der Politik, dem Staat und den Geheimdiensten.

Lauscher

Es ist nur vernünftig, nicht zu gutgläubig im Netz unterwegs zu sein. Man kann seine E-Mails verschlüsseln (und macht es doch nicht), man kann darauf achten, Webseiten nur über verschlüsseltes HTTPS zu besuchen, man kann SSH und viele andere verschlüsselte Protokolle nutzen. Alle diese Methoden schützen vor dem Ausspionieren auf dem Transportweg.

Aber sie tun es nicht vollständig. Immer noch kann man erkennen, wer mit wem wie viel Daten austauscht. Um das zu verschleiern, muss man auf TOR-Netzwerke setzen. Eine andere Alternative ist es, sämtliche Nutzungsarten auf wenige große Anbieter zu verteilen. Man geht nicht nur in der Masse unter, sondern läßt den Mitlauscher auch im unklaren über seine detaillierten Aktivitäten.

Wer bin ich?

Trotzdem bleibt ein weiteres Problem: Die Namensauflösung. Wir sind es gewohnt, bei E-Mail-Adressen, URL-Zeilen, Spiele-Servern, ja bei jeder Interaktion mehr oder weniger sprechende Namen zu benutzen. Der Dienst, der die Namen in IP-Adressen der zugehörigen Server umwandelt ist das DNS, das Domain-Name-System.

DNS ist clever konstruiert, es funktioniert wie eine verteilte Datenbank. Die innere Struktur der Namen entspricht Hierarchieebenen, die in unterschiedlicher Verantwortung stehen und von vielen verschiedenen Parteien betrieben wird. Die Delegation reicht bis in die Firma oder den Hobbykeller. Von dort aus wird die ganze Welt mit Auskünften versorgt, falls mal jemand wirklich was mit mir zu tun haben will. Das System stellt die Auskunftsdaten in den Hoheitsbereich des jeweiligen (Web-, Mail-)Server-Betreibers. Die Entscheidung, wer welche Auskunft bekommt, liegt damit praktisch beim Endnutzer. So kann eine Firma beispielsweise intern mehr und andere Dienste betreiben als nach außen sichtbar sein sollen.

Eine weitere clevere Idee ist, die Namensauflösung in spezielle Software, die Resolver, durchzuführen. Alles, was diese Software benötigt, ist ein Internetzugang und eine kleine Anzahl fester Root-Server-Adressen, die zu wirklich jeder Frage eine Antwort kennen (auch wenn diese nur heißt, man möge bitte da drüben nachfragen). Diese Resolver merken sich alle Ergebnisse, die sie im Laufe der Zeit zu Gesicht bekommen und halte sie eine bestimmte (einstellbare) Zeit vor. So können sie viele Anfragen direkt beantworten und belästigen nicht den Rest der Welt. Caching sorgt so dafür, dass die Last der DNS-Quell-Server nicht zu groß wird. Da diese Resolver so wenig Anforderungen stellen, kann und soll praktisch jeder und jedes Gerät einen solchen Resolver betreiben.

Früher waren jedoch nicht alle Geräte so leistungsstark, einen vollen Resolver selbst zu betreiben. Also hat die Firma oder der Provider einen großen, leistungsfähigen zentralen Resolver hingestellt den alle Clients benutzen. Der Caching-Effekt wird durch diese regionale Zentralisierung größer, es werden deutlich weniger Anfragen an die DNS-Quell-Server geschickt.

Fäschungen und Zensur

Das Problem mit dem System ist, dass alle Anfragen unverschlüsselt und unauthentisiert sind. Jeder auf dem Weg kann mitlesen und die Antworten beliebig verändern. Da veränderte Antworten gefährlich sind (Umlenkung der Bankseite zu Phishern), wurde DNSSEC erfunden. Es unterschreibt die DNS-Antworten und verhindert somit eine Manipulation. Wer als Betreiber einer eigenen Zone diese nicht unterschreibt, handelt fahrlässig. Es ist wie der Betrieb eines HTTP-Server ohne HTTPS: Man bringt seine Nutzer und Kunden in Gefahr.

Auch die letzte Meile, also die Verbindung zum zentralen Resolver kann man mit DNSSEC gegen Manipulationen schützen. Alternativ kann man hier auch auf die gehypten Verfahren DNS-over-TLS (DOT) oder DNS-over-HTTPS (DoH) setzen, die zusätzlich die letzte Meile verschlüsseln. Besser ist es aber gleich einen eigenen DNSSEC validierenden Resolver auf dem Endgerät zu betreiben, denn das schützt auch gegen Manipulationen am vorgegeben Resolver selbst. Einige Provider lenken Tippfehler auf eigene Seiten um (NXDOMAIN-Rewriting), das muss man sich ja nicht antun.

Bleibt das Problem, das DNS Anfragen i.d.R. immer den vollen Namen anfragen als z.B. www.heise.de, auch wenn sie sich an einen Root-Server wenden. Die Idee dabei ist, die Antwortzeiten zu verkürzen, wenn der angefragte Server ohnehin schon mehr Details kennt, die er gleich mit schicken kann. Solche zusätzlichen Antworten wurden für Angriffe ausgenutzt, indem der DNS-Server von firma.de bei der Frage nach www.firma.de auch immer gleich noch eine (falsche) Antwort für www.heise.de mitschickte und die Resolver diese treudoof lernten. Mit DNSSEC wird es wieder möglich, diese zusätzlichen Antworten auszuliefern, weil der Resolver sie anhand der Signaturen als valide erkennen kann. Hat man das nicht, muss man mit den Antworten sorgsam umgehen.

Privatsphäre

Das Privacy-Problem ist nun noch anzugehen: Alle Root-Server bekommen die vollen Anfragen zu sehen. Aber auch hier gibt es seit Anbeginn eine Empfehlung: DNS kann Zoneninhalte komplett transferieren. Mit AXFR (Vollabzug) oder IXFR (Änderungen) kann ein Resolver präventiv die komplette Zone ein lernen und braucht nie wieder die Quell-Server mit konkreten Fragen zu belästigen. Die Root-Zone unterstützt das Modell, es ist für jeden Nutzer, der Wert auf Privatsphäre legt, zu empfehlen.

Die meisten Top-Level-Domains unterstützen den Zonentransfer nicht, meist aus markenrechtlichen Überlegungen. Hier würden also zumindest ein Teil der Anfragen aufschlagen. Es gibt seit eingen Jahren jedoch auch Resolver, die gerade bei den TLDs nur nach der delegierten Zone fragen und so die Privatsphäre der Anwender schützen.

Auch für private oder Firmen-Zonen ist ein offenes AXFR meist sinnvoll. Nicht nur, dass man wichtige Server so wesentlich stabiler betreibt, man gestattet so auch seinen Nutzern eine höhere Privatsphäre. Selbstverständlich darf man ins DNS keine ernsthaften Geheimnisse rein schreiben, aber das macht man ja sowieso nicht. Mit beliebig vielen Versuchen kann man die Namen immer automatisiert herausbekommen.

Fazit

Zusammengefasst kann man sagen: DNS ist gereift, es kann mit den Bedrohungen der Überwachung und Zensur umgehen. Alles was man tun muss, ist einen eigenen, validieren Resolver zu betreiben, wenn möglich mit einer Kopie der Root-Zone. Bis auf DNSSEC (gegen Zensur) sind das alles Empfehlungen aus den Frühzeiten des DNS.

Wenn ein Protokoll alt wird, stirbt mangels Nutzung einfach aus. Protokolle wie DNS überleben jedoch, indem sie sich an geänderte Anforderungen anpassen oder flexibel genug eingesetzt werden können.

Mein persönlicher Vorwurf an die Protagonisten von DoH ist folgender: Wer ein verteiltes System zugunsten einer Handvoll großer Anbieter aufgibt, dabei aktive Nutzungsfälle wie Split-DNS sabotiert und auf lokale Validierung verzichtet, der bekommt zentrale Überwachungs- und Zensursysteme. Es ist von einem technischen Redakteur unverantwortlich, seine Leser derartig in die Irre zu führen und sie damit in Gefahr zu bringen.

Das Internet basiert auf zwei grundsätzlichen Prinzipien: Dezentraliät und Interoperabilität. Internet ist das genaue Gegenteil von großen, zentralen Plattformen. Es ist die große, weite Landschaft, nicht der eingezäunte Garten.

Wenn ein ISP über seine Außenanbindungen Traffic schaufelt, dann ist es oft Glückssache, welches Leitung wieviel Daten abbekommt. Natürlich wird man gezielt versuchen einige Teilnetze nur auf einigen bestimmten Upstreams zu announcieren, damit genau dort der Traffic auch rein kommt. Aber das Finetuning ist sehr schwer. Man müßte ziemlich genau wissen, welcher Datenstrom zu welcher Zeit auf welchem Weg durchläuft, um die Änderung planen zu können.

Details bitte

Kürzlich hatte ich über Netflow geschrieben. Dort wurden die Datenströme nach Quell- und Ziel-AS summiert. jetzt will ich es detaillierter haben.

Weiterhin benötigt werden nun:

  • Der Router, der die Daten einsammelt.
  • Das Peer-ASN mit dem der Router direkt redet.
  • Der Netzblock, der im globalen Routing auftauchen wird.
  • Und der Schönheit wegen, der lokale Dienst, der den Traffic abbekommt oder initiiert.

Um nicht sämtliche IP Adressen als relevant ansehen zu müssen, definiere ich mir einen neuen Flow pro Richtung:

flow record in
 match routing source as 4-octet
 match routing source as peer 4-octet
 match routing destination as 4-octet
 match ipv4 destination address
 match ipv6 destination address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
flow record out
 match routing source as 4-octet
 match routing destination as 4-octet
 match routing destination as peer 4-octet
 match ipv4 source address
 match ipv6 source address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long

Zusätzlich zu den Quell- und Ziel-ASNs nehme ich nun auch noch das Peer-ASN und die Quell- oder Ziel-IP dazu.

So beschränke ich mich auf die IP-Adressen im lokalen Netz (oder halt Transit) und aggregiere auf dem Router schon über die unbekannten externen IPs. Es wäre denkbar, auch IP-Prefixe statt der Adresse zu nehmen, aber ich habe Routing-Objekte, die kleiner sind als einige Prefixe. Also bleibt es bei den Adressen.

IPv4 und IPv6 sind zusammengefaßt, eine von beiden Werten wird schon relevant sein.

Als erste Überraschung präsentiert mir die Ausgabe Peer-ASN an Routern, die gar keine direkte Verbindung zu diesem AS haben!

Es stellt sich heraus, daß das Peer-AS ein abgeleiteter Wert ist, der durch ein Blick in die Routing-Tabelle ermittelt wird. Es zeigt also immer auf das Peer-AS, das der Router genommen hätte, wenn er das Paket jetzt in diese Richtung routen müßte.

Logischerweise ist also das Source-Peer-ASN i.d.R. falsch. Aber auch das Destination-Peer-ASN kann falsch sein, wenn es mehrere gleichberechtigte Wege gibt. Es ist durchaus möglich, das Pakete zum Peer 1 zu schicken und Peer 2 im Netflow zu hinterlegen.

Also stelle ich erstmal auf incoming und outgoing Interface um. Unglücklicherweise kann der Netflow-Collector überhaupt nicht damit umgehen, nur ein Interface zu bekommen. In der Annahme es gäbe beide Interfaces im Flow werden einfach die nächsten zwei Byte nach dem ersten Interface als das fehlende Interface angesehen. Alle anderen Felder werden danach mit einem Offset von zwei völlig fehlerhaft geparst. Also bekommt der Collector seinen Willen und das fehlende Interface (aber nur collected).

flow record in
 match routing source as 4-octet
 match routing destination as 4-octet
 match interface input
 match ipv4 destination address
 match ipv6 destination address
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
 collect interface output
flow record out
 match routing source as 4-octet
 match routing destination as 4-octet
 match ipv4 source address
 match ipv6 source address
 match interface output
 collect timestamp sys-uptime first
 collect timestamp sys-uptime last
 collect counter bytes long
 collect counter packets long
 collect interface input

Achja, die Router-IP. Der nfcapd hat mehrere Module, die man getrennt aktivieren muß. Das Modul 13 schreibt die IP-Adresse des Netflow-Sensors (des Routers) mit.

Damit sind die Werte erst einmal erfaßt.

Mach mal bunt

Da mich aktuell nur IPv4 interessiert genügt es für die Auswertung sich darauf zu konzentrieren:

nfdump -r ... -q -N -A srcip4/26,srcas,inif,router,outif,dstas,dstip4/26 -O bps

Dieses Kommando aggregiert auf Basis von /26er Netzen, für die ich händisch im Auswertescript hinterlegt habe, welches Routing-Object und welcher Zweck gemeint sind.

Das Script schreibt die aggregierten Daten alle fünf Minuten in ein Logfile. Es ersetzt dabei die Interfaces pro Router mit den Peer-AS-Werten anhand einer manuellen Zuordnungstabelle.

Das Script versucht des weiteren, Flows von Transit-Traffic korrekt zuzuordnen. Wenn Quell- und Ziel-ASN ungleich Null sind, habe ich Transit.

Sind auf einem Router Quell- und Ziel-Interface einem Peer zugeordnet ist es einfach, wenn nicht muß man den eingehenden Flow einem Ausgehenden zuordnen, der die gleichen Quell- und Ziel-ASNs aufweist. Dabei kann es passieren, daß der Traffic aufspaltet. In dem Fall entnehme ich das Minimum an übereinstimmenden Traffic und ordne den Rest solange weiter zu, bis der Resttraffic unter der Nachweisgrenze verschwindet.

Im Ergebnis entstehen Einträge der Form:

DHCP 91.137.60.0/22 rudo5 8220 other 94
2906 8220 rudo5 178.19.237.0/24 NAT 86
other 196714 rudo7 178.19.228.0/22 NAT 85
2906 8220 rudo8 rudo6 196714 196714 83

Der Flow ist von links nach rechts zu lesen und die letzte Zahl ist der Traffic in Mbps.

Aus diesen Angaben generiert sich mit Javascript ein SVG.

SVG deswegen, weil es interaktiv ist:

  • Man kann die Daten in fünf-Minuten-Schritten auswählen.
  • Fährt man mit der Maus über eine Kurve, so wird diese hervorgehoben und der Eintrag erscheint als Tooltip.
  • Fährt man mit der Maus über ein Rechteck (Router, Peer, Netz, ...) werden alle durchlaufenden Kurven hervorgehoben und man bekommt die Summenbandbreite als Tooltip.
2018-09-24-163642_1280x1024_scrot

Grün ist eingehender Traffic, blau ausgehender und rot ist Transit. Die Dicke der Linie und die Größe der Rechtecke geht linear mit dem Traffic. Router und Peers haben die Größe der maximalen Kapazität. so sieht man den Auslastungsstand.

Mit dieser Darstellung kann ich nachträglich mir anschauen, was zu bestimmten Stoßzeiten im Netz los war. Ich sehe, welche Routing-Objekte evtl. besser über einen anderen Upstream announciert werden könnten. Auf diese Weise kann ich sehr fein abstimmen, wieviel Traffic auf welcher Leitung herein kommt und muß erst wesentlich später neue Bandbreite zukaufen.

Das Aggregationsschema führt allerdings auch in die Irre. Es ist nicht unterscheidbar, ob es 5000 Flows mit 1 Mbps gab oder 10 Flows mit 500 Mbps: Angezeigt werden 5 Gbps. Das fiel auch erst spät auf, als ein Scan über alle IP Adressen trotz nur wenig Mbps sich zu einem gewaltigen Strom aufplusterte. Aber damit muß man aktuell leben.