Fixing FreeIPA ACME


I've managed to fix one of the recent problems with my FreeIPA. To be more specific – after few months breakage, ACME issuer is working again for me.

Solution was dead simple after I've found the relevant line in the logs:

2024-02-07 21:59:24 [ajp-nio-0:0:0:0:0:0:0:1-8009-exec-3]
SEVERE: Servlet.service() for servlet [ACME] in context with path [/acme] threw exception
org.jboss.resteasy.spi.UnhandledException: com.netscape.certsrv.base.UnauthorizedException:
Authorization failed: Authorization failed on resource: group=Certificate Manager Agents, operation: {1}

I've fired up an LDAP client (I'm using JXplorer), went to /ipaca/groups/Certificate Manager Agents and added two records. Type uniqueMember with value uid=acme-kaitain.pipebreaker.pl,ou=people,o=ipaca, plus another one for the second replica. FreeIPA started to issue certificates again, although there are still some strange trackbacks in the logs.

Why the group membership dissapeared? I don't know.

Woes with FreeIPA and SIDs


Sid (from Ice Age)

As cool as FreeIPA is – I'm using it for over 10 years at home – sometimes I fell it breaks just by being looked at.

TLDR: If you have accounts or groups with UID or GID not falling in any defined range ID ranges, fix that by any of: 1) changing the UID/GID; 2) extending defined ID range; 3) creating a new ID range covering those UIDs/GIDs.

Then generate new SIDs with ipa config-mod --enable-sid --add-sids.

Few months ago my FreeIPA installation stopped allowing users to login. It was mostly a nuisance for me, nothing critical:

  • on most important computers I have local accounts

  • services authenticating with plain LDAP continued to work

  • so what didn't work? Login into FreeIPA's web interface. But admin accounted worked, so…

When I eventually started to debug, I found following logs in krb5kdc.log:

krb5kdc[3123](info): AS_REQ : handle_authdata (2)
krb5kdc[3123](info): AS_REQ (6 etypes {aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19),
aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), camellia256-cts-cmac(26),
camellia128-cts-cmac(25)}) 192.168.x.x: HANDLE_AUTHDATA: zdzichu@PIPEBREAKER.PL for krbtgt/PIPEBREAKER.PL@PIPEBREAKER.PL, No such file or directory

Some searching the web later, I've concluded No such file or directory refers to SID, a Security Identifier. SIDs are some Microsoft's Active Directory properties. I see no reason to have them on Linux-only FreeIPA installs.

The Upgrade section in the documentation is wrong:

The upgrade does not turn on the feature. If the admin wants to enable SID generation, he needs to update the packages and run the new command

It's not true, admin desires don't matter. As Alexander Bokovoy wrote on the mailing list:

FreeIPA generates SIDs by default since FreeIPA 4.9.8. It is configured to do so on new installations even when integration with AD is not considered, due to tightened requirements to process constrained delegation in Kerberos.

So SIDs are really required in FreeIPA now. I don't want them, but whatever. There is a command which is supposed to generate missing data:

ipa config-mod --enable-sid --add-sids

It finished without errors, but login still didn't work.

More searching. The commands fires up a job (in LDAP server?) so let look into dirsvr's errors.log:

[12/Jan/2024:14:07:51.524937136 +0100] - ERR - sidgen_task_thread - [file ipa_sidgen_task.c, line 194]: Sidgen task starts ...
[12/Jan/2024:14:07:51.566941696 +0100] - ERR - find_sid_for_ldap_entry - [file ipa_sidgen_common.c, line 521]: Cannot convert Posix ID [135] into an unused SID.
[12/Jan/2024:14:07:51.585948214 +0100] - ERR - do_work - [file ipa_sidgen_task.c, line 154]: Cannot add SID to existing entry.
[12/Jan/2024:14:07:51.597088076 +0100] - ERR - sidgen_task_thread - [file ipa_sidgen_task.c, line 199]: Sidgen task finished [32].

OK, we're getting somewhere. I had some an obsolete group defined with GID 135. Let's remove it and re-run the command.

[12/Jan/2024:14:24:29.879953617 +0100] - ERR - find_sid_for_ldap_entry - [file ipa_sidgen_common.c, line 521]: Cannot convert Posix ID [1037] into an unused SID

I know this UID, this is one of the users I've migrated to FreeIPA. Obviously I cannot remove it.

Turns out, FreeIPA has something called ID ranges. If you have accounts or groups with UID or GID not falling in any defined range, sidgen script just fails.

I had to go to IPA Server -> ID Ranges -> Add in web console and make changes. I did not want to mess with already defined ranges, so I created a new one. An “unix” range. Base 1000, size 1000, had to guess some numbers for RID ranges before it was accepted.

Not that I'm so smart to figure it out. There's Knowledgebase solution 394763 for exactly this problem.

And just like that, kerberized login to FreeIPA started working again.

Knowing what was wrong, I've started noticing (and understanding) other people have the same kind of issues.

One problem down, two to go. Replication between my replicas is not working. Again with unhelpful message:

[12/Jan/2024:14:33:32.812986996 +0100] - ERR - NSMMReplicationPlugin - acquire_replica - agmt="cn=kaitain.pipebreaker.pl-to-okda.pipebreaker.pl" (okda:389): Unable to acquire replica: permission denied. The bind dn "" does not have permission to supply replication updates to the replica. Will retry later.

I did all the steps from KB 2988311 but it didn't help.

Second problem, ACME on FreeIPA ceased to work for me.

I hadn't had willpower to debug these two, yet.

How systemd exponential restart delay works


Since the beginning, systemd had a Restart= directive to do just that – restart a service when it fails or exists. Some tuning was provided by RestartSec= (how long to wait between restarts), StartLimitBurst= (how many times to try) and few minor directives.

Starting with systemd v254, we have two new knobs:

  • RestartSteps= the number of steps to take to increase the interval of auto-restarts

  • RestartMaxDelaySec= the longest time to sleep before restarting a service as the interval goes up

Together, they provide ability to exponentially extend wait-time between restarts. First restart is quite quick, but then system waits more and more. Here what it means.

Let assume a service with following settings:

Restart=always
RestartSec=100ms (the default)
RestartMaxDelaySec=10s
RestartSteps=5

Upon a failure, systemd will wait (rounded a bit):

  1. 100ms until first restart

  2. 250ms until next restart (first step)

  3. 630ms until next restart (second step)

  4. 1.58s until next restart (third step)

  5. 3.98s until next restart (fourth step)

  6. 10.0s until next restart (RestartSteps=5 – fifth step) and following restarts

Second example. Given:

RestartSec=1s
RestartMaxDelaySec=10s
RestartSteps=3

subsequent restarts will be done after waiting:

  1. 100ms

  2. 2.15s (step 1)

  3. 4.64s (step 2)

  4. 10.0s (step 3, as in RestartSteps=3).

Hope this helps. You can find the exact formula in src/core/service.c.

Logitus → Netia


Firma Logitus, od kilku lat mój dostawca internetu, została w tym roku przejęta przez Netię. Moja dotychczasowa umowa właśnie wygasła, więc zostałem przełączony na netiową infrastrukturę.

Mimo zapewnień konsultantki z infolinii, że nic się w dostępie nie zmieni, pierwsza wizyta technika zakończyła się niepowodzeniem. Otóż chciał on przekonfigurować mój router¹, bo jednak technologia dostępu się zmieniła! Zamiast zwykłego DHCP – Netia używa PPP-over-Ethernet.

¹ Moim routerem jest po prostu domowy serwer (sieć dostawcy mam podłączoną po switcha na dedykowanym VLANie), do zmiany na pppoe nie byłem gotowy. Musieliśmy spotkać się tydzień później, a ja w międzyczasie zrobiłem research.

Następnym razem się udało, ale jakim kosztem. Mam silne flashbacki sprzed 25 lat, kiedy to ostatni raz używałem pppd. Niewiele się tu zmieniło. Wciąż brakuje sensownych wartości domyślnych, więc plik konfiguracyjny puchnie przy każdej usterce.

Do pięknie zintegrowanej konfiguracji sieciowej w systemd-networkd trzeba było dołączyć osobnego demona pppd, żyjącego w swoim świecie, więc całość wygląda teraz jak powiązana sznurkami. Znowu nie obyło się bez skryptów ip-up poprawiających konfigurację po nawiązaniu połączenia. W tym przypadku – do którego urządzenia sieciowego ma się przypinać tunel SIT do Hurricane Electric. Tak, Netia w mojej okolicy w dalszym ciągu nie ogarnia IPv6.

Jedyny powiew świeżości to możliwość monitorowania łącza. Przekompilowałem pppd w Fedorze z jedną łatką z wersji 2.5.1, dzięki mój Prometheus zbiera trochę statystyk (chociaż pośredniczy w tym skrypt w… Perlu, udający CGI). Z tego wykresik rysuje Grafana. Stały narzut PPPoE to prawie 3ms opóźnienia na LCP echo request-reply (taki ping w warstwie łącza danych), czasami skacze do kilkunastu ms.

Wykres z grafany z minimalnymi i maksymalnymi opóźnieniami LCP

Wyraźnie widać też zwiększenie opóźnień o 4-5ms na wykresach rysowanych przez Smokeping:

Wykres ze smokeping do biall.net.plWykres ze smokeping do forum gazeta.pl

Pierwsza „awaria” miała miejsce już po tygodniu. O 23:57 przestało cokolwiek przychodzić, pomimo nawiązanej sesji i wymagany był restart pppd. Normalnie jak z modemami w ubiegłym wieku.

Podsumowując, z Netią jest obiektywnie gorzej niż było w Logitusie. Pierwsza faktura na 0zł też nie jest plusem, miewałem takie u poprzedniego dostawcy. A dane na niej nie działają w panelu Netia Online.

Obecnie używam z Netią poniższej konfiguracji pppd, a definicję dla systemd oparłem na znalezionej tutaj.

# With  this option, the peer will have to supply the local IP address during IPCP negotiation
noipdefault

defaultroute

# Do not require the peer to authenticate itself.
noauth

# Do not exit after a connection is terminated; instead try to reopen the connection
persist

# Specifies how many seconds to wait before re-initiating the link after it terminates.
holdoff 2

# I've got one silent break in connectivity, restarting pppd helped
# add pinging the other end to monitor this
# send an LCP echo-request frame to the peer every n seconds
lcp-echo-interval 2
# will presume the peer to be dead if n LCP echo-requests are sent without receiving a valid LCP echo-reply
lcp-echo-failure 3
# will send LCP echo-request frames only if no traffic was received from the peer
# unfortunately, will cause ppp-rtt data to be empty if the traffic is constant
#lcp-echo-adaptive

# with 2.5.1 + prometheus exporter as a perl script
lcp-rtt-file /run/ppp-rtt.data

## Don't detach from the controlling terminal.
#nodetach
# Use  this option to run pppd in systemd service units of Type=notify (up_sdnotify implies nodetach).
up_sdnotify

plugin pppoe.so

# Use the ethernet device interface to communicate with the peer
nic-vl2isp
# Set the ppp interface name for outbound connections.
ifname pppoe-netia

user "5l3d21u@bn24.pl"

Shelly są wporzo


Mam bardzo pozytywne odczucie związane ze smart kontrolerami marki Shelly.

Większość sterowania w domu mam polutowane na bazie modułów Sonoff i d1mini. We wszystkich wgrywałem lub wymieniałem firmware, żeby mieć:

  • w pełni lokalne działanie, bez jakieś chińskiej chmury

  • obsługę MQTT do integracji

Ostatnio kupiłem modulik z serii Shelly mini… i po krótkiej analizie zostawiłem oryginalne oprogramowanie. Bo wszystko ma.

Zdjęcie 3 modułów z serii Shelly Mini

Moduły są całkiem małe (29×35×16mm), przy odrobinie szczęścia można je upchnąć w puszce pod włącznikiem. MQTT w standardzie (a także obsługa webhooków, websocketów i własnego JSON-RPC po UDP). Procesor ESP32 wystarcza to komunikacji z użyciem TLS. Niestety sieciowo zaimplementowano jedynie IPv4.

Interfejs webowy jest czytelny i przemyślany. Np. koło adresu MAC jest wygodny przycisk kopiujący go do schowka.

Interfejs webowy Shelly

Tak, przy okazji mierzy zużyte kWh. Oprócz tego podstawowe terminarze i akcje można zakodować bezpośrednio na kontrolerze. W opcjach jest opcja repeatera WiFi, prawdopodobnie można na bazie tych modułów zrobić mesh.

Jeśli dać tym urządzonkom dostęp do internetu, z poziomu tego interfejsu można też zaktualizowaź firmware do najnowszego stabilnego lub beta.

Na stronach Shelly wszystkie funkcje i API są dobrze udokumentowane. Podłączenie pod mojego OpenHABa zajęło mi mniej niż kwadrans. Do nowszych wersji OpenHAB są nawet natywne bindingi.

Shelly dostaje moją foczkę aprobaty.

Stacja pogodowa po taniości


Jak najtaniej kupić stację pogodową? Wcale nie kupować. Sąsiedzi z pewnością już jakieś mają, a każdy szanujący się haker ma jakiś odbiornik SDR w szufladzie.

rtl_433 „z pudełka” obsługuje ponad 200 różnych protokołów i ma bardzo przyjemny wysyłacz MQTT.

/dżogstaff/2023.10.12-temperatury.png

Wyraźnie widać, że któryś sąsiad powiesił termometr w nasłonecznionym miejscu ;)

Fun fact: większość czujników ciśnienia, w kołach samochodów na parkingu pod blokiem, wysyła też informacje o swojej temperaturze.

Ech, ECH


Twórcy przeglądarek w końcu ogarnęli się z kluczowym elementem ukrywania z jakimi stronami się łączymy, czyli prywatność++. Bo o ile wymieniane dane są szyfrowane przez TLS, to zanim to nastąpi przeglądarka WWW musi powiedzieć z jaką stroną chce gadać. Te informacje są (były) widoczne dla wszystkich. Taki niezaufany obserwator może nie wiedzieć co robimy, ale z samego faktu połączenia z http://szybkiewypo.pl może coś tam wywnioskować.

Ta nieszyfrowana informacja nazywa się Server Name Indicator (SNI). Jej zachowująca prywatność wersja to Encrypted SNI (ESNI), które przez kilka lat się nie przyjęło. Ostatnio jednak udało się dopracować standard i jako Encrypted Client Hello (ECH) zostało włączone w popularnych przeglądarkach.

Działanie można sprawdzić na https://tls-ech.dev/. Uzbrojony w Chrome 117.0.5938.149 kliknąłem i…

You are not using ECH. :(

Co jest, powinno działać! Sprawdziłem #encrypted-client-hello we flagsach – włączone. Inna przeglądarka? W Mozzarella Firefox 118.0.1 tak samo nie działa. Podejrzane.

Zacząłem trochę researchu, czytania. I znalazłem dwie poszlaki. W opisie ficzera w Chrome mamy taki zapis:

While supported on all platforms, ECH requires keys fetched via DNS in the new HTTPS record. Chrome can currently fetch the HTTPS record over DoH and over our built-in DNS resolver. As of writing, the built-in DNS resolver is not yet enabled.

Podobne z Firefoksem:

No, but DoH is required by Firefox to get ESNI going so please first make sure you have that enabled!

DoH to oczywiście DNS-over-HTTPS. Spoko funkcjonalność, ale akurat mam ją wyłączoną w mojej domowej sieci. Wprowadziłem blokowanie reklam na poziomie lokalnego DNS (bazy z PiHole). Szkoda by było, jakby kogoś z domowników czy gości tego nie objęło, bo przeglądarka postanowiła rozwiązywać nazwy na własną rekę.

Tak więc w obecnych implementacjach przeglądarki używają ECH jedynie w powiązaniu z DoH. Moim zdaniem niesłusznie. Nie ufają lokalnym DNSom, które mogą być spoko. Pozwalają jednocześnie na podsłuchiwanie negocjacji TLS gdzieś „po drodze”. Ignorują inne bezpieczne sposoby rozwiązywania nazw (DNS-over-TLS, DNS-over-TOR itp).

Czynią mnie smutnym.

20 lat pisania bloga


Właśnie stuknęła w miarę równa rocznica mojego pisania na tym blogu. Pierwszy post pojawił się równo 20 lat temu. Uff!

Zaczęło się na serwisie Jogger, a gdy ten skończył działalność – przeniosłem wypociny na własny serwer. W międzyczasie próbowałem też publikacji na Google+. Też już nie działa, ale wpisy stamtąd zintegrowałem z resztą treści.

Początek był w zasadzie przypadkowy. Byłem w tamtym czasie developerem EKG2, to jest multikomunikatora. Wersja pierwsza obsługiwała tylko sieć Gadu-Gadu, ja w drugiej rozwijałem wsparcie protokołu Jabber/XMPP. Jogger był serwisem który umożliwiał publikowanie poprzez wysyłanie wiadomości Jabberem. Doskonały sposób na testowanie działania swojego kodu.

Przy okazji Joggera, super rozwiązaniem budującym społeczność była publikacja wszystkich notek na głównej stronie serwisu. To taka namiasta Planety, czyli agregatora różnych blogów. Po zamknięciu Joggera i wielkim rozproszeniu joggerowców, powstała nowa planeta zrzeszająca osoby stamtąd.

Jak to bywa na początku, poza wpisami testowymi nie wiedziałem za bardzo o czym blogować. Próbowałem recenzować oglądane filmy, eksternalizowałem przejścia na uczelni, próbowałem ''polemiki w internecie''. Generalnie bez większych sukcesów. Najbardziej chyba podchodziły mi wpisy techniczne. Może bez konkretnych tematów, ale mam nadzieję pomocne, gdy któryś zostanie komuś wskazany przez wyszukiwarkę.

Dekadę temu miałem okres, gdy ucząc się nowej technologii robiłem tak jakby jakby notatek. Mi to się przydało – pomagało w sensownym ułożeniu nowej wiedzy, natomiast dla innych użyteczność była znikoma.

W miedzyczasie zostałem deweloperem Fedora Linux, która również ma swoją planetę. Aby tam publikować zacząłem czasem pisać po angielsku, notki są oznaczone odpowiednim tagiem.

Nigdy nie dałem rady publikować regularnie. Jakiś czas temu próbowałem utrzymać tempo co najmniej jednego wpisu miesięcznie, ale nie udało się. Chociaż zawsze jest o czym pisać, to Dunning-Kruger wchodzi mocno. Jak coś poznajemy, to na początku często jest euforia. Super, świetna sprawa, świat musi się o niej dowiedzieć. I wtedy łatwo pisać. Z czasem wchodzą refleksje. E, dopiero to poznaję, na pewno jest mnóstwo wpisów specjalistów w tej dziedzinie (pewnie nawet je właśnie czytam ucząc się), bez sensu pisać.

Wtedy trzeba sobie uświadomić, że w każdej chwili jest dużo osób które są na początku naszej drogi. I dla nich zasygnalizowanie jakiegoś tematu jest cenne, daje punkt zaczepienia i może stać się początkiem niezłej przygody. Z myślą o nich warto pisać.

Podsumowując. Przegladając moje wpisy z dwóch dekad łatwo znajduję takie, do których bym się nie przyznał. Zwłaszcza te z G+. Pokazywanie, że się ma silne opinie nie polega na byciu opryskliwym. Brak szacunku dla innych nie jest oznaką niczego dobrego. Na szczęście przeszło mi to lata temu i z nowszych notek jestem zadowolony.

A Ta notka powstawała przez prawie pół roku, chyba najdłużej ze wszystkich dotychczasowych. 2,5% czasu istnienia bloga :) 20 lat temu byłem studentem. Teraz pracuję. Za 20 lat będę dalej pracował, chociaż za rogiem będzie już emerytura. A czy będzie jeszcze kolejne 20… to się zobaczy.

Atakowanie problemu od różnych stron


Dzisiaj napiszę o sieciach (mój konik), problemie z opóźnieniami i dwóch rozwiązaniach (krótko- i długoterminowym).

Problem

Problem miała firma Meta (wtedy jeszcze nazywała się Facebook), a winne były: geografia i fizyka. Pierwsza, bo firma serwerownie miała tylko w Stanach Zjednoczonych, natomiast produkt^W klientów np. w Azji. Druga, fizyka – bo światło z Indii do Kalifornii leci prawie 50 milisekund, a w światłowodzie to, o panie!, nawet 75 ms.

Trzecim winnym jest historyczny stos protokołów – TCP/IP, HTTP, TLS. I ich gadatliwość, zanim można coś użytecznego odebrać. Pamiętając o tych nieskracalnych 75 milisekundach w jedną stronę, wyobraźmy sobie Prakesha chcącego otworzyć stronę Facebook. Załóżmy, że lokalny DNS zna już adres IP.

Nawiązanie połączenia TCP/IP wymaga wymiany przez obie strony 3 pakietów (z flagamia SYN→, SYN+ACK← i ACK→). Zestawienie połączenia musi potrwać co najmniej 225 milisekund.

Cool, możemy rozmawiać z serwerem FB. No to uzgodnijmy szyfrowanie, powiedzmy TLS1.2. Ta pogadanka to już 4 pakiety. Kolejne +300 milisekund przy dobrych wiatrach.

Teraz już możemy wysłać zapytanie HTTP (+75ms) i dostać odpowiedź (+75ms).

W ten sposób od żądania do otrzymania pierwszego bajtu minęło prawie ¾ sekundy. O ile Prakesh jeszcze czeka (bo przy obecnych attention spans mógł już się znudzić i pójść gdzieś indziej), zacznie mu się powoli ładować strona Facebooka. Powoli, bo każdy element strony to osobne zapytanie i odpowiedź HTTP (+150ms).

Jeśli przeglądarka jest w miarę ogarnięta, to otworzy kilka połączeń i będzie równolegle wysyłać zapytania. „W locie” możemy mieć dużo pakietów, ale każda między każdą parą zapytania-odpowiedzi musi minąć czas fizycznej propagacji.

Rozwiązanie na szybko

Inżynierowie Facebooka chcieli ułatwić życie użytkownik z Azji, wdrożyli więc rozwiązanie w postaci lokalnych punktów obecności (ang. points of presence, PoP). To taki punkt łączności znajdujący się (sieciowo) blisko Prakesha. Blisko, to znaczy nie 150 ms stąd, ale powiedzmy ~10 ms. Wciąż nawiązanie szyfrowanego połączenia to wymiana kilku pakietów, ale ponieważ cel jest blisko, to pierwsze pełnoprawne zapytanie można wysłać już po 50 milisekundach.

W pierwszej chwili może się wydawać, że zapytanie do PoP nie ma większego sensu. Dane i tak są przecież w serwerowni FB w Stanach, 75 ms stąd, i tam trzeba sięgnąć. Ale tutaj dzieje się ważna rzecz. PoP ma pewną pulę uprzednio zestawionych, szyfrowanych połączeń z serwerownią w USA. Nie trzeba otwierać nowego za każdym razem. Zapytanie użytkownika z Azji można od razu wysłać i po 150 ms dostać odpowiedź.

W ten sposób zamiast po 750 ms, pierwsze bajty dotrą już po 50+150+50 ms, czyli 3× szybciej. Not great, not terrible. Całość strony też załaduje się odpowiednio szybciej.

Rozwiązanie poprawne

Point-of-presence to fajny hack, ale długofalowe rozwiązanie wymagało dużych inwestycji, lat pracy i współpracy różnych podmiotów.

Lokalne serwerownie. Duży wydatek i wysiłek organizacyjny, ale też duży uzysk. Z Singapuru do Indii jest tylko 16 ms (tj. około 3,5 tys. km). Na innych kontynentach Meta też postawiła kilka lokalnych DC.

Jak inaczej można jeszcze dorzucić do pieca?

TCP Fast Open https://en.wikipedia.org/wiki/TCP_Fast_Open było próbą otwierania połączeń TCP/IP szybciej, mniejszą liczbą pakietów (pamiętamy, że każdy kosztuje nas 150 ms). Nie zażarło, ale za to…

Protokół QUIC pozbył się w ogóle TCP. “U” w nazwie jest od UDP, które jest bezpołączeniowe i pozwala zacząć rozmowę szybciej. Przyjął się, za chwilę do niego wrócimy. Jak również do zbliżonego protokołu SPDY, który próbował być szybszym HTTP z użyciem TCP.

TLS1.3. Szyfrowanie było najwolniejszym elementem nawiązywania połączenia (4 pakiety!). Opracowanie trybu 0rtt pozwoliło na nawiązywanie szyfrowanych sesji już pojedyńczą wymianą, o ile strony rozmawiały ze sobą wcześniej.

HTTP/2 i HTTP/3. W końcu samo wysyłanie zapytań o elementy strony też poprawiono. Co prawda już HTTP/1.1 z końca ubiegłego wieku pozwalało na wysłanie kilku zapytań na raz, zamiast sekwencyjnie (tzw. pipelinining), ale działało to tak se. W wyższych wersjach jest to dobrze rozwiązane. Nie musząc zestawiać nowych połączeń można dostać całą stronę szybciej.

Wspomniany wcześniej protokół SPDY był podstawą opracowania HTTP/2. Natomiast QUIC jest fundamentem na którym działa HTTP/3.

Points of Presence były sprytnym, szybkim rozwiązaniem. Dogłębne rozpykanie problemu wymagało współpracy wielu podmiotów – Meta, Google, programistów Linuksa, IETF i twórców przeglądarek. Ale dzięki temu możemy oglądać kotki szybciej.

Migrated home server to the UEFI boot


I've migrated my home server to boot using UEFI. It means suprising number of things:

  • I did something useful during my unplanned PTO days

  • Fedora's GRUB instructions are useful and precise

  • I was really wrong in my rant couple years ago. Although I had to switch firmware into Windows 8 (no CSM) mode today.

  • the server is ready for modernization later this year, the upgrade of fives: some AMD Ryzen 7xxx (AM5 socket), DDR5, PCIe5. Packed in a SSUPD Meshroom S case. Getting back to the integrated GPU and hopefully lowering power consumption (now it idles at around 90W🙁)

  • I can unsubscribe from BIOS Boot SIG, as this was my last legacy-booting computer. The SIG mailing list is completely empty, apparently all the ruckus with needing BIOS booting within Fedora has no real standing.

Elektromobilność mini


Po kilku latach pracy zdalnej noszę się z zamiarem sprzedaży jednego z samochodów. Głównie stoi pod blokiem, więc co go ruszę to się psuje. Ale komunikacja miejska jest w Gdańsku fatalna, Traficar nie zawsze jest w okolicy, taksówek nie lubię, a czasem trzeba gdzieś dojechać.

Do tego pora też już na kryzys wieku średniego. Jeździć na Harley Davidsonie Żona mi nie pozwala. Więc może kupić sobie elektryka? Zbiegiem okoliczności, w zeszłym roku zacząłem poruszać się nieślubnym dzieckiem motoru i samochodu elektrycznego.

Udział w konferencji KubeCon NA 2022 zakończyłem z hulajnogą elektryczną (dzięki, CloudCasa!). Stuknęło mi właśnie 640 przejechanych kilometrów, więc pora na trochę refleksji. Spoiler alert – jest fun!

Gdańsk jak wiadomo jest miastem górzystym. Mieszkam na 90m n.p.m, jadąc np. na ściankę wspinaczkową muszę przekroczyć punkt o wysokości 111m. Rowerem jest to już dla mnie męczące. Hulajka daje radę, chociaż na niektórych podjazdach znacząco zwalnia. Będzie lepiej jak schudnę ;)

Zasięg po mieście nie stanowi problemu, ale też najdłuższą trasę jaką zrobiłem to do Schroniska Promyk i z powrotem. Około 30 km, przewyższenia 70 metrów. Nawet na imprezę w Sopocie wolałem pojechać jednośladem niż komunikacją miejską. W jedną stronę godzinka, trasę powrotną hulajnoga zrobiła w bagażniku taksówki.

Zaskoczyły mnie czasu przejazdów w porównaniu z samochodem. Na trasach miejskich, którymi jeżdżę, są… porównywalne. Na drogach dla rowerów jest dużo mniej sygnalizatorów świetlnych niż na drogach. Samochodem często stoję i czekam na zielone, w tym czasie po DDR można przejechać bez zatrzymania.

Raz miałem sytuację deszczu uniemożliwiającego szybszą jazdę. Jednak znalezienie w pobliżu samochodu z carsharing, zapakowanie pomykacza do bagażnika i powrót do domu zajęło mi więcej czasu, niż jakbym powoli jechał hulajnogą.

Cenowo ten minielektryczny pojazd jest nie do pobicia. Załadowanie do pełna w zeszłym roku kosztowało ok. 45 gr. Koszt przejechania kilometra poniżej 2 groszy!

I na koniec, co dla niektórych jest ważne: na hulajnodze wygląda się całkiem nieźle.

Pssst


Krąży po necie taki obrazek osoby, której wydaje się zabawne, że odświeżacz powietrza może mieć nadany adres IPv4:

Otóż kto poszedł w smart home, ten się w cyrku nie śmieje. No mojej liście widnieje:

7  d1mini04 - odświeżacz WC

Taki odświeżacz to w bardzo proste urządzenie. Dwie baterie i przełącznik: 9–18–36 minut. Po włączeniu, co zadany czas dźwignia naciska na chwilę ujście puszki ze środkiem zapachowym. I tak przez 24h na dobę, niezależenie czy ma to sens czy nie.

A gdyby tak…

/dżogstaff/2022.09.10-gladys.jpg

Tak rozbudowany odświeżacz:

  • ma czujnik światła; psiknięcie następuje gdy najpierw jest jasno, a potem zapada ciemność – ktoś był w WC, a potem je opuścił i zgasił światło

  • w nocy nie psika, bo na co to komu?

  • nie psika też jak jesteśmy na wyjeździe i dom jest ustawiony w tryb wakacyjny

  • a jak już odświeża, to w dowolnych interwałach, a nie trzech narzuconych przez producenta

  • liczy ile było psiknięć, co pozwala przygotować się do wymiany wkładu

/dżogstaff/2022.09.10-grafdash.png

Modyfikacja była bardzo prosta, bo pierwsze wciśnięcie dźwigni następuje zaraz po włączeniu urządzenia. Steruje więc tranzystorem podając napięcie na mechanizm. Następuje psiknięcie, tranzystor wyłączam. W OpenHAB wygląda to tak:

Switch sD1MINI04_refresh "Odświeżenie WC" <wifi> {
        mqtt=">[motherqtt:/d1mini04/gpio/14:command:ON:1],>[motherqtt:/d1mini04/gpio/14:command:OFF:0]",
        expire="6s,command=OFF"
        }
/dżogstaff/2022.09.10-openhabdash.png

Kiedyś polutowałem okap, żeby do niego gadać. Odświeżacz jest na tyle smart, że wie jak i kiedy ma robić swoją robotę. Bez gadania.

Przerwa na 3,5 tysiąca lat


Już blisko trzy lata odkąd postanowiłem przeczytać wszystkie książki z uniwersum Diuny. Koniec już widać – jeszcze tylko 5+1 książek i kilka opowiadań. Postanowiłem jednak zrobić przerwę i poczytać inne pozycje. Akurat jestem między „Dziećmi” a „Bogiem Imperatorem”, czyli w chronologii uniwersum następuje przeskok o tysiące lat. Co ciekawe, „Bóg Imperator” był pierwszą diunową książką którą kiedykolwiek przeczytałem, a było to w wakacje po 7. klasie podstawówki.

Projekt Gom Dżabbar planuję zakończyć w przyszłym roku. Wynik do przerwy:

Tytuł

Wydanie

Przeczytane

"Hunting Harkonnens"

2002

09.07.2019

The Butlerian Jihad

2002

15.08.2019

"Whipping Mek"

2003

22.08.2019

The Machine Crusade

2003

29.11.2019

The Faces of a Martyr

2004

01.12.2019

The Battle of Corrin

2004

29.01.2020

Sisterhood of Dune

2012

02.04.2020

Mentats of Dune

2014

08.06.2020

"Red Plague"

2016

08.06.2020

Navigators of Dune

2016

19.07.2020

House Atreides

1999

22.10.2020

House Harkonnen

2000

10.01.2021

House Corrino

2001

07.03.2021

Paul of Dune (Parts II, IV, VI)

2008

24.07.2021

"Wedding Silk"

2011

25.07.2021

The Winds of Dune (Part II)

2009

04.08.2021

The Duke of Caladan

2020

09.10.2021

The Lady of Caladan

2021

15.05.2022

The Heir of Caladan

2022

Dune

1965

17.10.2021

"Whisper of Caladan Seas"

2001

17.10.2021

"Blood of the Sardaukar"

2019

22.10.2021

"The Waters of Kanly"

2017

20.10.2021

Paul of Dune (Parts I, III, V, VII)

2008

21.11.2021

The Winds of Dune (Part IV)

2009

26.11.2021

"The Road to Dune"

1985

19.12.2021

Dune Messiah

1969

30.12.2021

The Winds of Dune (Parts I, III, V)

2009

22.01.2022

Children of Dune

1976

11.03.2022

God Emperor of Dune

1981

Heretics of Dune

1984

Chapterhouse: Dune

1985

"Sea Child"

2006

"Treasure in the Sand"

2006

Hunters of Dune

2006

Sandworms of Dune

2007

W przerwie mam zamiar nadrobić książki niebeletrystyczne. Zebrało się tego trochę, patrząc to co mam napoczęte i czekające na Kindle i na półce: The Manager's Path, The DevOps Handbook, The Making of a Manager, Critical Chain, Turner Diaries, Think Again, Remote, Public Speaking Fastlane, Łowcy Szpiegów, Człowiek i błędy ewolucji, The Black Swan, Antifragile, Effective DevOps, Blackout, Zones of Thought, Software Architecture for Big Data and the Cloud.

A potem… mam przeczytane kilka tomów „Gry o tron”, The Expanse kusi, Trylogia Marsjańska autorstwa Kim Stanley Robinson też, może bobiverse, serię Culture wypadało by znać, twórczość Dukaja też. TODO długie, życie krótkie.

Obvious webdevel things dump


Having just spent hours debugging simple Flask application, I need to went:

1. tzdata package in fedora-minimal container image is broken. RPM database lists files which are not installed (actually, they were removed during base container build). It's getting fixed.

Symptom: FileNotFoundError: [Errno 2] No such file or directory: '/usr/share/zoneinfo/zone.tab'

Workaround: microdnf reinstall tzdata.

2. HTML checkboxes are weird. When they are set, they appear in HTTP request data with value. When unset, they are not in the request (i.e. one cannot look for checked = False). Thus, following is enough to find if the checkbox has been checked:

if "checkbox_name" in request.form:
 

3. default-on checkboxes with state retained over POST… This one was tricky. Apparently, initialising Flask-WTForms with request data on the first load overwrites default state. Solution: use form data in POST handler only.

class SomeForm(FlaskForm):
  checkbox_name = BooleanField("Some label", default=True)

  @app.route("/", methods=["GET", "POST"])
  def main():
      # doing "form = SomeForm(request.form)" here would obliterate default checkbox state; don't do it

      if request.method == "POST":
          form = SomeForm(request.form)
          
      else:
          # not a POST? start with default, empty form
          form = SomeForm()
          

The lights are blinking, but a part of me is broken


Software neglect forces perfectly good hardware obsolete. I was suprised it could strike such basic devices as an ethernet switch.

Few years ago I bought a TP-Link gigabit switch for home network. TL-SG2216 model ticked all the boxes: 16 ports, 2 SFP slots (if I ever get FTTH), VLANs, IPv6 support and remote management, 5 years warranty. Although ssh required strange dances since the beginning (ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -oCiphers=aes256-cbc -oHostKeyAlgorithms=+ssh-dss), the HTTPS interface worked fine. Until it broke last year.

Firefox was adamant – SSL_ERROR_NO_CYPHER_OVERLAP. Chromium threw similar tantrum: ERR_SSL_VERSION_OR_CIPHER_MISMATCH. HTTPS management UI on my switch ceased to be secure enough for modern browsers. The world rushed forward, obsoleting and disabling old, unsecure algorthms and protocols. In the meantime my switch stood still. Eventually the world surpassed what was possible with TP-Link.

From my perspective, the web UI broke. I bought a switch with HTTPS management, and this feature stopped working. So, in the last days of my warranty coverage, I reported the issue to TP-Link. Long story short, it was denied on a technicality. I should have opened the issue through the distributor who sold me the switch, not directly with TP-Link. I've got this information after the warranty lapsed, which ended the story.

But frankly, I do not think TP-Link would be able to salvage this situation. I put only a tiny blame on them.

They designed the switch couple years ago. It was good enough and worked with the ecosystem of its time. They provided couple minor firmware upgrades, and after a decade on the market, EOLed the switch.

It is the world which changed.

Couple decades ago, network hardware once deployed would be working for years, practically forever. Security risks weren't so serious as we have now. No one would deprecate and remove protocols in the name of security. How long 3DES (hell, even single DES?) was with us?

Today, security is paramount. Our lifes are entwined with TCP/IP services. Protocols are phased out and improved when needed. Web browsers automatically update to newer versions. And this is good. But manufactures need to catch up. Product development cannot end when market availability starts. Fixes, updates are required to do more work to retain functionality. Even bigger changes like adding new TLS protocol needs to happen during the device lifetime. We need regulators (like EU) to enforce that.

We also need to vote with our wallets. Maybe pay a bit more, but buy from companies providing better support for their products, through their shelf-life and beyond. Couple of years ago I was dissapointed [2] with Motorola not delivering on promise of upgrades for Moto G. I will not buy Motorola Android phone again.

What options do I have with the switch?

I could replace the switch with something modern, but it's just spending money and generating electro-waste.

I could get a little VM with obsolete operating system and an old browser just to manage this switch. This is unsafe, makes me shudder and is too cumbersome to even consider.

Finally, I can manage the device using plain, unencrypted HTTP. Given it's accessible in my LAN only, this is the way to go. I will be sad inside, but that's the only loss.

sslscan output below shows the sad state of TP-SG2216 web management:

Testing SSL server distrans.pipebreaker.pl on port 443 using SNI name distrans.pipebreaker.pl

SSL/TLS Protocols:
SSLv2     disabled
SSLv3     disabled
TLSv1.0   enabled
TLSv1.1   disabled
TLSv1.2   disabled
TLSv1.3   disabled

Supported Server Cipher(s):
Preferred TLSv1.0  128 bits  RC4-SHA
Accepted  TLSv1.0  128 bits  RC4-MD5
Accepted  TLSv1.0  112 bits  DES-CBC3-SHA
Accepted  TLSv1.0  56 bits   TLS_RSA_WITH_DES_CBC_SHA

Smart-zegarek do łazienki


Najlepszą motywację do skończenia projektu jest publiczne przyznanie, że się coś robi. Wtedy pojawia się presja…

W tajemnicy przed Żoną przygotowuje mały wyświetlacz prezentujący najważniejsze o poranku informacje. W weekend popisałem kilka odwołań do różnych API i na tę chwilę mam zebrane dane do wyświetlania:

$ ./epaper.py
Czas: 6:56
---
Thunderstorm (burze z piorunami)
Wiatr 63 km/h
2°C, odczuwalna -5°C
---
Do Pruszcza
 * obwodnicą 26 min
   miastem   28 min
---
[++                ] PM2,5: 4.52% ; [++                ] PM10: 2.94%
Wspaniałe powietrze! / Korzystaj z życia!

Rano prezentowane informacje są nieco inne, niż w trakcie dnia:

  • aktualny czas; rano dokładny, później z dokładnościa do kwadransa

  • pogoda – bieżąca, wieczorem: prognoza na dzień następny; dane biorę z OpenWeatherMap

  • czas dojazdu do pracy, dwiema alternatywnymi drogami. Googlowy Directions API bierze pod uwagę aktualne natężenie ruchu. I podobno pierwsze $200 każdego miesiąca jest darmowe. Po południu ta informacja nie jest potrzebna – może zamiast tego pokazywać czas dojazdu do najbliższego wydarzenia z kalendarza, z wpisaną lokalizacją?

  • jakość powietrza informacyjnie, akurat mieszkam niedaleko kilku czujników Airly

Kwestia prezentacji zajęła mi więcej badań, bo chciałbym utrzymać wszystko w Pythonie. Spodobał mi się pewien wyświetlacz, ale informacje w necie nie były spójne. Za to idealnym wyczuciem wykazał się producent wyświetlacza. W weekend pokazali, że działa z MicroPython:

Więc zakupiłem. Zanim dojdzie z Chin, wsparcie dla MicroPythona będzie już gotowe.

I am sorry if you read this at “We Make Fedora” :(


Chances are you are reading this post on a blog aggregator (“planet”) named We Make Fedora (lack of link deliberate). We Make Fedora was apparently organised by Daniel Pocock. He copied all the blog sources from Planet Fedora, but mixed-in some shady, anonymous sources. This way, “conspiracy theory”-like nameless posts build on credibility of real Fedora developer's blogs.

I do not want neither my name nor mine posts to appear alongside such content. Examples of recent posts:

  • borderline slanderous posts about Chris Lamb, former Debian leadership (on allegely Fedora-related site!) personal matters

  • insinuations about trafficking of underage girls by open source communities, on one occasion implicating Justin W. Flory from Fedora

  • comparison between Adolf Hitler's activities (!!!) and German Free Software Foundation of Europe

  • equaling Google's Youth Hacking 4 Freedom with nazi Concentration Camps

Holocaust is a very painful memory for European society. It should never be forgotten, the memory should be treated with seriousness in places like Yad Vashem Institue. It should never be used in an anonymous slanderous content.

Again, I do not want my name used to legitimise above content. I've asked Daniel to remove my blog from his aggregator three times:

  • on Tue, 24 Aug 2021 12:00:33 +0200, in a direct email

  • on Mon, 6 Sep 2021 09:17:35 +0200, in an email to Daniel and fedora-devel (apparently still in moderation queue)

  • on Mon, 6 Sep 2021 17:08:42 +0200, in a reply to Daniel

Despite above efforts, my posts still appear on We Make Fedora. I don't want to see my name on a site with such dubious content. I going to block access to my RSS/ATOM feeds for the aggregator. Unfortunately anyone can utilize public feeds to create any site he wants.

ACME & FreeIPA – super easy


This post will be short. Recent FreeIPA versions contain ACME server implementation, which makes TLS certificate issuance a breeze.

FreeIPA

FreeIPA is a solution giving you LDAP for user accounts, CA for issuing certificates and Kerberos for SSO, delivered with nice WebUI in an integrated package.

ACME

Automated Certificate Management Environment is a protocol designed to automate process of getting a TLS certificate. It was popularised by Let's Encrypt, BuyPass, Venafi and others.

When you have FreeIPA, you have your own Certificate Authority. It is most sensible to use it for securing your internal endpoints. Your clients should already trust this CA. Your internal network may not be reachable by external ACME providers. And you may want to hide your internal hostnames from appearing in global Certificate Transparency Databases.

Ready to start? Make sure package pki-acme is installed on you FreeIPA server. Next, enable ACME functionality:

$ ipa-acme-manage enable

The ipa-acme-manage command was successful

Done! Now configure the client – for my k8s I'm using awesome cert-manager. Start with definition of a ClusterIssuer with your FreeIPA URL (put you own email and server address, of course):

---
kind: ClusterIssuer
apiVersion: cert-manager.io/v1
metadata:
  name: pipebreaker-freeipa
  spec:
    acme:
      email: tomek@pipebreaker.pl
      server: https://ipa-ca.pipebreaker.pl/acme/directory
      privateKeySecretRef:
        # Secret resource that will be used to store the account's private key.
        name: issuer-pbrk-account-key
      solvers:
        - http01:
            ingress: {}

Second (and last) step is to annotate each ingress which should get a TLS certificate automatically provided:

---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  annotations:
    cert-manager.io/cluster-issuer: pipebreaker-freeipa
[]

And that's basically it. After few moments certificate should be issued:

/dżogstaff/2021.11.25-freeipa-issued-certificate.png

When using cert-manager, make sure it's version 1.6.0 or later. There was a fix for ambiguity in spec which solved some interoperability problems with FreeIPA implementation. The fix may be backported for older cert-manager releases.