|
|
| (17 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) |
| Zeile 1: |
Zeile 1: |
| * Das Zukunftsprojekt [[Polyzalos]] erfordert die Integration eines HTTP/2 Servers in OrgaMon | | * Das Zukunftsprojekt [[Polyzalos]] erfordert die Integration eines HTTP/2 Servers in OrgaMon |
| * Im Moment entsteht deshalb ein HTTP/2 Server in FreePascal, Zielsystem ist im Moment auf win64 beschränkt | | * Im Moment entsteht deshalb ein HTTP/2 Server in FreePascal, Zielsystem ist im Moment auf Linux beschränkt |
| * Alle Quelltexte befinden sich auf GitHub | | * Alle Quelltexte befinden sich auf GitHub |
| ** [[https://github.com/Andreas-Filsinger/OrgaMon/blob/main/PASconTools/cryptossl.pas cryptossl.pas]] | | ** [[https://github.com/Andreas-Filsinger/Polyzalos/blob/main/src/cryptossl.pas cryptossl.pas]] |
| ** [[https://github.com/Andreas-Filsinger/OrgaMon/blob/main/PASconTools/hpack.pas hpack.pas]] | | ** [[https://github.com/Andreas-Filsinger/Polyzalos/blob/main/src/hpack.pas hpack.pas]] |
| ** [[https://github.com/Andreas-Filsinger/OrgaMon/blob/main/PASconTools/http2.pas http2.pas]] | | ** [[https://github.com/Andreas-Filsinger/Polyzalos/blob/main/src/http2.pas http2.pas]] |
|
| |
|
| == Inbetriebnahme == | | == Inbetriebnahme == |
|
| |
|
| === openSSL ===
| | pacman -S openssl mkcert |
|
| |
|
| Windows
| | === localhost-Zertifikat === |
|
| |
|
| * http://slproweb.com/products/Win32OpenSSL.html
| | # mit "mkcert" |
| * Downloade und Installiere die 64bit Light Version (im Moment "Win64 OpenSSL v3.2.0 Light" .exe)
| | # |
| ** Standard-Ziel akzeptieren, "in das Systemverzeichnis" angekreuzt lassen
| | mkcert -install |
| | | |
| Linux
| | # gehe in dein /hosts/localhost Verzeichnis |
| | | # |
| * selbst aus den Quellen compilieren, da zumeist 1.0 Teil der Distributionen ist
| | mkcert -cert-file cert.pem -key-file privkey.pem "localhost" |
| | |
| === Zertifikat ===
| |
| | |
| ==== localhost ====
| |
|
| |
|
| * mit openssl erst mal key.pem und cert.pem erstellen (hier im Beispiel für die Server-Identität "localhost")
| | # mit "openssl" |
| ** <code>openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=<b><i>localhost</i></b>'</code>
| |
| | |
| #
| |
| # | | # |
| # | | # |
| openssl req -x509 -out localhost.crt -keyout localhost.key -newkey rsa:2048 -nodes -days 365 -sha256 -subj '/CN=localhost' -extensions EXT -config <( \ | | openssl req -x509 -nodes -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost' |
| printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
| |
| | |
|
| |
|
| * ein Hauptverzeichnis ausdenken und dort ein Verzeichnis pro CN erstellen | | * ein Hauptverzeichnis ausdenken und dort ein Verzeichnis pro CN erstellen |
| Zeile 49: |
Zeile 40: |
| cert.pem | | cert.pem |
|
| |
|
| * Zertifikat in Google Chrome installieren
| | === local.orgamon.net-Zertifikat === |
| ** Einstellung -> Sicherheit und Datenschutz -> Sicherheit -> Zertifikate verwalten -> Reiter "Vertrauenswürdige Stammzertifizierungsstellen" -> Importieren ->
| |
| | |
| ==== local.orgamon.net ====
| |
|
| |
|
| * Ich habe bereits ein letsencrypt *.orgamon.net Zertifikat | | * Ich habe bereits ein letsencrypt *.orgamon.net Zertifikat |
| Zeile 59: |
Zeile 47: |
| * privkey.pem und cert.pem kann ich so für den Webserver nutzen | | * privkey.pem und cert.pem kann ich so für den Webserver nutzen |
| * Meine Entwicklungsumgebung kann somit die lokale Maschine sein, obwohl ich eine richtige Domain angebe deren Namensauflösung im Web läuft | | * Meine Entwicklungsumgebung kann somit die lokale Maschine sein, obwohl ich eine richtige Domain angebe deren Namensauflösung im Web läuft |
|
| |
| ==== On demand cert generation ====
| |
|
| |
| * Generiere doch ein key/cert für computername.local
| |
|
| |
| https://github.com/marsupilami79/zeoslib/blob/master/src/webservice/server/dbcproxycertstore.pas
| |
|
| |
| === Port 443 auf dem eigenen System öffnen ===
| |
|
| |
| Wenn Du einen von aussen sichtbaren Webserver (HTTPS) auf dem eigenen Rechner betreiben willst musst Du Port :443 öffnen.
| |
|
| |
| * http://praxistipps.chip.de/windows-10-ports-in-der-firewall-oeffnen-so-gehts_42589
| |
|
| |
| * Auf deinem Router brauchst Du eine feste IP oder ein Dyndns
| |
| * Auf deinem Router musst Du eingehenden Netzwerkverkehr auf Port :443 auf deinen lokalen Rechner leiten (AVM nennt das "Freigabe")
| |
|
| |
| === polyzalosd ===
| |
|
| |
| * Diese Konsolenanwendung gibt Statusmeldungen (Log) in Farbe aus
| |
| * dies muss unter Windows jedoch aktiviert werden
| |
|
| |
| reg add HKEY_CURRENT_USER\Console /v VirtualTerminalLevel /t REG_DWORD /d 0x00000001 /f
| |
|
| |
| * https://ss64.com/nt/syntax-ansi.html
| |
|
| |
| {{Anmerkung|Dies macht polyzalosd inzwischen über eine Windows-API Funktion selbst}}
| |
|
| |
| == Informationsquellen ==
| |
|
| |
| === HPACK ===
| |
|
| |
| * RFC <b>HPACK</b> https://tools.ietf.org/html/rfc7541
| |
|
| |
| === HTTP/2 ===
| |
|
| |
| * RFC <b>HTTP/2</b> https://datatracker.ietf.org/doc/html/rfc9113
| |
| ** veraltet: <b>HTTP/2</b> https://tools.ietf.org/html/rfc7540
| |
| * https://github.com/nghttp2/nghttp2
| |
| ** https://nghttp2.org/blog/2014/04/27/how-dependency-based-prioritization-works/
| |
| * https://github.com/nginx/nginx
| |
| * https://github.com/h2o/h2o
| |
|
| |
| === Design ===
| |
|
| |
| * https://calendar.perfplanet.com/2020/head-of-line-blocking-in-quic-and-http-3-the-details/
| |
| * Der Client stellt eine Menge Requests, der erste Response (16 MB gross) verstopft aber die sende Richtung
| |
| ** die folgenden Responses hätten aber nur minimal kleine Antworten benötigt, also z.B. HTTP 304
| |
| ** dann blockiert der lange Response alles andere
| |
| ** in der Aufbau-Phase einer Seite wäre es gut der Server hätte eine Kenntniss davon was der Client alles braucht
| |
| ** Es ist ja eigentlich klar war ein "full" Reload benötigt, und da sollte man multiplexen solange noch nicht alle Antworten durch sind
| |
|
| |
| === TLS ===
| |
|
| |
| * https://wiki.openssl.org/index.php/Simple_TLS_Server
| |
| * http://openssl.6102.n7.nabble.com/TLS-1-3-client-hello-issue-td72449.html#a72460
| |
| * http://slproweb.com/products/Win32OpenSSL.html
| |
| * https://github.com/openssl/openssl/blob/master/include/openssl/tls1.h
| |
| * https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/
| |
| * http://gnutls.org/manual/gnutls.html#Server-name-indication
| |
| * https://github.com/jay/http2_blacklisted_ciphers
| |
| * https://wiki.openssl.org/index.php/TLS1.3
| |
|
| |
| === Konzept ===
| |
|
| |
|
| |
| * cOrgaMon ist ein https:// Server nach HTTP/2 Standard ohne UI
| |
| * <u>eine</u> Instanz von cOrgaMon kümmert sich um <u>eine</u> langbestehende TCP-Clientverbindung (KEEP_ALIVE)
| |
| * HTTPS:// TLS 1.3 (nichts anderes!)
| |
| * Clients, die NICHT die "Server Name Indication (SNI) extension" liefern werden abgelehnt
| |
| * Target ist win64 und linux
| |
| * openSSL Lib der Version 3.1 oder besser wird verwendet
| |
| * die Verbindung bleibt ständig bestehen
| |
| * Test https://tools.keycdn.com/http2-test
| |
|
| |
| === Implementierung TCP ===
| |
|
| |
| {|
| |
| |[[Datei:HTTP2.png|220px]]
| |
| |[[Datei:SrvOrgaMon.png|220px]]
| |
| |}
| |
|
| |
| * unit HPACK.pas erstellen (Quelle github)
| |
| * testen mit https://github.com/http2jp/hpack-test-case (uses json)
| |
| * unit HTTP2Server.pas erstellen (https://github.com/nghttp2/nghttp2)
| |
| * ev. auch mit https://python-hyper.org/h2/en/stable/index.html und Kopplung über das WSGI Interface
| |
|
| |
| ==== Test ====
| |
|
| |
| Sollte dein cOrgaMon-Host ROM heissen:
| |
|
| |
| * openssl s_client -debug -servername <i><b>rom</b></i> -connect <b><i>rom</i></b>:443
| |
|
| |
| Sollte interessant sein, was der Server so liefert, kann man das in eine Datei umleiten:
| |
|
| |
|
| |
| #
| |
| # openssl s_client -servername rom -nextprotoneg "h2,h3" -sess_out out.http2 -connect rom:443 >o.http2
| |
| #
| |
|
| |
| #
| |
| # hexdump -C o.http2
| |
| # (leider ist ein openssl interner Prefix nicht vermeidbar, aber ab einer gewissen Position gehts los!)
| |
| #
| |
|
| |
| 00000df0 28 73 65 6c 66 20 73 69 67 6e 65 64 20 63 65 72 |(self signed cer|
| |
| 00000e00 74 69 66 69 63 61 74 65 29 0a 2d 2d 2d 0a 50 52 |tificate).---.PR|
| |
| 00000e10 49 20 2a 20 48 54 54 50 2f 32 2e 30 0d 0a 0d 0a |I * HTTP/2.0....|
| |
| 00000e20 53 4d 0d 0a 0d 0a 00 00 18 04 00 00 00 00 00 00 |SM..............|
| |
| 00000e30 01 00 00 10 00 00 03 00 00 00 65 00 04 00 00 ff |..........e.....|
| |
| 00000e40 ff 00 05 00 10 00 00 00 00 04 08 00 00 00 00 00 |................|
| |
| 00000e50 00 0a 00 00 |....|
| |
| 00000e54
| |
|
| |
| === Aufbau ===
| |
|
| |
| [[Datei:HTTP2-Units.png|300px]]
| |
|
| |
| ==== HTTP2 ====
| |
|
| |
| * Zentrale Steuerunit für den HTTP2 Server
| |
| * Öffnet und Schliesst die Verbindung, dabei wird die openSSL entsprechend Konfiguriert
| |
| * Beobachtet die Verbindungsaushandlung
| |
| * Lehnt ungeeignetes ab
| |
| * Verhindert Fallbacks in unsichere Technik
| |
| * Verarbeitet den Server-Domain Namen Callback
| |
| * Stellt .pem und .cert zur Verfügung
| |
|
| |
| * implementiert den Datenmultiplexer laut RFC, fügt also den fragmentierten Netzwerkverkehr wieder in geordnete Bahnen
| |
| * Feuert Events wenn Daten "fertig" vorliegen an HTTP2
| |
|
| |
| typischer HTTP/2 Content am Anfang der Verbindung.
| |
|
| |
| Client -> Server
| |
|
| |
| 50 52 49 20 2A 20 48 54 54 50 2F 32 2E 30 0D 0A PRI.*.HTTP/2.0..
| |
| 0D 0A 53 4D 0D 0A 0D 0A
| |
| 00 00 12 (18 Bytes Content)
| |
| 04 00 00 00 00 00 SETTINGS, also 3 Settings!)
| |
| 00 01 00 01 00 00
| |
| 00 04 00 02 00 00
| |
| 00 05 00 00 40 00
| |
| 00 00 04 (4 Bytes content)
| |
| 08 00 00 00 00 00 WINDOW_UPDATE
| |
| 00 BF 00 01
| |
| 00 00 05 (5 Bytes Content)
| |
| 02 00 00 00 00 03 PRIO
| |
| 00 00 00 00 C8
| |
| 00 00 05 (5 Bytes Content)
| |
| 02 00 00 00 00 05 PRIO
| |
| 00 00 00 00 64
| |
| 00 00 05 (5 Bytes Content)
| |
| 02 00 00 00 00 07 PRIO
| |
| 00 00 00 00 00
| |
| 00 00 05 (5 Bytes Content)
| |
| 02 00 00 00 00 09 PRIO
| |
| 00 00 00 07 00
| |
| 00 00 05 (5 Bytes Content)
| |
| 02 00 00 00 00 0B PRIO
| |
| 00 00 00 03 00
| |
|
| |
|
| |
| FRAME_SETTINGS
| |
| HEADER_TABLE_SIZE 65536
| |
| INITIAL_WINDOW_SIZE 131072
| |
| MAX_FRAME_SIZE 16384
| |
| FRAME_WINDOW_UPDATE
| |
| 0 has Window_Size_Increment 12517377
| |
| FRAME_PRIORITY
| |
| Stream 3.0 has 200
| |
| FRAME_PRIORITY
| |
| Stream 5.0 has 100
| |
| FRAME_PRIORITY
| |
| Stream 7.0 has 0
| |
| FRAME_PRIORITY
| |
| Stream 9.7 has 0
| |
| FRAME_PRIORITY
| |
| Stream 11.3 has 0
| |
|
| |
| ==== HMUX ====
| |
|
| |
| <i>Entfällt, wurde in HTTP2 integriert</i>
| |
|
| |
| ==== HPACK ====
| |
|
| |
| * implementiert die Header Compression laut RFC
| |
|
| |
| ==== cryptossl ====
| |
|
| |
| * spricht mit der openSSL Bibliothek und implementiert dabei nur was gebraucht wird.
| |
|
| |
| ==== Informationsquellen ====
| |
|
| |
| * https://stackoverflow.com/questions/19029647/ssl-ctx-use-privatekey-file-failed
| |
| * https://letsencrypt.org
| |
| * https://github.com/certbot/certbot
| |
| * Der Client MUSS den Servername mitteilen damit cOrgaMon erkennen kann welcher Mandant geladen werden soll
| |
| ** https://tools.ietf.org/html/rfc6066
| |
| * auf diesen Server-Namen MUSS Certifikat Pinnig angewendet werden, er darf also KEIN anderes Zertifikat verwendet werden
| |
| ** https://tools.ietf.org/html/rfc7469
| |
|
| |
| ==== Schritt für Schritt mit Lets Encrypt ====
| |
|
| |
| Wir sind als in Besitz einer Domain und haben es geschafft Port 80 auf die eigene WIndows 10 Kiste zu lenken
| |
|
| |
| * Sorry, aber wir brauchen als erstes einen HTTP Webserver
| |
| * https://www.windowspro.de/wolfgang-sommergut/web-server-iis-windows-10-installieren-konfigurieren
| |
|
| |
| * letsencrypt-win-simple.V1.9.3.zip
| |
| * https://github.com/Lone-Coder/letsencrypt-win-simple/releases
| |
|
| |
| == Paralleles Arbeiten ==
| |
|
| |
|
| |
| * Ein einzelner OrgaMon-Prozess ist für eine dauerhafte TCP/Connection zuständig
| |
| * Ich denke dass mit OpenSSL 3.5 QUIC Server Support kommt (https://github.com/openssl/openssl/commit/cb629550cdab518c925e9b402e11b86497a03845)
| |
|
| |
| === Thread: SSL_read() ===
| |
|
| |
| * Ein Thread sollte SSL_read ausführen, wenn da ein Datenblock oder FRAME fertig ist, sollte dieser als "EventProc" an den Main-Thread übergeben werden
| |
| ** https://github.com/BeRo1985/pasmp
| |
|
| |
| === Thread: JOBs ===
| |
|
| |
| * Möglicherweise startet OrgaMon wiederum SubProgramme mit langen Laufzeiten, diese SubProgramme schreiben Status Infos in memcached
| |
| * Rückmeldungen dieser lang laufenden Prozesse ev. über https://developer.mozilla.org/de/docs/Web/API/Push_API
| |
|
| |
| == Pascal -> JavaScript ==
| |
|
| |
| Durch den Wegfall der GUI muss Code auf der Client GUI autark laufen können. Dieser soll im OrgaMon Programm als FreePascal-Code aufnotiert werden, die compilierung teilt den Code auf (Client Code / Server Code) und verteilt das Java-Script über den HTTP2 Server. Freepascal hat schon eine Implementierung die Pascal nach JS ermöglicht.
| |
|
| |
| Details:
| |
|
| |
| * Die Tatsache "JavaScript" auf der Clientside wird der Lazarus-IDE scheinbar verheimlicht
| |
| ** Es muss also der Pascalcode in JavaScript umgewandelt werden
| |
| ** Für den Client muss eine Art Code-Lib zur Verfügung stehen, die Pascal rufen kann und umgekehrt
| |
| * Die IDE soll denken/vorleben das Client-Seitig auch "Pascal" gesprochen wird
| |
| ** Debugging: Hier muss der WebClient in den remote-Debugging Modus gebracht werden
| |
| *** https://developer.mozilla.org/en-US/docs/Tools/Remote_Debugging
| |
| ** Es könnte die Infrastruktur der "Source maps" verwendet werden, also "komprimierte" Zeilen des JavaScript Quellcodes zeigen auf die entsprechenden Zeilen, die in FreePascal formuliert sind. Es werden also "fake"-Source-Maps zur Verfügung gestellt, so das eine korrekte 1:1 Beziehung zwischen Pascal und Javascript bestehen kann.
| |
| ** FreePascal und die Lazarus IDE müssen lernen, dass Teile vom Quelltext "remote" executables sind
| |
| ** FreePascal Lazarus muss Möglichkeiten bieten von einem eintretendem JAvaScript Breakpoint gerufen zu werden
| |
|
| |
| ** Es soll alles auch in der Lazarus IDE mit Break-Points programmierbar sein, die IDE soll ein Verständnis haben welche Zeile welchen Code verbirgt
| |
| * Die IDE sollte den Client-Side Part ev. farblich hinterlegen?!
| |
| * Es muss so sein, dass eine Unit weiterhin ServerSide- / ClientSide- Code mischen kann
| |
|
| |
| program SimpleCalculator;
| |
|
| |
| var
| |
| Panel : TPanel;
| |
| Button1 : TButton;
| |
| Button2 : TButton;
| |
|
| |
| procedure Panel.OnClick;
| |
| begin
| |
| beep; // This goes to JavaScript Client Code
| |
| end;
| |
|
| |
| procedure Button1.OnClick;
| |
| begin
| |
| Button2.Disable; // This goes to JavaScript Client Code
| |
| end;
| |
|
| |
| procedure Button1.OnClick;
| |
| begin
| |
| Button2.Disable; // This goes to JavaScript Client Code
| |
| end;
| |
|
| |
| begin
| |
| App.add(Panel);
| |
| App.add(Button1);
| |
| App.add(Button2);
| |
| end.
| |
|
| |
|
| |
| * die IDE soll ein Verständnis haben dass auf Client-Seite nicht "alles" Programmierbar ist
| |
| * aus den JavaScript Parts soll über einen Dispatcher der nonGUI Code aufbar gemacht werden
| |
| * In einer Datenbank soll das Know-How für die Web Objekte gespeichert sein
| |
|
| |
|
| == Retry-, Reconnect- Fähig == | | == Retry-, Reconnect- Fähig == |
| Zeile 343: |
Zeile 53: |
| * Ein kleines Symbol oder eine Uhr, oder ich weis noch nicht, soll symbolisieren wenn es sich um eine frisch aufgebaute Verbindung handelt | | * Ein kleines Symbol oder eine Uhr, oder ich weis noch nicht, soll symbolisieren wenn es sich um eine frisch aufgebaute Verbindung handelt |
| * Es. soll eine Reconnect auch visualisiert werden, oder auch ein Verbindungsende / Abbruch | | * Es. soll eine Reconnect auch visualisiert werden, oder auch ein Verbindungsende / Abbruch |
| * In der Anfangszeit brauche ich aber ein Feedback das mir beweist dass NICHT immer neue TCP verbindungen aufgebaut werden | | * Die Dev Tools haben im "Netzwerk" ein Toggle oder OFFLINE Knopf um das zu testen |
| * Der HTTP/2 Server soll eine Modus haben, wo er nur EINE Verbindung EINER IP akzetiert
| |
|
| |
|
| == Meilensteine == | | == Meilensteine == |
|
| |
|
| | 20.03.2026 SSE für /log in die Client Console |
| 08.12.2023 Feature Freeze: Funktionalität für ServiceWorker und sqlite3.wasm Test ausreichend | | 08.12.2023 Feature Freeze: Funktionalität für ServiceWorker und sqlite3.wasm Test ausreichend |
| 01.12.2023 RFC: "WINDOW_UPDATE" verbessert | | 01.12.2023 RFC: "WINDOW_UPDATE" verbessert |
| Zeile 366: |
Zeile 76: |
| == todo == | | == todo == |
|
| |
|
| * Linux Version
| |
| * HTTP/2 erste Login Seite | | * HTTP/2 erste Login Seite |
| * OLAP -> Migration auf Console | | * OLAP -> Migration auf Console |
| * Auswertung -> Migration auf Console | | * Auswertung -> Migration auf Console |
| * OrgaMon Workflow Sheet?! | | * OrgaMon Workflow Sheet?! |
| | * zstd shared-compression-dictionaries |
|
| |
|
| == Screen-Shots == | | == Screen-Shots == |
|
| |
|
| [[Datei:PolyZalos-0.png|200px]] | | [[Datei:PolyZalos-0.png|200px]] |