SGINet: Aufbau, Protokoll und Lehren eines Rechnerverzeichnisses
SGINet ist ein Verzeichnis für Silicon-Graphics-Rechner unter IRIX, das der Betreiber flexion seit 2024 führt. Dieses Paper beschreibt, woraus es besteht, wie sich eine Maschine registriert, welches Protokoll der Client spricht, was die Website zeigt, was sich über das geschlossene Backend erschließen lässt und wie der Light-Client ältere Maschinen über ein Relay anbindet. Gelesen sind der vollständige Quelltext des Clients, der Light-Client, die Website und der Ankündigungs-Thread. Am Ende stehen die Lehren für ein Verzeichnis dieser Art: eine Identität, die ein Credential ist und keine Seriennummer, getrennte Schnittstellen für Clients und Website, und ein Protokoll, das ohne TLS und ohne richtige Uhr auskommt.
Inhalt
- Gegenstand und Grenzen
- Woraus SGINet besteht
- Registrierung und Identität
- Das Protokoll des Clients
- Was die Website zeigt
- Das Backend, aus Spuren erschlossen
- Der Light-Client und das Relay
- Was aus dem Befund nicht folgt
- Lehren für ein Verzeichnis dieser Art
- Quellennachweis
Anhang
1. Gegenstand und Grenzen
Untersucht wird SGINet, ein Verzeichnis für Silicon-Graphics-Rechner unter IRIX. SGINet hat vier Schichten, und jede Aussage in diesem Paper nennt die Schicht, auf der sie beobachtet wurde.
- Der Client ist offen. Gelesen ist das Repository
sginet/sginet-clientauf GitHub im Stand des Commitsc8007876vom 30. Oktober 2026, jede Datei außer den mitgelieferten Fremdbibliotheken und den Bilddaten.1 Aussagen über den Client sind damit Aussagen über diesen Stand. Im Anhang steht zu jeder Aussage Datei und Zeile. - Der Light-Client ist ein eigener Tarball mit Quelltext und Binaries, gelesen im Stand vom 21. Februar 2026.2
- Die Website
sginet.flexion.ioist am 2. November 2026 im Browser begangen worden, als Text und mit Blick auf die Aufrufe, die sie an ihre API richtet.3 Aussagen über die Website gelten für diesen Tag. - Das Backend ist geschlossen. Alles über das Backend ist aus Hostnamen, Pfaden, Antwortfeldern und Fehlertexten erschlossen und ist als solches gekennzeichnet.
- Das Forum ist der Ankündigungs-Thread von flexion auf
forums.sgi.shmit seinen vier Beiträgen bis zum 19. Oktober 2026.4
Kein Programm von SGINet wurde gebaut oder ausgeführt. Der Quelltext liegt als Archiv unter sources/ neben diesem Dokument.
2. Woraus SGINet besteht
SGINet besteht aus fünf Teilen. Drei davon laufen auf dem SGI-Rechner, einer in der Cloud, einer im Browser.
| Teil | Was er ist | Was er tut |
|---|---|---|
sginet | Kommandozeilenprogramm mit ncurses-Oberfläche, C89, statisch gegen BearSSL, json-c und ncurses gebaut | Registriert die Maschine, lädt das Hardware-Inventar hoch, meldet als Daemon alle zwölf Minuten den Online-Zustand, zeigt die Systemliste, sucht Software, lädt Screenshots hoch, zeigt Forum-Beiträge und eine Shoutbox, prüft die Systemkonfiguration, aktualisiert sich selbst und startet auf Wunsch einen kleinen Webserver im LAN |
xsginet | X11/Motif-Programm mit demselben API-Code | Registrierung, Systemliste mit Inventar, Screenshots, Shoutbox, Softwaresuche, Systemprüfung |
xsginet-globe | OpenGL-Programm mit Motif | Zeigt die Nutzer auf einem drehbaren Globus, lässt den eigenen Standort setzen |
| Light-Client | Zwei kleine C-Programme für IRIX 4, 5 und 6 | Druckt das Inventar als JSON zum Einfügen auf der Website und pingt über einen Proxy im LAN |
| Website | Angular-Anwendung auf sginet.flexion.io | Liste aller Systeme, Detail mit Inventar, Hall of Fame, Modellverteilung, Softwaresuche, Downloads, manueller Inventar-Upload, Weltkarte |
Die Clients werden mit dem IRIX-eigenen Compiler gebaut und als tardist-Paket für IRIX 6.5 und IRIX 5.3 verteilt, das die Programme nach /usr/bin legt und ein init-Skript für den Daemon einrichtet.1 Alle drei Programme sprechen TLS 1.2 mit der Cloud; die fünf Wurzelzertifikate von Amazon sind in die Binaries einkompiliert, und wo /dev/urandom fehlt, sammelt der Client Entropie aus Zeitmessungen und einer Seed-Datei.1 Der Updater lädt ein neues Binary von einer Adresse, die das Backend nennt, und prüft nur dessen Dateigröße.1
3. Registrierung und Identität
Die Identität einer Maschine ist ihre Hardware-Seriennummer. Der Client liest sie mit syssgi(SGI_SYSID) und schreibt sie als Hexstring in jede Anfrage.1 Es gibt kein Token, keine Signatur und kein Passwort. Wer die Seriennummer einer fremden Maschine kennt, kann für sie pingen, ihr Inventar ersetzen oder sie umbenennen. Die Website zeigt die Seriennummer nicht; öffentlich ist eine Kennung aus Benutzername und gekürztem Hash.3
Die Registrierung läuft so ab: Beim Start sendet der Client hello. Antwortet das Backend mit dem Code 2, zeigt der Client einen Hinweis, dass Inventar und Benutzername öffentlich werden, fragt beim Backend die Modellnamen zum Maschinentyp aus uname ab, lässt den Benutzer das Modell wählen, fragt Benutzername und Maschinenname ab und sendet register. Das Backend kann in jeder Antwort mit requestHINV ein frisches Inventar anfordern.1 Der Benutzername ist frei wählbar und an kein Konto gebunden. Wer seinen Eintrag löschen lassen will, schreibt dem Betreiber eine Nachricht im Forum.4
4. Das Protokoll des Clients
Alles ist HTTPS-POST mit einem JSON-Objekt, dessen Feld action die Operation nennt. Der Client spricht fünf Endpunkte unter einem Pfad, der nach AWS API Gateway aussieht.1
| Endpunkt | Aktionen | Zweck |
|---|---|---|
| sginet-client | hello, register, IP2Model, ping, updateHINV, shutdown, getSystemHINVAsList, check-updates, getShoutbox, postShoutbox, renameSystem | Registrierung, Lebenszeichen, Inventar, Systemliste (als ping mit showSystems), Updater, Shoutbox |
| sginet-sw | softwaresearch | Paketsuche in SGUG-RSE, Nekoware und SGI Freeware |
| sginet-files | getSignedUploadPolicy | Liefert eine vorsignierte S3-POST-Policy, mit der der Client den Screenshot direkt in den Bucket lädt |
| sginet-rss | whatsnew-sgug, sgug-getPostByID | Forum-Beiträge |
| sginet-globe | saveMyPosition, getMarkers | Standort setzen und Marker für den Globus holen |
In jeder Anfrage steht ein Objekt client, das der Client aus seinem Zustand füllt. Der Ping ist nichts anderes als dieses Objekt.
| Feld | Inhalt |
|---|---|
| version | Versionsstring des Programms, zum Beispiel V20261026-1000-CL6 |
| clientType | Drei Buchstaben für das Programm und die IRIX-Generation: CL5, CL6, X_5, X_6, XG5, XG6 |
| mode | Betriebsart als Zahl, etwa 2 für den Daemon |
| gen | Protokollgeneration, fest 1 |
| clientID | Die Hardware-Seriennummer |
| uptime | Sekunden seit dem Start, aus dem Startzeitpunkt des Prozesses 1 |
| avg | Die drei Lastwerte, aus der Ausgabe von uptime geparst |
Das Inventar ist ein Objekt hinv. Es verbindet drei Dinge: Werte aus Systemaufrufen, die erste Zeile zweier hinv-Kommandos und das rohe Inventar des Kernels aus getinvent().
| Feld | Herkunft auf IRIX |
|---|---|
| ipmodel | Die ersten vier Zeichen von utsname.machine, etwa IP30 |
| cpucount | sysmp(MP_NPROCS) |
| osrelease | utsname.sysname und utsname.release |
| cpu | Erste Zeile von hinv -t cpu |
| processor | Erste Zeile von hinv -c processor, gefiltert auf MHZ oder GHZ |
| inv | Ein Array aller Einträge von getinvent() mit class, state, type; bei CPU-Einträgen zusätzlich Takt, Flavor und Cache-Größe |
Die Deutung der Zahlen in inv übernimmt das Backend: Die Website zeigt zu jedem Eintrag ein classLabel und ein deviceLabel, die der Client nicht sendet.3 Antworten sind flach: success, message, bei Fehlern code, bei Listen ein Array lst.
5. Was die Website zeigt
Am 2. November 2026 führte die Liste 78 Systeme, davon 4 online, mit zwölf Modellgruppen zum Filtern. Drei Zustände sind sichtbar: online, offline und ohne Zustand, letzteres bei Maschinen, die nur über den manuellen Upload in die Liste gekommen sind und nie gepingt haben.3
| Ort | Felder |
|---|---|
| Liste | Online-Zustand, Maschinenname, Modellname, Anzahl CPUs, erste Grafikkarte, Besitzer, laufende Uptime, Gesamt-Uptime |
| Detail | Name, Besitzer, Maschinentyp aus uname, Modell, CPU-Anzahl, RAM in MB, CPU-Typ, CPU-Takt, Grafikkarte, Betriebssystem, Registrierdatum, Datum des Inventars, Client-Version, Online-Zustand mit Uptime, Gesamt-Uptime, längste Uptime, Lastwerte, die Inventarliste mit Klasse und Gerät, Screenshots des Besitzers, ein Teil-Link |
| Hall of Fame | Meiste CPUs, meister RAM, längste Gesamt-Uptime, längste durchgehende Uptime, stärkste Grafik, Modellverteilung |
| Karte | Ein Three.js-Globus mit grünen Markern für Online- und roten für Offline-Maschinen, sofern der Besitzer einen Standort gesetzt hat |
Die Website spricht dieselbe Cloud-Funktion wie der Client, aber über einen zweiten Hostnamen und mit eigenen Aktionen: getSystemsList, getSystemHINV, getHallOfFame, getDownloadLinks, listScreenshotsByUsername, getMarkersWeb. Eine Client-Aktion ohne das Objekt client weist das Backend mit der Meldung No client info ab.3 Die Shoutbox ist laut Forum nur in den Clients sichtbar und nicht auf der Website.4
6. Das Backend, aus Spuren erschlossen
Nichts in diesem Abschnitt ist gelesen. Es ist aus dem erschlossen, was Client und Website preisgeben.
| Spur | Deutung | Stand |
|---|---|---|
Pfad /sginet/prod/sginet-client unter drei Hostnamen, darunter zlpymtpx3c.execute-api.eu-central-1.amazonaws.com | AWS API Gateway mit der Stage prod in Frankfurt, dahinter je eine Lambda-Funktion pro Endpunkt | belastbar |
Feld GSI1SK als Kennung einer Maschine, Kommentar im Client zum Fehlertext The conditional request failed | DynamoDB mit einem Global Secondary Index | belastbar |
Vorsignierte POST-Policy mit X-Amz-Credential und Bucket | Screenshots liegen in S3; die Website sagt, sie werden nach zwei Jahren gelöscht | belastbar |
| README: Die API behält IP und Zeitpunkt jeder Anfrage bis zu drei Tage für Metriken | Zugriffslog des Gateways | schwach |
| README und Installationshinweis: Anfragen von Emulatoren werden stillschweigend abgewiesen | Eine Prüfung im Backend, deren Merkmal nicht sichtbar ist; der Client enthält keine Emulatorprüfung | schwach |
| Ping alle zwölf Minuten, Website zeigt vier von 78 online | Online heißt: ein Ping innerhalb eines Fensters, dessen Länge nicht sichtbar ist | unerforscht |
7. Der Light-Client und das Relay
Für IRIX 4 und 5 ohne aktuelles TLS gibt es den Light-Client. Sein erstes Programm druckt dasselbe Inventar wie der große Client als eine JSON-Zeile mit action: hinv-upload, clientID, uptime und format: 1; der Besitzer fügt diese Zeile auf der Website im Dialog „Upload HINV“ ein.2 Sein zweites Programm pingt mit action: ping-light über reines TCP und HTTP/1.1 ohne jede Verschlüsselung an einen Hostnamen und Port, die der Besitzer angibt.2
Dort steht ein nginx im LAN des Besitzers, der die Anfrage entgegennimmt und mit TLS an die Cloud weiterreicht; die mitgelieferte Konfiguration setzt dafür den Host-Header und den TLS-Servernamen.2 Der Light-Client weiß von alldem nichts. Für ihn ist das Relay der Server. Für Maschinen mit einem alten curl gibt es daneben einen zweiten Gateway-Hostnamen, der noch TLS 1.0 annimmt.2
8. Was aus dem Befund nicht folgt
Dass das Backend keine weitere Prüfung der Identität vornimmt, folgt nicht. Gelesen ist, was der Client sendet, und das ist die Seriennummer ohne Signatur. Was das Backend daraus macht, ist nicht sichtbar. Eine IP-Bindung oder eine Plausibilitätsprüfung des Inventars wäre von außen nicht zu erkennen.
Dass die Emulatorprüfung an einem bestimmten Merkmal hängt, folgt nicht. Der Client sendet die Seriennummer, den Maschinentyp und das rohe Inventar; welches davon das Backend prüft, ist nicht sichtbar.
Dass die Website alle Felder zeigt, die das Backend speichert, folgt nicht. Die Antworten der Website-Aktionen enthalten die Felder aus Tabelle 5 und wenige mehr, etwa isNew und sort. Was sonst in der Datenbank liegt, bleibt offen.
Dass der Betrieb so bleibt, folgt nicht. Die Endpunkte, die Hostnamen und die Updater-Dateien sind der Stand des 2. November 2026; das Forum zeigt, dass flexion die Verteilung innerhalb eines Jahres zweimal umgestellt hat, von RPM auf tardist und von SGUG-RSE-Abhängigkeiten auf statische Binaries.4
9. Lehren für ein Verzeichnis dieser Art
Aus dem Befund folgen Lehren für jedes Verzeichnis, das alte Rechner über das Netz registriert und ihren Zustand zeigt. Sie gelten unabhängig von der Plattform.
- Die Identität einer Maschine ist ein Credential, keine Seriennummer. Eine Seriennummer, die im Klartext in jeder Anfrage steht, ist für jeden Mitleser und für jeden, der sie je gesehen hat, der Schlüssel zur Maschine. Ein Verzeichnis gibt jeder Maschine bei der Registrierung ein eigenes Geheimnis und prüft damit jede Anfrage.
- Was von alten Maschinen kommt, wird im Klartext kommen. TLS auf einem System der Neunziger scheitert an Bibliotheken, an Wurzelzertifikaten, an Entropie und an der Uhr; SGINet braucht dafür einkompilierte Zertifikate, einen Entropie-Rückfall, einen zweiten Hostnamen für TLS 1.0 und am Ende ein Relay im LAN. Ein Protokoll, dessen Sicherheit in der Nachricht liegt, kommt ohne all das aus, und ein Relay bleibt trotzdem möglich, wenn der Client seine Serveradresse aus einer Konfiguration liest.
- Die Uhr der Maschine ist nicht zu gebrauchen. Pufferbatterien sind leer, und ein Zertifikat ist dann abgelaufen oder noch nicht gültig. Ein Prüfmerkmal gegen Wiederholung darf deshalb nicht an der Zeit hängen, sondern an einem Zähler oder einer Nonce.
- Client-Schnittstelle und Website-Schnittstelle sind zwei Dinge. SGINet trennt sie durch Aktionsnamen und ein Pflichtfeld und weist Anfragen ohne Client-Objekt ab. Die Trennung gehört an die Adresse, damit die eine Seite ohne Zertifikat auskommt und die andere Konten und Anmeldung bekommen kann.
- Rohdaten sammeln, Deutung dem Server lassen. Der Client sendet die Zahlen des Kernel-Inventars, der Server macht daraus Klassen- und Gerätenamen. Der Client bleibt klein und muss für eine bessere Deutung nicht neu verteilt werden.
- Den Produktnamen kennt der Kernel nicht. Er kennt eine Typnummer, der Besitzer kennt das Gerät auf seinem Tisch. Der Server liefert zur Typnummer eine Liste von Modellen, aus der der Besitzer wählt, mit einem Feld für alles, was nicht in der Liste steht.
- Online ist ein Fenster, Uptime ist eine Rechnung. Ein Lebenszeichen im festen Takt, ein Fenster von zwei Takten für „online“ und daraus auf dem Server Gesamt-Uptime und längste Uptime; eine Hall of Fame aus diesen Zahlen hält die Besitzer bei der Stange.
- Sagen, was öffentlich wird, bevor es öffentlich wird. SGINet zeigt den Hinweis vor der Registrierung. Ein Verzeichnis, das Besitzername und Standort zeigt, braucht dazu eine Einwilligung, die der Besitzer selbst widerrufen kann, und eine Löschung, für die er niemanden anschreiben muss.
- Ein Updater, der nur die Dateigröße prüft, ersetzt das Binary durch alles, was die richtige Länge hat. Eine Aktualisierung über das Netz braucht eine Signatur, die der Client vor dem Austausch prüft, oder sie findet über das Paketsystem des Betriebssystems statt.
- Stillschweigendes Abweisen ist für den Besitzer nicht von einem Fehler zu unterscheiden. Wer Emulatoren nicht will oder sie anders zeigt, sagt es in der Antwort und auf der Website.
- Der Weg auf eine alte Maschine ist das Paketsystem und das Netz. SGINet liefert ein natives Paket je Systemgeneration, statisch gelinkt, mit init-Skript, und die Besitzer holen es auf einem heutigen Rechner und kopieren es auf die alte Maschine. Ein Download auf der alten Maschine selbst ist nicht die Regel.
Quellennachweis
Vier Quellen, in der Reihenfolge ihres Auftretens. Der Quelltext des Clients und des Light-Clients ist vollständig gelesen, die Website als Text begangen, der Thread vollständig gelesen.
- sginet: sginet-client, Stand des Commits c8007876 vom 30. Oktober 2026. Quelltext vollständig gelesen Quelle↩↩↩↩↩↩↩
- flexion: sginet-client-light V20260221-0830, Tarball mit README, Quelltext, Skripten und nginx-Konfiguration. Volltext gelesen Quelle↩↩↩↩↩
- flexion: SGINet, Website, begangen am 2. November 2026: Startseite, Systemliste, Detail EMPIRICIST, Screenshots, Hall of Fame, Softwaresuche, Downloads, About, Weltkarte. Als Text gelesen, API-Aufrufe mitgeschrieben Quelle↩↩↩↩↩
- flexion: SGINet, CLI client + daemon + X11 app for SGI systems running IRIX. Thread im Forum der Silicon Graphics User Group, 10. August 2024, mit Beiträgen vom 27. September 2025 und 19. Oktober 2026. Volltext gelesen Quelle↩↩↩↩
Anhang
Fundstellen mit Zeilennummern und die mitgeschriebenen Aufrufe der Website. Für die Aussagen oben braucht man das hier nicht.
A. Fundstellen im Client
Alle Zeilen gelten für den Commit c8007876d3a5fd146b47481e2d7fd3760aad0c96 des Repositories sginet/sginet-client; die Links führen auf GitHub zu Datei und Zeile. Der Light-Client ist im Tarball aus Quelle 2 unter sginet-client-light/. Beide liegen als Archiv unter sources/ neben diesem Dokument.
| Aussage | Fundstelle |
|---|---|
| Daemon pingt alle zwölf Minuten | sginet.c:311-323, sleep(720) |
Identität ist die Seriennummer aus syssgi(SGI_SYSID) | hwinfo_sgi.c:62-71 |
Fünf Endpunkte unter sginet-api.flexion.io/sginet/prod/ | cloudAPI.c:8-12 |
Felder des Objekts client | cloudAPI.c:92-114 |
Aktionen hello, ping, shutdown, updateHINV und die Antwort mit code 2 | cloudAPI.c:451-515 |
Payload von register | cloudAPI.c:517-556 |
Modellliste mit IP2Model | cloudAPI.c:557-610 |
Systemliste als ping mit showSystems, Felder der Antwort, Kommentar zu The conditional request failed | cloudAPI.c:357-450 |
| Updater: Download und Prüfung allein über die Dateigröße | cloudAPI.c:689-750 |
| Signierte S3-Policy und Upload-Felder | cloudAPI.c:824-914, fileutils.c:14-44 |
| Standort setzen und Marker holen | cloudAPI.c:115-156, cloudAPI.c:284-356 |
Inhalt von hinv: uname, sysmp, zwei hinv-Kommandos, getinvent() | hwinfo_sgi.c:72-174 |
Lastwerte aus uptime, Uptime aus Prozess 1 | hwinfo_sgi.c:175-241 |
| TLS 1.2 mit BearSSL, Handshake-Timeout zehn Sekunden, Entropie-Rückfall mit Seed-Datei | http_client.c:34-41, http_client.c:171-254, http_client.c:573-601 |
| Fünf Amazon-Wurzelzertifikate einkompiliert | ta_builtin.c:1-3, BUILDING.md:78-84 |
| Webserver auf Port 8064 | webserver.c:1-28 |
| Client-Typen und Versionsstrings | include/sginet.h:4-10, include/x11-client.h:25-31, x11-globe/include/globe.h:19-25 |
| Listenzeile der Motif-App und Auffrischung alle fünf Minuten | x11-client/main.c:9, x11-client/main.c:266-279 |
| Globus: Markertypen, Farben, Standort per Klick | include/cloudAPI.h:105-127, x11-globe/main.c:548-598 |
| Paket: installierte Dateien und init-Skript | dist/make-tardist-IRIX-6.sh:1-30, daemon/sginet-daemon:21-24 |
| Build: C89 für IRIX 5, MIPSpro, statisch | Makefile:1-45, BUILDING.md:6-15 |
| README: Emulatoren abgewiesen, Logs drei Tage, Screenshots zwei Jahre | README.md:21-65 |
Light-Client: Payload von hinv-upload und ping-light | src/sginet-light.c:211-225, src/sginet-light-http-ping.c:432-463 |
| Light-Client: Klartext-HTTP an Proxy-Host und Port, Ping alle zwölf Minuten | src/sginet-light-http-ping.c:46-48, :278-398, :467-476 |
| Light-Client: nginx als TLS-Relay im LAN | local-nginx-proxy/sginet-proxy:9-27, README.md:29-34 |
| Light-Client: Ping über curl mit TLS 1.0 an eine zweite Gateway-Adresse | scripts/sginet-ping-TLS_1_0.sh:1-2 |
B. Beobachtete Aufrufe der Website
Mitgeschrieben am 2. November 2026 im Browser, durch Mitlesen der XMLHttpRequest-Aufrufe der Anwendung.
| Seite | Aufruf | Antwort |
|---|---|---|
| Systemliste | POST api-gw-eu01.flexion.ch/sginet/prod/sginet-client, {"action":"getSystemsList","params":{}} | systems.total 78, systems.online 4, systems.lst[] mit machinename, username, modelname, ipmodel, CPUcount, gfx0, uptime, totalUptime, longestUptime, loadavg, online, GSI1SK, isNew, sort |
| Detail | dieselbe Adresse, {"action":"getSystemHINV","params":{"id":"CompuHacker/d3f7-3b199-0e58a-67e"}} | system mit regDT, hinvDT, memoryMB, clientversion, hinv.inv[] mit classLabel und deviceLabel, osrelease, processor, loadavg, online, uptime, totalUptime, longestUptime |
| Screenshots | POST .../sginet-files, {"action":"listScreenshotsByUsername","params":{"username":"CompuHacker","offset":0,"limit":10}} | lstFiles, total, offset, hasMore |
| Hall of Fame | {"action":"getHallOfFame","params":{}} | ranking[] mit rtype CPU, RAM, UPTIME, LONGESTUPTIME, GFX und winners[]; modelCount[] |
| Downloads | {"action":"getDownloadLinks","params":{}} | Links und Versionen für tardist, Light-Client und je einen Updater-Eintrag pro Client-Typ mit fileSize |
| Weltkarte | POST sginet-api.flexion.io/sginet/prod/sginet-globe, {"action":"getMarkersWeb"} | markers.lst[] mit lat, lng, online; dieselbe Adresse mit getMarkers ohne client antwortet {"success":false,"message":"No client info"} |