<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Maciej[cc]</title><atom:link href="https://nabozny.io/index.xml" rel="self" type="application/rss+xml"/><link>https://nabozny.io/</link><description>Blog o programowaniu i nie tylko</description><lastBuildDate>Tue, 22 Jul 2025 19:19:00 +0000</lastBuildDate><language>pl-PL</language><generator>Hugo 0.167.0</generator><item><title>Pastéis de nata</title><link>https://nabozny.io/pasteis-de-nata/</link><dc:creator>maciej</dc:creator><pubDate>Tue, 22 Jul 2025 19:19:00 +0000</pubDate><category>Inne</category><guid isPermaLink="true">https://nabozny.io/pasteis-de-nata/</guid><description>Przepis na pyszne babeczki z budyniowym nadzieniem</description><content:encoded>&lt;p&gt;Przepis na pyszne babeczki z budyniowym nadzieniem&lt;/p&gt;&#10;&lt;h3 id="składniki"&gt;Składniki&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;6 żółtek jaj&lt;/li&gt;&#10;&lt;li&gt;3 łyżki mąki przennej&lt;/li&gt;&#10;&lt;li&gt;1 i 1/4 szklanki mleka (osobno użyjemy 1 a osobno 1/4)&lt;/li&gt;&#10;&lt;li&gt;Niecała szklanka cukru&lt;/li&gt;&#10;&lt;li&gt;2/3 szklanki wody&lt;/li&gt;&#10;&lt;li&gt;Rolka ciasta francuskiego lub filo (z filo wychodzi trochę inny smak)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Potrzebna będzie też brytfanka do babeczek, 2 garnki i sitko.&lt;/p&gt;&#10;&lt;h3 id="przygotowanie"&gt;Przygotowanie&lt;/h3&gt;&#10;&lt;p&gt;Do 1/4 szklanki mleka wsyp 3 łyżki mąki i rozmieszaj dokładnie, np. ubijaczką do piany, tak aby nie było grudek. Pozostawiamy na później. Do garnka wlewamy wodę z cukrem i gotujemy. Po zagotowaniu należy dodać mleko i zagotować. Po zagotowaniu wyłączamy palnik i dodajemy po kolei mąkę zmieszaną z mlekiem oraz żółtka jajek. Cały czas należy mieszać, aby nie zrobiły się grudki. Jeśli jeszcze nie wyłączyłeś gazu zrób to teraz, nadzienie szybko się przypala. Po dokładnym rozmieszaniu całość należy przelać przez sitko do drugiego garnka aby pozbyć się grudek.&lt;/p&gt;&#10;&lt;p&gt;Następnie wykładamy kubeczki w brytfance kawałkami ciasta francuskiego lub filo tak, aby były dokładnie wyłożone aż do brzegów. W powstałe miejsca wlewamy przygotowany budyń. Całość należy dać do piekarnika na ok. 250-270*C, na 8-10 minut. Budyń powinien się lekko zarumienić podczas pieczenia. Jeśli robisz z ciasta filo, to wystające ponad budyń brzegi spalą się. Należy je później odkroić.&lt;/p&gt;&#10;&lt;p&gt;Po wystygnięciu babeczki są gotowe do jedzenia&lt;/p&gt;</content:encoded></item><item><title>Debugowanie kontenerów w kubernetesie – część 2</title><link>https://nabozny.io/debugowanie-kontenerow-w-kubernetesie-czesc-2/</link><dc:creator>maciej</dc:creator><pubDate>Tue, 12 Mar 2024 10:02:11 +0000</pubDate><category>Cloud</category><category>Linux</category><category>docker</category><category>linux</category><category>k8s</category><category>kubernetes</category><category>sieci</category><guid isPermaLink="true">https://nabozny.io/debugowanie-kontenerow-w-kubernetesie-czesc-2/</guid><description>Po poprzedniej części zapraszam na kolejną, pokazującą jak poradzić sobie z ograniczeniami które wprowadza Kubernetes podczas debugowania aplikacji sieciowych.
Wykonanie pojedynczego polecenia/shelll kubectl -n my_namespace exec -it pod -- /bin/some_command Gdzie zwykle /bin/some_command można …</description><content:encoded>&lt;p&gt;Po poprzedniej &lt;a href="https://nabozny.io/debugowanie-kontenerow-w-chmurze/"&gt;części&lt;/a&gt; zapraszam na kolejną, pokazującą jak poradzić sobie z ograniczeniami które wprowadza Kubernetes podczas debugowania aplikacji sieciowych.&lt;/p&gt;&#10;&lt;h3 id="wykonanie-pojedynczego-poleceniashelll"&gt;Wykonanie pojedynczego polecenia/shelll&lt;/h3&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl -n my_namespace exec -it pod -- /bin/some_command&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Gdzie zwykle &lt;em&gt;/bin/some_command&lt;/em&gt; można zastąpić &lt;em&gt;/bin/bash&lt;/em&gt;&lt;/p&gt;&#10;&lt;h3 id="kontener-do-debugowania"&gt;Kontener do debugowania&lt;/h3&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl debug my_pod_name -n my_namespace -it --image=ubuntu:latest /bin/bash&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Powyższe spowoduje uruchomienie nowego kontenera w tym samym podzie. Dzięki temu możemy połączyć się do localhost (127.0.0.1) i sprawdzić jak działają nasze serwisy za pomocą curl/wget. W trybie debug mamy też dostęp do roota, dzięki czemu hardening właściwej aplikacji nie jest aż tak straszny i nie ogranicza nas, np. w zainstalowaniu nowych paczek. Taki kontener nie współdzieli też systemu plików z oryginalnymi kontenerami z poda, dzięki temu nie namieszamy zbyt dużo.&lt;/p&gt;&#10;&lt;h3 id="lepszy-kontener-do-debugowania"&gt;Lepszy kontener do debugowania&lt;/h3&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl debug my_pod_name -n my_namespace -it --image=ubuntu:latest --share-processes -c container_name --copy-to=mg-debug&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Jest to trochę bardziej rozbudowana wersja poprzedniego polecenia. Odpalając taki kontener do debugowania możemy wybrać jeden z istniejących kontenerów i kubectl skopiuje jego konfiguracje (zamontowane &lt;em&gt;volumes&lt;/em&gt;, sieć i przestrzeń procesów). Zabawa w takim środowisku daje już dość duże możliwości interakcji z innymi kontenerami. Można wysłać przyjacieski sygnał -KILL do procesów, pogrzebać w podmontowanych wolumenach lub sprawdzić sieć, również bez ograniczeń hardeningu.&lt;/p&gt;&#10;&lt;h3 id="shell-noda"&gt;Shell noda&lt;/h3&gt;&#10;&lt;p&gt;Link dla zdesperowanych: &lt;a href="https://github.com/kvaps/kubectl-node-shell"&gt;https://github.com/kvaps/kubectl-node-shell&lt;/a&gt;. Skrypt potrafi uruchomić shell na nodzie kubernetesa. Dzięki niemu możemy dostać się jako root na dowolnego noda z klastra jako root i wprost pogrzebać w systemie. Chyba najbardziej &amp;ldquo;wszechmocna&amp;rdquo; opcja do zabawy w szukanie dziury w całym.&lt;/p&gt;&#10;&lt;p&gt;Miłego debugowania!&lt;/p&gt;&#10;</content:encoded></item><item><title>Co zrobić gdy nie mamy w kontenerze roota i trzeba debugować sieć</title><link>https://nabozny.io/co-zrobic-gdy-nie-ma-dostepu-netstat-ani-root/</link><dc:creator>maciej</dc:creator><pubDate>Wed, 27 Dec 2023 08:24:13 +0000</pubDate><category>Linux</category><guid isPermaLink="true">https://nabozny.io/co-zrobic-gdy-nie-ma-dostepu-netstat-ani-root/</guid><description>Często debugowanie kontenerów w kubernetesie wymaga przeanalizowania ruchu, jaki wchodzi lub wychodzi do systemu. Nie ma z tym problemu jeśli mamy dostęp do konta administratora u możemy uruchomić netstat lub tcpdump aby popatrzeć w pakiety. Co jeśli nie ma do tego dostępu?</description><content:encoded>&lt;p&gt;Często debugowanie kontenerów w kubernetesie wymaga przeanalizowania ruchu, jaki wchodzi lub wychodzi do systemu. Nie ma z tym problemu jeśli mamy dostęp do konta administratora u możemy uruchomić netstat lub tcpdump aby popatrzeć w pakiety. Co jeśli nie ma do tego dostępu?&lt;/p&gt;&#10;&lt;h3 id="znajdź-proces"&gt;Znajdź proces&lt;/h3&gt;&#10;&lt;p&gt;Na początek zacznijmy od znalezienia procesu, który obsługuje ruch na porcie 80:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ps&#10;bash: ps: command not found&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Będzie trudniej&amp;hellip; przejdźmy to katalogu &lt;em&gt;/proc&lt;/em&gt;. Część z podkatalogów odpowiada procesom. Zwykle w kontenerach oraz w Linuksie proces z PID o numerze 1 odpowiada pierwszemu procesowi w systemie/kontenerze (np. &lt;em&gt;/bin/init&lt;/em&gt;). Mamy zatem sporo różnych wpisów w proc:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ls -l /proc&#10;total 0&#10;dr-xr-xr-x 9 root root 0 Dec 19 11:59 1&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 29&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 30&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 31&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 32&#10;dr-xr-xr-x 9 root root 0 Dec 27 08:05 33&#10;dr-xr-xr-x 9 root root 0 Dec 27 08:06 55&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 56&#10;dr-xr-xr-x 9 nginx nginx 0 Dec 27 08:09 63&#10;drwxrwxrwt 2 root root 40 Dec 19 11:59 acpi&#10;dr-xr-xr-x 13 root root 0 Dec 19 11:59 asound&#10;...&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Każdy z nich odpowiada osobnemu procesowi. Po nazwie właściciela można stwierdzić co to za proces, ale aby upewnić się, sprawdźmy wpis &lt;em&gt;exe&lt;/em&gt; w takim katalogu:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ls -lh /proc/29/exe&#10;lrwxrwxrwx 1 nginx nginx 0 Dec 27 08:10 /proc/29/exe -&amp;gt; /usr/sbin/nginx&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;exe&lt;/em&gt; to link symboliczny do pliku wykonywalnego w systemie plików. Mamy zatem ustalonego podejrzanego oraz jego proces.&lt;/p&gt;&#10;&lt;h3 id="jakie-porty-są-otwarte-przez-proces"&gt;Jakie porty są otwarte przez proces&lt;/h3&gt;&#10;&lt;p&gt;Aby sprawdzić z czego korzysta dany proces zwykle można urzyć &lt;em&gt;lsof&lt;/em&gt; lub &lt;em&gt;netstat&lt;/em&gt;. W dobrze zabezpieczonych systemach nie mamy takiej możliwości. Zamiast tego możemy podglądnąć listę otwartych prze nginx plików:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ ls -lh /proc/29/fd/&#10;total 0&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 0 -&amp;gt; /dev/null&#10;l-wx------ 1 nginx nginx 64 Dec 27 08:13 1 -&amp;gt; &amp;#39;pipe:[37844]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 10 -&amp;gt; &amp;#39;anon_inode:[eventfd]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 11 -&amp;gt; &amp;#39;anon_inode:[eventfd]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 12 -&amp;gt; &amp;#39;socket:[40105]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 13 -&amp;gt; &amp;#39;socket:[40107]&amp;#39;&#10;l-wx------ 1 nginx nginx 64 Dec 27 08:13 2 -&amp;gt; &amp;#39;pipe:[37845]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 3 -&amp;gt; &amp;#39;socket:[40103]&amp;#39;&#10;l-wx------ 1 nginx nginx 64 Dec 27 08:13 4 -&amp;gt; &amp;#39;pipe:[37845]&amp;#39;&#10;l-wx------ 1 nginx nginx 64 Dec 27 08:13 5 -&amp;gt; &amp;#39;pipe:[37844]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 6 -&amp;gt; &amp;#39;socket:[40099]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 7 -&amp;gt; &amp;#39;socket:[40100]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 8 -&amp;gt; &amp;#39;socket:[40102]&amp;#39;&#10;lrwx------ 1 nginx nginx 64 Dec 27 08:13 9 -&amp;gt; &amp;#39;anon_inode:[eventpoll]&amp;#39;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pliki z numerami (dokładniej deskryptorami, możliwe, że kojarzysz to z funkcji &lt;em&gt;open&lt;/em&gt; w C) 0 i 1 to standardowe wejście i wyjście. Za ich pomocą program komunikuje się z użytkownikiem w konsoli. Tutaj jest wejście jest ustawione na &lt;em&gt;/dev/null&lt;/em&gt; a wyjście przekierowane do pipe. To, co nas interesuje, to pliki opisane jako &lt;em&gt;socket:[numer]&lt;/em&gt;. Są to połączenia sieciowe. Nazwa symlinka to deskryptor pliku/socketu widziany po stronie aplikacji. Numer widoczny po &lt;em&gt;socket:&amp;hellip;&lt;/em&gt; to identyfikator obiektu po stronie jądra systemu, tzw. inode.&lt;/p&gt;&#10;&lt;p&gt;Jak sprawdzić który inode odpowiada socketowi, nasłuchującemu na porcie 80? Popatrzmy w plik &lt;em&gt;/proc/net/tcp&lt;/em&gt;:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;$ cat /proc/net/tcp&#10; sl local_address rem_address st tx_queue rx_queue tr tm-&amp;gt;when retrnsmt uid timeout inode &#10; 0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 40099 1 0000000000000000 100 0 0 10 0&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pokazuje on otwarte połączenia sieciowe. Ostatnia kolumna to inode połączenia (socketu). Jeśli poszukasz jej w &lt;em&gt;/proc/29/fd&lt;/em&gt;, to znajdziesz podobny wpis, dla deskryptora pliku nr &lt;em&gt;6&lt;/em&gt;. Teraz wystarczy popatrzeć na &lt;em&gt;local_address&lt;/em&gt; i zamienić numer portu &lt;em&gt;0050&lt;/em&gt; na wartość dziesiętną i wyjdzie port &lt;em&gt;80&lt;/em&gt;, na którym słucha nasza aplikacja.&lt;/p&gt;&#10;&lt;p&gt;Wszystko to używając jedynie &lt;em&gt;ls&lt;/em&gt; oraz &lt;em&gt;cat&lt;/em&gt; z konta zwykłego użytkownika, które zwykle nie są usuwane podczas zabezpieczania kontenerów&lt;/p&gt;</content:encoded></item><item><title>Debugowanie kontenerów w chmurze</title><link>https://nabozny.io/debugowanie-kontenerow-w-chmurze/</link><dc:creator>maciej</dc:creator><pubDate>Fri, 24 Sep 2021 08:29:21 +0000</pubDate><category>Cloud</category><category>Debugowanie</category><category>Linux</category><guid isPermaLink="true">https://nabozny.io/debugowanie-kontenerow-w-chmurze/</guid><description>Czasami coś nie działa i przyczyna tego za diabła nie chce dać się znaleźć. Poniżej kilka pomocnych rad w debugowaniu w środowisku chmury i kontenerów, czyli “u mnie działa, a na cudzym komputerze nie”</description><content:encoded>&lt;p&gt;Czasami coś nie działa i przyczyna tego za diabła nie chce dać się znaleźć. Poniżej kilka pomocnych rad w debugowaniu w środowisku chmury i kontenerów, czyli &amp;ldquo;u mnie działa, a na cudzym komputerze nie&amp;rdquo;&lt;/p&gt;&#10;&lt;h3 id="problem"&gt;Problem&lt;/h3&gt;&#10;&lt;p&gt;Moja strona nie działa, a devops skomplikował sprawę. Na wejściu do naszego serwisu stoi ELB, ALB lub inny load balancer, który przekierowuje ruch do kontenera zarządzanego przez ECS lub kubernetes. Żeby było trudniej, nie mamy dostępu do czeluści load balancera i wejście na noda klastra też jest ograniczone. Możemy jedynie dostać się do kontenera.&lt;/p&gt;&#10;&lt;p&gt;Porblem pojawia się gdy frontend (UI) wysyła żądanie do backendu. Nie dostajemy poprawnej odpowiedzi, a jedynie błąd 503 Service Unavailable.&lt;/p&gt;&#10;&lt;h3 id="rozwiązanie"&gt;Rozwiązanie&lt;/h3&gt;&#10;&lt;p&gt;Znajdź problem i napraw :)&lt;/p&gt;&#10;&lt;h3 id="rozwiązanie-2"&gt;Rozwiązanie 2&lt;/h3&gt;&#10;&lt;p&gt;Zanim zaczniesz grzebać, upewnij się, że zepsucie danego kontenera nie pociągnie za sobą negatywnych konsekwencji. W przypadku Kubernetesa, ECS lub innych orchestratorów (jakkolwiek to się tłumaczy) usunięcie zepsutego kontenera powinno spowodować automatyczne utworzenie nowego, takiego samego. Oprócz tego dobrą rzeczą będzie kawałek papieru lub gedit do notowania co robimy, aby łatwo dało się zrobić rollback zmian, które są trwałe lub odtworzyć całą ścieżkę.&lt;/p&gt;&#10;&lt;p&gt;Ponadto pomyśl czy żądanie/request, które będziemy naprawiać nie niszczy czegoś po stronie backendu. Jeśli problem sprawia guzik &amp;ldquo;skasuj konto&amp;rdquo; to dwukrotne debugowanie tego samego requestu będzie problematyczne&amp;hellip;&lt;/p&gt;&#10;&lt;h5 id="sprawdź-co-nie-bangla"&gt;Sprawdź co nie bangla&lt;/h5&gt;&#10;&lt;p&gt;Na początek znajdź z użyciem developer tools jakie żądanie sprawia problem. Otwórz &lt;em&gt;developer tools&lt;/em&gt; w przeglądarce i popatrz co się dzieje gdy strona wysyła do backendu request. W dalszej części bardzo pomocne będzie skopiowanie polecenia cURL z dokładnymi parametrami żądania, które wysyła przeglądarka. W zakładce z listą połączeń sieciowych z &lt;em&gt;developer tools&lt;/em&gt; możesz wybrać skopiowanie requestu m.in. jako polecenie programu cURL.&lt;/p&gt;&#10;&lt;p&gt;Ponadto, w ulubionym edytorze tekstu, jakim jest oczywiście &lt;em&gt;pico&lt;/em&gt; albo &lt;em&gt;gedit&lt;/em&gt;, zapisz powyższe polecenie. Często bedzie ono zawierało całą masę nagłówków, id sesji, ciasteczek i innych rzeczy, które weryfikuje backend w celu uwierzytelnienia człowieka. Jako użyteczny dodatek możesz zamienić w takim poleceniu nagłówek &lt;em&gt;User Agent&lt;/em&gt; na własny string. W większości logów user agent pojawia się w każdej linijce logowanego requestu i dzięki temu będzie nam łatwiej przeszukać logi tylko z naszego curla.&lt;/p&gt;&#10;&lt;p&gt;Mając powyższe sprawdź czy curl dostaje tak samo niepoprawną odpowiedź od serwera. Możliwe że już na tym etapie otrzymasz komunikat z błędem i dalsze debugowanie stanie się zbędne.&lt;/p&gt;&#10;&lt;h5 id="logi"&gt;Logi&lt;/h5&gt;&#10;&lt;p&gt;Chyba podstawowa rzecz, dużo grepa, a jeśli to AWS to dużo scrollowania i szukania w cloudwatch. Jeśli nie ma w logach aplikacji z backendu, to możliwe że jest w logach load balancera. Jeśli nie, to&amp;hellip;&lt;/p&gt;&#10;&lt;h3 id="czas-na-grubszy-kaliber"&gt;Czas na grubszy kaliber&lt;/h3&gt;&#10;&lt;p&gt;Czasami błąd jest tak uciążliwy, że ani w logach ani w odpowiedzi backendu nie da się znaleźć jego przyczyny. Pozostaje więc kilka cięższych dział:&lt;/p&gt;&#10;&lt;h5 id="wewnątrz-kontenera--netstat"&gt;Wewnątrz kontenera – netstat&lt;/h5&gt;&#10;&lt;p&gt;Odpal &lt;em&gt;netstat&lt;/em&gt; z pakietu &lt;em&gt;net-tools&lt;/em&gt; w Ubuntu/Debianie. Polecenie &lt;em&gt;netstat -ntap&lt;/em&gt; powinno wypisać wszystkie nawiązane połączenia i otwarte porty. Sprawdź czy wszystko jest tak jak powinno, tj. czy serwer nasłuchuje na odpowiednim porcie, czy widać połączenie z bazą etc.&lt;/p&gt;&#10;&lt;p&gt;Jeśli wszystko jest ok, to spróbuj wykonać to samo podczas wykonywania żądania przez cURL. Jeśli takie żądanie wykonuje się za szybko i nie nadążasz klikać, to wrzuć gdzieś &lt;em&gt;sleep 10&lt;/em&gt;, tylko nie zapomnij go usunąć :) Ponieważ często po zmodyfikowaniu kodu potrzebny jest restart serwisu, a ubicie głównego procesu spowoduje restart kontenera, spróbuj &lt;em&gt;kill -HUP [proces]&lt;/em&gt;. Dawno dawno temu, gdy komputery obsługiwało się bez myszki (i nie przez touch screen) zdarzało się, że coś zerwało połączenie z terminalem, na którym mieliśmy uruchomiony interaktywny proces. Przez &lt;em&gt;SIGHUP&lt;/em&gt; można było poinformować taką odłączoną aplikacje, że straciliśmy z nią połączenie i chcemy aby się zakończyła. Serwery zwykle nie reagowały na to, jednak przez lata &lt;em&gt;SIGHUP&lt;/em&gt; stał się sygnałem do reloadu konfiguracji i często również skryptów, które są wykonywane przez serwer. Dzięki temu prawdopodobnie nie zrestartujesz kontenera, w którym pracujesz.&lt;/p&gt;&#10;&lt;p&gt;Wracając do tematu – mając już wrzuconego gdzieś &lt;em&gt;sleep 10&lt;/em&gt; spróbuj netstat ponownie i zobacz czy nic nie wygląda podejrzanie&lt;/p&gt;&#10;&lt;h5 id="curl-do-kontenera"&gt;cURL do kontenera&lt;/h5&gt;&#10;&lt;p&gt;Kolejnym punktem do odhaczenia jest wysłanie żądania przez cURL bezpośrenio z kontenera do niego samego. Możemy wykorzystać wcześniejsze polecenie cURL. Możemy też dodać opcje wymuszającą na cURL&amp;rsquo;u wyświetlenie nagłówków. Jeśli się powiedzie, to problem prawdopodobnie pojawia się gdzieś wcześniej, np. między load balancerem a kontenerem. Jeśli masz taką możliwość, wykonaj to samo z load balancera.&lt;/p&gt;&#10;&lt;h5 id="nc-do-innych-usług"&gt;nc do innych usług&lt;/h5&gt;&#10;&lt;p&gt;Jeśli to zadziała, dobrze jest sprawdzić połączenie z bazą lub innymi wymaganymi serwisami bezpośrednio z kontenera: &lt;em&gt;nc nazwa_hosta port&lt;/em&gt; ( &lt;em&gt;apt install netcat&lt;/em&gt;). W przypadku bazy można doinstalować jej klienta i spróbować się połączyć, przy okazji wykonując jakiś prosty select na tabelach, do których aplikacja ma mieć dostęp.&lt;/p&gt;&#10;&lt;h5 id="udawanie-innych-serwisów"&gt;Udawanie innych serwisów&lt;/h5&gt;&#10;&lt;p&gt;Kolejnym trikiem, który może się przydać jest odpalenie czegoś, co udaje bazę lub inny serwis. Pozwoli to poznać nam jakie żądania są wysyłane do sąsiednich usług. Może to być przydatne gdy nie mamy możliwości zainstalowania &lt;em&gt;tcpdump&lt;/em&gt; lub jest to zabronione.&lt;/p&gt;&#10;&lt;p&gt;Jak to zrobić aby stało się to tylko lokalnie, bez psucia całej infrastruktury? Sprawdź jaki host jest ustawiony jako np. mikroserwis, który chcesz podsłuchać (jeśli używasz po IP, to sorry&amp;hellip;). Następnie wpisz w &lt;em&gt;/etc/hosts&lt;/em&gt; nowy wpis: &lt;em&gt;127.0.0.1 [nazwa hosta]&lt;/em&gt; i odpal w kontenerze &lt;em&gt;nc -l [port usługi]&lt;/em&gt;. W Linuksie pierwszeństwo w ustalaniu adresów przypisanych do hostów ma plik /etc/hosts, dzięki czemu dodając do niego nowy wpis wymusimy aby nasz kontener połączył się z localhost zamiast właściwego hosta. Uruchomiony program &lt;em&gt;nc&lt;/em&gt; pozwoli wypisać to, co miało zostać wysłane przez aplikację z naszego kontenera do serwisu. Pamiętaj, aby usunąć później wpis z &lt;em&gt;/etc/hosts&lt;/em&gt; :)&lt;/p&gt;&#10;&lt;h5 id="podglądnięcie-zmiennych-środowiskowych"&gt;Podglądnięcie zmiennych środowiskowych&lt;/h5&gt;&#10;&lt;p&gt;Często zanim połączymy się z bazą lub podglądniemy ruch sieciowy do danego hosta warto sprawdzić jakie zmienne znają aplikacje, które są już uruchomione w kontenerze. Czasami przez błąd w konfiguracji aplikacja może nie mieć możliwości uzyskania tych zmiennych, bo np. zabrakło uprawnienia IAM do odpytania Secret Parameter Store. Może też to wynikać ze zmienionego API lub biblioteki – zamiast jednego requestu o listę wszystkich parametrów odpytuje o każdy z osobna, do czego IAM już nie uprawnia.&lt;/p&gt;&#10;&lt;p&gt;Wykonaj &lt;em&gt;ps aux&lt;/em&gt;. Zwykle pierwszy proces będzie znał tylko te parametry, które są przekazywane bezpośrednio przez dockera. Wszelkie inne, uzyskiwane z chmury są znane późniejszym procesom, po pełnej inicjalizacji środowiska. Możesz podglądnąć jeden z wyższych PID&amp;rsquo;ów (ale nie z naszej sesji!) przez wpis w &lt;em&gt;/proc/[pid]/environ&lt;/em&gt;:&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;sudo cat /proc/123/environ | tr &amp;lsquo;\0&amp;rsquo; &amp;lsquo;\n&amp;rsquo;&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;Poszczególne zmienne są rozdzielone zerami (znakami o kodzie zero), stąd &lt;em&gt;tr&lt;/em&gt;, który zmieni zera na nowe linie. Jeśli wygląda ok, to pijemy kolejną kawę i szukamy dalej&lt;/p&gt;&#10;&lt;h5 id="ponownie-netstat-lsof"&gt;Ponownie netstat, lsof&lt;/h5&gt;&#10;&lt;p&gt;Sprawdź ulimit i porównaj z ilością połączeń i otwartych plików w kontenerze. W zależności od konfiguracji ten parametr przy dużej ilości połączeń może stwarzać problemy&lt;/p&gt;&#10;&lt;h5 id="podglądanie-z-czym-się-łączy-aplikacja"&gt;Podglądanie z czym się łączy aplikacja&lt;/h5&gt;&#10;&lt;p&gt;Sprawdzisz to przez &lt;em&gt;tcpdump udp port 53&lt;/em&gt;. W trakcie działania sniffera możesz wykonać żądanie przez cURL i sprawdzić co się dzieje i z czym się łączy aplikacja. Jeśli używasz IP, to zapytanie tcpdump będzie trochę inne.&lt;/p&gt;&#10;&lt;h5 id="strace-do-czytania-logów"&gt;strace do czytania logów&lt;/h5&gt;&#10;&lt;p&gt;Jeśli cloudwatch szczególnie uwiera tu i ówdzie, przez co nie możesz znaleźć logów, warto sprawdzić co aplikacja wypisuje na standardowe wyjście. Nightmare w kontenerze? Nie :) Spróbuj:&lt;br&gt;&#10;&lt;em&gt;strace --attach=[pid serwera] -e write=1,2&lt;/em&gt;&lt;br&gt;&#10;Powyższe podłączy &amp;ldquo;debuger&amp;rdquo; strace do procesu i będzie wyłapywało jedynie wywołania systemowe funkcji write do plików o fd=1 i 2. Oznaczają one odpowiednio &lt;em&gt;stdout&lt;/em&gt; i &lt;em&gt;stderr&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p&gt;Nie jest to najwygodniejsza metoda oglądania logów, ale pozwala użyć ukochanego grepa i awk&amp;rsquo;a, co w przypadku cloudwatch nie zawsze jest najwygodniejsze i najszybsze.&lt;/p&gt;&#10;&lt;p&gt;Dla przykładowego &lt;em&gt;ls&lt;/em&gt; wykonanego przez ssh:&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://nabozny.io/uploads/2021/09/strace-ssh.png" alt="" width="635" height="61" class="alignnone size-full" loading="lazy" decoding="async"&gt;&lt;/p&gt;&#10;&lt;p&gt;otrzymamy wynik ze strace:&lt;br&gt;&#10;&lt;img src="https://nabozny.io/uploads/2021/09/strace-out.png" srcset="https://nabozny.io/uploads/2021/09/strace-out_hu_ff789cf743115bfc.png 600w, https://nabozny.io/uploads/2021/09/strace-out.png 1004w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" alt="" width="1004" height="690" class="alignnone size-full" loading="lazy" decoding="async"&gt;&lt;br&gt;&#10;Nie jest to najczytelniejsze, ale odpowiednio okraszając to grep&amp;rsquo;em i wycinając wszystkie znaki sterowania terminalem (kolory, znaki specjalne etc.) możemy uzyskać dość czytelny wgląd w to, co się dzieje. Powyższa metoda zadziała też na połączeniach sieciowych, w tym na tych, któ©e są już odszyfrowane i idą np. do fcgi po systemowym sockecie.&lt;/p&gt;&#10;&lt;h3 id="na-koniec"&gt;Na koniec&lt;/h3&gt;&#10;&lt;p&gt;Jeśli nie udało się nic znaleźć, a aplikacja dalej się sypie, to pozostaje stara dobra metoda&amp;hellip; wyłącz i włącz kontener, później instancje, a na koniec pogadaj z frontendowcami i backendowcami którzy muszą wysyłać to problematyczne żądanie. Chociaż pogadać i zrozumieć jest dobrze przed całym powyższym szukaniem dziury w całym ;)&lt;/p&gt;</content:encoded></item><item><title>Nowy adres</title><link>https://nabozny.io/nowy-adres/</link><dc:creator>maciej</dc:creator><pubDate>Tue, 31 Aug 2021 09:55:17 +0000</pubDate><category>Uncategorized</category><guid isPermaLink="true">https://nabozny.io/nowy-adres/</guid><description>Od dzisiaj można przeglądać bloga pod adresem nabozny.io. Stara domena (jak również maile, jeśli ktoś do mnie pisał na nią :) ) przestanie być aktywna z końcem listopada.</description><content:encoded>&lt;p&gt;Od dzisiaj można przeglądać bloga pod adresem nabozny.io. Stara domena (jak również maile, jeśli ktoś do mnie pisał na nią :) ) przestanie być aktywna z końcem listopada.&lt;/p&gt;&#10;</content:encoded></item><item><title>Przepis na makowiec</title><link>https://nabozny.io/przepis-na-makowiec/</link><dc:creator>maciej</dc:creator><pubDate>Mon, 02 Nov 2020 12:08:29 +0000</pubDate><category>Inne</category><category>przepisy</category><guid isPermaLink="true">https://nabozny.io/przepis-na-makowiec/</guid><description>Do zrobienia będą potrzebne:
Puszka maku Około 500-600g mąki tortowej 150g stopionego masła 180ml mleka (+/- szklanka) 6 żółtek Saszetka suchych drożdży lub pół kostki świeżych (chyba 50g) 6 łyżek cukru Pół łyżeczki soli Papier do pieczenia jeśli chcemy zawinąć Mieszamy po kolei: żółtka, cukier (na …</description><content:encoded>&lt;p&gt;Do zrobienia będą potrzebne:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Puszka maku&lt;/li&gt;&#10;&lt;li&gt;Około 500-600g mąki tortowej&lt;/li&gt;&#10;&lt;li&gt;150g stopionego masła&lt;/li&gt;&#10;&lt;li&gt;180ml mleka (+/- szklanka)&lt;/li&gt;&#10;&lt;li&gt;6 żółtek&lt;/li&gt;&#10;&lt;li&gt;Saszetka suchych drożdży lub pół kostki świeżych (chyba 50g)&lt;/li&gt;&#10;&lt;li&gt;6 łyżek cukru&lt;/li&gt;&#10;&lt;li&gt;Pół łyżeczki soli&lt;/li&gt;&#10;&lt;li&gt;Papier do pieczenia jeśli chcemy zawinąć&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Mieszamy po kolei: żółtka, cukier (na tym etapie można zrobić kogel mogel :), masło (jeszcze lepszy kogel mogel), drożdże, sól i letnie/lekko ciepłe mleko. Następnie dosypujemy mąkę tak, żeby ciasto przestało się lepić i dało się je jako tako rozłożyć na papierze. Jeśli potrzeba, mąki można dosypać nawet więcej niż 500-600g, byle tylko dało się to rozwałkować.&lt;/p&gt;&#10;&lt;p&gt;Można (ale nie trzeba) całość ostudzić w lodówce przez ok. pół godziny, aby było łatwiej rozwałkować. Następnie bierzemy kawałęk, ok 70cm papieru do pieczenia i rozwałkowujemy na nim ciasto w podłużny placek. Na taki placek wykładamy mak z puszki (połowę lub 1/3, w zależności na ile kawałków podzieliliśmy ciasto) i delikatnie, równomiernie rozsmarowywujemy. na koniec z pomocą drugiej osoby zwijamy: jedna osoba unosi jeden koniec papieru do pieczenia, a druga zaczyna zrolowywać ciasto z makiem. W ten sposób powstaje zawijane ciasto o przekroju: (@). Taką roladę należy luźno zawinąć w papier do pieczenia, aby się nie rozerwała podczas pieczenia – wystarczy zostawić luz na około dwa palce. W ten sposób z powyższego przepisu da się zrobić 2-3 rolady makowe. Na koniec zabezpieczamy papier, np. zszywkami i wkładamy na pół godziny do piekarnika na 180*C.&lt;/p&gt;&#10;&lt;p&gt;Druga, prostsza wersja polega na wyłożeniu połowy ciasta do szerokiej brytfanki, nałożeniu na to maku i położeniu drugiej warstwy rozwałkowanego ciasta na wierzch. Jest mniej roboty, ale nie można tym poszpanować przed rodziną. Pieczemy mniej więcej tyle samo.&lt;/p&gt;&#10;</content:encoded></item><item><title>Szyfrowany dysk sieciowy dla potrzeb serwerowych</title><link>https://nabozny.io/szyfrowany-dysk-sieciowy-dla-potrzeb-serwerowych/</link><dc:creator>maciej</dc:creator><pubDate>Mon, 26 Oct 2020 07:05:44 +0000</pubDate><category>Linux</category><category>Kryptografia</category><guid isPermaLink="true">https://nabozny.io/szyfrowany-dysk-sieciowy-dla-potrzeb-serwerowych/</guid><description>Poniżej przedstawiam kilka sposobów na wykorzystanie przestrzeni dyskowej zdalnej maszyny w sposób zabezpieczający w pełni nasze dane. Założenie konfiguracji jest jedno – maszyna udostępniająca swój dysk nie może mieć wglądu w nasze dane, które przechowujemy ani w klucze, którymi dane są szyfrowane. …</description><content:encoded>&lt;p&gt;Poniżej przedstawiam kilka sposobów na wykorzystanie przestrzeni dyskowej zdalnej maszyny w sposób zabezpieczający w pełni nasze dane. Założenie konfiguracji jest jedno – maszyna udostępniająca swój dysk nie może mieć wglądu w nasze dane, które przechowujemy ani w klucze, którymi dane są szyfrowane. Całość komunikacji ma być w pełni bezpieczna, a jedyny dostęp do danych ma być możliwy jedynie po ich odszyfrowaniu w locie, już na komputerze klienta.&lt;/p&gt;&#10;&lt;p&gt;Dzięki temu przejęcie docelowej maszyny nie będzie oznaczało od razu wycieku naszych danych. Ma to być zapewnione począwszy od dostępu do samego jej dysku, aż po grzebanie w RAM&amp;rsquo;ie, gdzie mogą być przechowywane klucze szyfrujące, gdyby szyfrowanie odbywało się po zdalnej stronie. Kolejnym wymogiem jest aby sposób przechowywania danych był możliwy w środowisku serwerowym, gdzie chcemy zautomatyzować cały proces montowania i dostępu do danych, a więc bez żadnych UI oraz webowych interfejsów.&lt;/p&gt;&#10;&lt;h3 id="duplicity"&gt;Duplicity&lt;/h3&gt;&#10;&lt;p&gt;Najprostszym i zarazem najmniej funkcjonalnym na codzień rozwiązaniem jest zaprzęgnięcie narzędzia do backupów &lt;em&gt;duplicity&lt;/em&gt;. Instalujemy go za pomocą:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install duplicity&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;i od razu możemy korzystać. Jest to jeden z wygodniejszych sposobów na tworzenie backupów:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;export PASSPHRASE=&amp;#34;ala ma kota&amp;#34;&#10;duplicity full /home/shrek rsync://shrek@remote-host//backups/shrek&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Plusy:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Wsparcie dla przeróżnych backendów, od ssh, S3 aż po różne egzotyczne chmury&lt;/li&gt;&#10;&lt;li&gt;Pozwala tworzyć pełne kopie jak również przyrostowe, co może ograniczyć ilość używanego miejsca&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Wady:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Działa jedynie jako backup na żądanie, nie da się wykorzystywać do bieżących operacji, tak jak system plików&lt;/li&gt;&#10;&lt;li&gt;Potrafi się wysypać przy dużych ilościach plików&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="ecryptfs-po-nfs"&gt;Ecryptfs po NFS&lt;/h3&gt;&#10;&lt;p&gt;Kolejnym, trochę wygodniejszym do codziennego użytku narzędziem jest połączenie NFS i ecryptfs. Z racji, że jest to połączenie dwóch różnych systemów plików, potrafi sprawiać problemy podczas usypiania komputera lub gdy wystąpią problemy z siecią.&lt;/p&gt;&#10;&lt;p&gt;Instalacja i uruchomienie po stronie klienta (zakładam, że gdzieś stoi serwer NFS):&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install ecryptfs-utils nfs-utils&#10;&#10;mkdir /.backup&#10;mkdir /backup&#10;&#10;sudo mount -t nfs zdalny_host:/zasob_nfs /.backup&#10;sudo mount -t ecryptfs /.backup /backup&#10;# Tutaj ecryptfs poprosi o podanie nowego hasła, metody szyfrowania i kilku innych detali&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Korzystając z takiego połączenia systemów plików nasz lokalny komputer pokaże w katalogu &lt;em&gt;/backup&lt;/em&gt; odszyfrowaną zawartość katalogu &lt;em&gt;/.backup&lt;/em&gt;. Każdy plik lub katalog w &lt;em&gt;/backup&lt;/em&gt; odpowiada w ten sposób zaszyfrowanemu plikowi lub katalogowi w &lt;em&gt;/.backup&lt;/em&gt;. Dzięki zastosowaniu NFS wszelkie dane, które zapisujemy w /backup są w formie zaszyfrowanej przesyłane przez sieć do hosta, który udostępnia swój katalog przez NFS.&lt;/p&gt;&#10;&lt;p&gt;Plusy:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Działa na żywo, jak zwykły system plików&lt;/li&gt;&#10;&lt;li&gt;Szyfrowanie jest wykonywane w całości po stronie klienta&lt;/li&gt;&#10;&lt;li&gt;Nie angażuje sterownika plików, dzięki czemu trudniej o uszkodzenie plików na poziomie systemu plików&lt;/li&gt;&#10;&lt;li&gt;Łatwe wykonywanie bezpiecznego backupu zaszyfrowanych danych – wystarczy rsync&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Wady:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Czasami potrafi mocno zwolnić, zwłaszcza gdy mamy duży ping lub powolne łącze&lt;/li&gt;&#10;&lt;li&gt;Zawieszenie się lub zerwanie połączenia NFS skutecznie blokuje szyfrowany system plików, przez co procesy utykają na dostępie do plików w przypadku problemów sieciowych&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="nbd-i-luks"&gt;NBD i LUKS&lt;/h3&gt;&#10;&lt;p&gt;Ostatnim rozwiązaniem jest wykorzystanie serwera Network Block Device, który udostępni przez sieć całe urządzenie blokowe oraz systemu LUKS, który potrafi szyfrować całe urządzenia blokowe, ponad systemem plików. Dla zestawienia powyższych narzędzi nasz serwer będzie jedynie udostępniać pojedynczą partycję przez NBD, a my jako klient wykorzystamy mapowanie i odszyfrowanie jej przez driver LUKS, a następnie zamontujemy tak odszyfrowane urządzenie jako partycję ext4.&lt;/p&gt;&#10;&lt;p&gt;Instalacja po stronie klienta:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install cryptsetup nbd-client&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Instalacja po stronie serwera:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install nbd-server&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Następnie trzeba dodać plik eksportujący urządzenie (np. partycja /dev/sda4) do pliku /etc/nbd-server/conf.d/backup:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;[backup]&#10; exportname = /dev/sda4&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pierwsze montowanie i formatowanie partycji po stronie klienta:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo nbd-client -N backup 10.11.22.33 /dev/nbd0&#10;&#10;# Sformatowanie dysku do luks i odszyfrowanie go. Po obu poleceniach cryptsetup zapyta o hasło&#10;sudo cryptsetup luksFormat /dev/nbd0&#10;sudo cryptsetup luksOpen /dev/nbd0 backup&#10;&#10;# cryptsetup stworzy plik backup, który reprezentuje odszyfrowane urządzenie /dev/nbd0:&#10;sudo mkfs.ext4 /dev/mapper/backup&#10;&#10;# Na koniec stwórzmy katalog, gdzie będziemy montować naszą partycję&#10;mkdir /backup&#10;&#10;sudo cryptsetup luksClose backup&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Montowanie i odszyfrowanie za każdym kolejnym razem:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;sudo nbd-client -N backup 10.11.22.33 /dev/nbd0&#10;sudo cryptsetup luksOpen /dev/nbd0 backup&#10;sudo mount /dev/mapper/backup /backup&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;i gotowe!&lt;/p&gt;&#10;&lt;p&gt;Zalety:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;W mojej opini najszybsze i najbardziej odporne na problemy sieciowe rozwiązanie&lt;/li&gt;&#10;&lt;li&gt;Pozwala w pełni wykorzystać dowolny system plików&lt;/li&gt;&#10;&lt;li&gt;W razie problemów dane można również odszyfrować na hoście lub dowolnym innym komputerze&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Wady:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Duże ryzyko uszkodzenia systemu plików w razie problemu z siecią&lt;/li&gt;&#10;&lt;li&gt;Utrudniony backup całego dysku&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="podsumowanie"&gt;Podsumowanie&lt;/h3&gt;&#10;&lt;p&gt;Kombinacji i różnych narzędzi umożliwiających podobne zabezpieczenie jest cała masa, zwłaszcza, jeśli nie ograniczymy się do tych typowo konsolowych. Powyższe jednak pozwolą w miarę dobrze zabezpieczyć się na wypadek przejęcia maszyny hostującej nasze dane i to w sposób dość &amp;ldquo;paranoiczny&amp;rdquo;. Zarówno dane jak i klucze deszyfrujące nie są znane po stronie serwera. Może to być zetem sposób na ochronę nawet w najbardziej ekstremalnych przypadkach – zapobiega wyciągnięciu kluczy np. z pamięci wirtualnej maszyny po uśpieniu jej. Natomiast z racji tego, że nasz klient nie posiada samych zaszyfrowanych danych bezpośrednio u siebie, to w przypadku przejęcia fizycznej maszyny, która te dane przetwarza pozostają one dalej bezpieczne, w formie zaszyfrowanej.&lt;/p&gt;&#10;&lt;p&gt;Do przechowywania dużych ilości danych można w tym przypadku wykorzystać na przykład tanie serwery z oferty kimsufi (nie, nie płacą mi za to :), z dyskami do 2TB w parze z raspberry pi hostowanym u siebie pod biurkiem lub wirtualną maszyną w innej chmurze.&lt;/p&gt;</content:encoded></item><item><title>Sejf w sejfie vs. Sejf z kilkoma drzwiczkami – jak kontrolować dostęp za pomocą kryptografii</title><link>https://nabozny.io/jak-kontrolowac-dostep-za-pomoca-kryptografii/</link><dc:creator>maciej</dc:creator><pubDate>Wed, 14 Oct 2020 15:06:24 +0000</pubDate><category>Kryptografia</category><guid isPermaLink="true">https://nabozny.io/jak-kontrolowac-dostep-za-pomoca-kryptografii/</guid><description>Czasami potrzeba zabezpieczenia dostępu do danych na różne sposoby, tak aby tylko powołane osoby mogły je odczytać. Standardowym, dość powszechnym sposobem jest zaprzęgnięcie do tego celu dedykowanego serwisu, który kontroluje co kto może zrobić (np. LDAP) i podpięcie do niego serwisu zarządzającego …</description><content:encoded>&lt;p&gt;Czasami potrzeba zabezpieczenia dostępu do danych na różne sposoby, tak aby tylko powołane osoby mogły je odczytać. Standardowym, dość powszechnym sposobem jest zaprzęgnięcie do tego celu dedykowanego serwisu, który kontroluje co kto może zrobić (np. LDAP) i podpięcie do niego serwisu zarządzającego danym zasobem (np. dostęp do systemu). Zaletą takiego podejścia jest oczywiście skalowalność i kontrola nad tym co się dzieje, jednak takie podejście zwiększa ilość słabych punktów, które mogą zawieść. Po pierwsze outage dowolnego z nich powoduje niedostępność całej usługi. Po drugie, znalezienie podatności w dowolnym z nich może doprowadzić do nieautoryzowanego dostępu do danych.&lt;br&gt;&#10;Zamiast powyższego podejścia chciałbym pokazać jak można uzyskać podobną &amp;ldquo;funkcjonalność&amp;rdquo; dotyczącą dostępu do danych za pomocą kryptografii. Zamiast kontrolować dostęp aktywnie, przez dedykowany serwis, zaszyfrujemy nasze dane w odpowiedni sposób, za pomocą ogólnodostępnych funkcji.&lt;/p&gt;&#10;&lt;p&gt;Jest kilka różnic w takim podejściu w stosunku do metody opartej o dedykowany serwis. Po pierwsze kryptografia działa offline, więc dostęp do danych będzie miała nawet osoba, która dostała je w zaszyfrowanej formie i jest offline, zatem można udostępnić je bezpiecznie nawet przez pendrive. Po drugie dostęp do danych jest dawany na zawsze. To znaczy, że jeśli raz damy dostęp do nich, to nie możemy go odebrać, a jedynie zaszyfrować dane ponownie, nowymi kluczami, nieznanymi danej osobie, jednak nie mamy gwarancji, że nie dostanie ich w starej formie. W przypadku serwisu typu LDAP wiemy czy ktoś się logował i prosił o dostęp do danego zasobu. Jeśli nie, to możemy mu go najzwyczajniej odebrać.&lt;/p&gt;&#10;&lt;p&gt;Na potrzeby tego wpisu i aby było łatwiej zrozumieć podejście kryptograficzne załóżmy, że nasze dane są trzymane w sejfie, a posiadanie dostępu tego sejfu pozwala odczytać te dane (odszyfrować).&lt;/p&gt;&#10;&lt;h3 id="sejf"&gt;Sejf&lt;/h3&gt;&#10;&lt;p&gt;Po prostu – dostęp do zasobu ma mieć jedynie uppawniona osoba. Dane szyfrujemy, a klucz dajemy zainteresowanemu. Albo zainteresowany daje nam swój publiczny klucz, a my nim szyfrujemy dane i tylko on może je odszyfrować. Jest to najprostsze podejście, które równocześnie pozwala dać dostęp grupie (przez skopiowanie tego samego klucza symetrycznegoosób bez kontroli w czyje ręce się dostanie. W przypadku szyfrowania kluczem asymetrycznym ten problem odpada – zakładamy, że nikt nie chce udostępniać swojego prywatnego klucza innym tylko po to aby mogli odszyfrować jednorazowo dane.&lt;/p&gt;&#10;&lt;h3 id="sejf-w-sejfie"&gt;Sejf w sejfie&lt;/h3&gt;&#10;&lt;p&gt;Wyobraźmy sobie sytuację, gdzie do dostęp do danych ma być uzyskany jedynie za zgodą wszystkich zainteresowanych na raz. Nikt nie dostanie się do naszego sejfu bez wiedzy pozostałych osób. Najprostszym przykładem może być nasz testament. Podczas jego odszyfrowania my będziemy &amp;ldquo;offline&amp;rdquo; z wiadomych względów, natomiast chcemy aby wszyscy zainteresowani (spadkobiercy) zostali powiadomieni i wzięli udział w jego otwarciu.&lt;/p&gt;&#10;&lt;p&gt;Aby uzyskać taką konfigurację musimy zaszyfrować dane (testament) za pomocą wielu różnych kluczy (lub kluczy publicznych różnych osób), które odpowiadać będą wszystkim zainteresowanym:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;zabezpieczone_dane = Sa(Sb(Sc(dane)))&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;gdzie &lt;em&gt;Sx&lt;/em&gt; jest szyfrowaniem za pomocą klucza należącego do osoby &lt;em&gt;x&lt;/em&gt;. W ten sposób każda osoba musi odszyfrować swoją &amp;ldquo;warstwę&amp;rdquo; aby dostać się do właściwych danych. Oczywiście istnieje tutaj ryzyko, że osoba posiadająca klucz &lt;em&gt;Sa&lt;/em&gt; ze względu na niechęć do ujawnienia danych zablokuje ten proces i osoby &lt;em&gt;b&lt;/em&gt; oraz &lt;em&gt;c&lt;/em&gt; nie dowiedzą się co było w środku. Również &lt;em&gt;Sc&lt;/em&gt; może nie podzielić się swoimi odszyfrowanymi danymi, po dowiedzeniu się co jest w środku.&lt;/p&gt;&#10;&lt;p&gt;Analogią jest tu oczywiście zamknięcie małego sejfu w większym, a tego w jeszcze większym. Aby dostać się do najmniejszego z nich otwarte muszą być wszystkie wcześniejsze drzwiczki większych sejfów, a więc wszyscy posiadacze kluczy muszą współpracować. W przypadku kryptografii współpraca (oraz przebywanie w jednym miejscu) nie jest już tak oczywiste i może częściowo zablokować dostęp do danych tak jak w opisanym przypadku.&lt;/p&gt;&#10;&lt;p&gt;Innym, dość chamskim przykładem takiego zabezpieczenia wymagającego współpracę dwóch lub więcej osób jest przypięcie komuś roweru dodatkowym zapięciem. Bez Was nie odjedzie swoim jednoślaedm ]:-&amp;gt; &lt;small&gt;Pozdrowienia dla Moniki z Motoroli. Pół biura Cie szukało żeby odpiąć mój rower :D&lt;/small&gt;&lt;/p&gt;&#10;&lt;p&gt;Natomiast jeśli dane są bardzo duże, to możemy użyć tymczasowego klucza (de)szyfrującego, który jest zamknięty w sejfach. Dopiero po otrzymaniu tego klucza można dostać się do właściwych dancyh, zamkniętych w innym, pojedynczym sejfie (zaszyfrowanych tym kluczem).&lt;/p&gt;&#10;&lt;h3 id="sejf-z-wieloma-drzwiczkami"&gt;Sejf z wieloma drzwiczkami&lt;/h3&gt;&#10;&lt;p&gt;Kolejnym podejściem jest zezwolenie na dostęp do dancyh/sejfu dowolnej osobie z grupy, ale z założeniem, że każdy ma swój inny, unikalny klucz. Najpopularniejszym rozwiązaniem tego problemu jest szyfrowanie dysków w naszych komputerach (halo windows, u Was też?). Każdy użytkownik systemu może ustawić swoje hasło do szyfrowania dysku, którym zaszyfrowany jest docelowy klucz. Podczas startu systemu podając jedno z haseł odszyfrowujemy tak na prawdę docelowy klucz symetryczny, którym jest zaszyfrowany cały dysk. Dzięki temu, oprócz możliwości udzielenia dostępu dla wielu osób, możemy w dowolnym momencie dodać lub usunąć hasło do odszyfrowania systemu plików, bez konieczności re-szyfrowania całego dysku. Zmieniając hasło, zapisujemy jedynie kilkadziesiąt/kilkaset bajtów zaszyfrowanego głównego klucza za pomocą naszego nowego hasła.&lt;/p&gt;&#10;&lt;p&gt;Jak takie coś wygląda w prawdziwym życiu? Ano tak:&lt;/p&gt;&#10;&lt;figure class="aligncenter"&gt;&#10;&#9;&lt;img src="https://nabozny.io/uploads/2020/10/locks.jpg" srcset="https://nabozny.io/uploads/2020/10/locks_hu_4a13a839255a0276.jpg 600w, https://nabozny.io/uploads/2020/10/locks.jpg 1024w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" alt="" width="1024" height="764" loading="lazy" decoding="async"&gt;&#10;&#9;&lt;figcaption&gt;&lt;small&gt;https://www.geograph.org.uk/photo/5932928&lt;/small&gt;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;Aby dostać się za taką bramkę trzeba odpiąć łańcuch. Aby to zrobić zdjęta musi być jedna z kilku kłódek. Każda z nich odpowiada konkretnemu mieszkańcowi posesji. Co jeśli ktoś zgubi klucz? Tylko ta osoba kupuje nową kłódkę i zakłada na swoje miejsce, bez zawracania głowy innym osobom dorabianiem nowego klucza.&lt;/p&gt;&#10;&lt;p&gt;W przypadku analogi do sejfu mielibyśmy skrzynkę nie z jednymi, a z wieloma drzwiczkami, każde z osobnym kluczem.&lt;/p&gt;&#10;&lt;h3 id="otwarcie-n-z-m-zamków"&gt;Otwarcie N z M zamków&lt;/h3&gt;&#10;&lt;p&gt;Moim zdaniem najciekawszym sposobem zabezpieczenia danych jest otwarcie sejfu (odszyfrowanie) przy dostępnych jedynie M kluczach z N, gdzie oczywiście M &amp;lt; N. Czyli mamy coś pomiędzy drugim a trzecim opisywanym rozwiązaniem: do otwarcia nie muszą być obecni wszyscy, ale nie może to być też jedna osoba. Sytuacja taka może być wymagana gdy na przykład bank wymaga do wysłania przelewu potwierdzenia od większości udziałowców firmy. Czyli mogą to być na przykład dowolne 4 z 7 osób. Zaimplementowanie tego mając centralny serwis jest oczywiście proste. Natomiast jak to zrobić z użyciem kryptografii? Wróćmy do czasów liceum albo nawet gimnazjum (lub końca podstawówki, jeśli gimb tu nie ma :) Jedna z mniej „pożytecznych” rzeczy, która była przez bardzo długi czas wałkowana, nawet jeszcze na studiach, to wielomiany. Gdzieś w tym okresie nauki pojawiało się też twierdzenie, że przez dowolne X punktów przechodzi dokładnie jeden wielomian X+1 stopnia. Aby to dobrze zwizualizować, wyznacz dwie kropki obok siebie i spróbuj przez nie narysować kilka paraboli. Działa? Tak! Parabola jest wielomianem 2-go stopnia. Jeśli wyznaczysz gdzieś pomiędzy trzecią kropkę, okaże się, że da się tamtędy przeprowadzić jedynie jedną parabolę (bez znaczącego jej wyginania :D ) Uff, dowód matematyczny za nami.&lt;/p&gt;&#10;&lt;figure class="aligncenter"&gt;&#10;&#9;&lt;img src="https://nabozny.io/uploads/2020/10/polynomial.png" alt="" width="499" height="346" loading="lazy" decoding="async"&gt;&#10;&#9;&lt;figcaption&gt;&lt;small&gt;Źródło: Wikipedia&lt;/small&gt;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;W czym to pomoże?&lt;/p&gt;&#10;&lt;p&gt;Osoba trzymająca pieczę nad sejfem (lub danymi) może ustawić jako jego kod dostępu (klucz szyfrujący) miejsca zerowe wielomianu (czyli tam, gdzie linia przecina się z poziomą osią na wykresie). Wielomian taki musi być stopnia odpowiadającego ilości wymaganych osób do otwarcia lub odszyfrowania danych. Czyli jeśli będziemy potrzebowali jednoczesnej współpracy 4 osób, to musimy „wylosować” wielomian 3 stopnia. Następnie dajemy każdej zainteresowanej osobie jeden punkt leżący na tym wielomianie. Punktów możemy wylosować do woli, bez ograniczeń, gdyż taki wielomian ciągnie się od -oo do +oo, a powyższe twierdzenie działa dla dowolnych punktów. Dzięki temu jeśli znajdą się wymagane 4 osoby chcące znaleźć klucz do odszyfrowania danych, to uda im się to przez wyznaczenie miejsc zerowych wielomianu, bazującego na ich 4 punktach, przez które przechodzi ten wielomian.&lt;/p&gt;&#10;&lt;p&gt;Dużo danych i cyferek&amp;hellip; wracając do przykładu potwierdzaniem przelewu w banku dla większości z 7-osobowego zarządu:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&amp;ldquo;Większość&amp;rdquo; to dowolne 4 osoby z 7&lt;/li&gt;&#10;&lt;li&gt;Zatem wielomian musi być stopnia 4-1, czyli trzeciego&lt;/li&gt;&#10;&lt;li&gt;Potrzebujemy 7 różnych punktów dla 7 różnych członków zarządu&lt;/li&gt;&#10;&lt;li&gt;Mając taki wielomian losujemy dowolne 7 punktów X,Y leżące na tym wielomianie, które nie są miejscami zerowymi&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Zatem po spotkaniu się 4 dowolnych osób, dostają one zadanie matematyczne polegające na znalezieniu wielomianu trzeciego stopnia przechodzącego przez ich punkty i wyznaczenia jego miejsc zerowych. Dla niewtajemniczonych, miejsce zerowe to tam, gdzie wykres wielomianu przecina się z osią poziomą. Dla mniej wtajemniczonych: narysuj dowolną parabolę przecinającą oś poziomą – to tam gdzie się przecina :) Wyznaczone miejsca zerowe, na przykład po zamianie na stringi i konkatenacji stają się naszym kluczem do odszyfrowania danych.&lt;/p&gt;&#10;&lt;p&gt;Skomplikowane&amp;hellip; ale z drugiej storny pomyśl o tym gdy z kolegą będziesz szukał miejsc zerowych aby gdzieś w sercu Bieszczad potwierdzić bankowi przelew, a zasięgu i komputera akurat brak ;)&lt;/p&gt;&#10;&lt;h3 id="bonus-otwarcie-n-z-m-zamków-z-bossem-"&gt;Bonus: Otwarcie N z M zamków z bossem :)&lt;/h3&gt;&#10;&lt;p&gt;Manipulując odpowiednio stopniem wielomianu oraz ilością punktów, jakie dostają poszczególne osoby możemy też przydzielić odpowiednie „wagi” tym osobom. Jeśli do dostępu do danych chcemy co najmniej jedną osobę z zarządu firmy i dowolnych 3 pracowników, lub dowolne dwie osoby z zarządu bez udziału pracowników, to każdy z zarządu może wtedy dostać odpowiednio więcej punktów leżących na wielomianie, ale w taki sposób, aby dalej brakowało mu trzech z nich.&lt;/p&gt;&#10;&lt;p&gt;Tak więc „boss” mający X-3 punkty potrzebuje co najmniej 3 pracowników do uzyskania klucza do odszyfrowania danych (tj. wyznaczenia tego wielomianu). Jeśli natomiast znajdzie innego „bossa”, to razem mają wręcz nadmiar punktów niezbędnych do ustalenia miejsc zerowych i odszyfrowania danych. Dzięki takiemu mechanizmowi możemy w prosty sposób kontrolować ile jakich osób będzie wymaganych do dostępu do danych.&lt;/p&gt;&#10;&lt;h3 id="co-jeszcze"&gt;Co jeszcze&lt;/h3&gt;&#10;&lt;p&gt;Do powyższych metod dochodzą też sposoby na usuwanie poszczególnych posiadaczy częściowego klucza lub aktualizacje kluczy, jak również cała matematyka polegająca na określeniu złożoności i bezpieczeństwa takich kluczy. Do tego polecam już jednak bardziej techniczne dokumenty.&lt;/p&gt;&#10;&lt;p&gt;Większość powyższych metod jest zaimplementowana w frameworku &lt;a href="https://dinemic.io"&gt;dinemic&lt;/a&gt;, który za pomocą podobnych mechanizmów kontroluje i zarządza dostępem do rozproszonej bazy danych.&lt;/p&gt;</content:encoded></item><item><title>Wakacje Tyrol vs. Beskid Sądecki</title><link>https://nabozny.io/wakacje-tyrol-vs-beskid-sadecki/</link><dc:creator>maciej</dc:creator><pubDate>Sun, 13 Sep 2020 09:26:12 +0000</pubDate><category>Uncategorized</category><guid isPermaLink="true">https://nabozny.io/wakacje-tyrol-vs-beskid-sadecki/</guid><description>Porównanie pobytu tu i tam, z nastawieniem na to aby nie zbankrutować i mieć fajne wakacje.</description><content:encoded>&lt;p&gt;Porównanie pobytu tu i tam, z nastawieniem na to aby nie zbankrutować i mieć fajne wakacje.&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://nabozny.io/uploads/2020/09/au2.jpg" srcset="https://nabozny.io/uploads/2020/09/au2_hu_bad09c8bbd04e778.jpg 600w, https://nabozny.io/uploads/2020/09/au2_hu_c2973fb3152af3da.jpg 1200w, https://nabozny.io/uploads/2020/09/au2.jpg 1296w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" alt="" width="1296" height="728" class="alignnone size-full" loading="lazy" decoding="async"&gt;&lt;/p&gt;&#10;&lt;p&gt;Krynica – znaleziony nocleg w pokoju 20m2 z łazienką i TV, niedaleko centrum po dość długich poszukiwaniach z widokiem na sąsiadującą plebanie. Tyrol – apartament znaleziony na Interhome, z promocją last minute. Ok. 70m2, z 3 pokojami, łazienką, w pełni wyposażoną kuchnią, TV i 3 balkonami na wszystkie strony z pięknym widokiem. Porównanie cen dla 2 dorosłych, dwójki dzieci do 6 lat, na 14 dni. Wszystkie ceny w zł.&lt;/p&gt;&#10;&lt;h3 id="nocleg-i-mieszkanie"&gt;Nocleg i mieszkanie&lt;/h3&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&lt;td&gt;Austria – Zillertal&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Polska – Krynica&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Nocleg 2 dorosłych i 2 dzieci&lt;/td&gt;&lt;td&gt;2700&lt;/td&gt;&lt;td&gt;Mieszkanie 60m2 z kuchnią i łazienką, 3 balkony, z Interhome&lt;/td&gt;&lt;td&gt;2100&lt;/td&gt;&lt;td&gt;Pokój 20m2 z łazienką, 1 okno&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Dojazd&lt;/td&gt;&lt;td&gt;500&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;70&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Parking&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;Duży parking przy domu w cenie&lt;/td&gt;&lt;td&gt;140&lt;/td&gt;&lt;td&gt;10zł/dzień, płatne ekstra&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Podatek lokalny&lt;/td&gt;&lt;td&gt;259&lt;/td&gt;&lt;td&gt;2,2eur za dorosłą osobę, sąsiedzi nie palą śmieciami&lt;/td&gt;&lt;td&gt;246&lt;/td&gt;&lt;td&gt;4,4zł za osobę&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;&lt;em&gt;Razem:&lt;/em&gt;&lt;/td&gt;&lt;td&gt;3459zł&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;2556zł&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="atrakcje"&gt;Atrakcje&lt;/h3&gt;&#10;&lt;p&gt;Tutaj Tyrol niestety przegrywa. Nie ma górali, na próżno również szukać parkingowych czychających za każdym rogiem, ulicznych wysokiej klasy artystów z krupówek lub misia. Rekompensuje to natomiast uprzejmość lokalnych mieszkańców. Nie pozna się też wielu ciekawych ludzi, ich kultury i historii czekając od 5 do 9 w kolejce do kolejki na Kasprowy.&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&lt;td&gt;Wyjazd kolejką na dużą górę&lt;/td&gt;&lt;td&gt;160&lt;/td&gt;&lt;td&gt;Ahorn, brak kolejek do wejścia, parking pod kolejką w cenie&lt;/td&gt;&lt;td&gt;240&lt;/td&gt;&lt;td&gt;Kasprowy, czekanie w kilkugodzinnej kolejce, parking i dojazd pod kolejkę ekstra&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Wjazd kolejką na małą górę&lt;/td&gt;&lt;td&gt;ok. 70&lt;/td&gt;&lt;td&gt;Żeby przejechać się małą kolejką pokroju tej z Jaworzyny, trzeba najpierw wjechać na dużą górę&lt;/td&gt;&lt;td&gt;64&lt;/td&gt;&lt;td&gt;Jaworzyna Krynicka, parking gratis!&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Wjazd na lodowiec&lt;/td&gt;&lt;td&gt;250&lt;/td&gt;&lt;td&gt;Hintertux, parking gratis&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;Brak lodowców&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Atrakcja – punkt widokowy&lt;/td&gt;&lt;td&gt;32&lt;/td&gt;&lt;td&gt;Przejazd ponad 30km przez Hohenstrasse na ponad 2000m, w tym zwiedzanie parku świstaków, liczne wodospady, trasa nad chmurami. Opłata jedynie za wjazd samochodu. Należy doliczyć paliwo&lt;/td&gt;&lt;td&gt;208&lt;/td&gt;&lt;td&gt;Wejście na wieżę widokową z wjazdem kolejką na Jaworzynę&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Wyjście na szlak&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;Niektóre fajne szlaki zaczynają się tak wysoko, że opłaca się wjechać na nie kolejką, żeby nie marnować czasu. Sporo jest też tych z samego dołu&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;Cena za wstęp na 3 korony&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Parking pod szlakiem&lt;/td&gt;&lt;td&gt;20-40&lt;/td&gt;&lt;td&gt;za pozostawienie samochodu wysoko w górach, na całą dobę&lt;/td&gt;&lt;td&gt;20zł&lt;/td&gt;&lt;td&gt;Zapłacone jakiś czas temu za pozostawienie auta gdzieś na błocie, na prywatnym polu&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Dojazd pociągiem do miasta&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;Zillertal bahn&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;Krynica – Piwniczna&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Godzina parkingu&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;ok. 1-1.5eur blisko centrum&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;SPP w Krynicy&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Dojazd do większego miasta&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;Innsbruck, 70km&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;td&gt;Kraków, 130km&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Jezioro z plażą i placem zabaw&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;Achensee, 4eur za 4 godziny parkingu, wstęp i atrakcje gratis&lt;/td&gt;&lt;td&gt;45&lt;/td&gt;&lt;td&gt;Kryspinów, dorośli po 15zł, auto 15zł. Jedyne znane mi jezioro, które choć trochę przypomina standardem darmowe Achensee. Dodatkowa atrakcja – Krakowskie towarzystwo&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;&lt;em&gt;Razem&lt;/em&gt;&lt;/td&gt;&lt;td&gt;549&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;1153&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="jedzenie"&gt;Jedzenie&lt;/h3&gt;&#10;&lt;p&gt;Z powodu braku kuchni pobyt w większości &amp;ldquo;apartamentów&amp;rdquo; w Krynicy wiąże się z wykupieniem wyżywienia lub chodzeniem od knajpy do knajpy. Za to w Tyrolu nie uświadczymy bezmięsnych parówek podawanych na każdą kolację na przemian z rozmoczonymi płatkami z mlekiem. Z drugiej strony w Krynicy nie musimy udawać weganina i unikać mięsa ze względu na jego ceny, możemy za to rozkoszować się własnym niezbyt smacznym jedzeniem, jeśli średnio gotujemy.&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&lt;td&gt;Jedzenie&lt;/td&gt;&lt;td&gt;1200&lt;/td&gt;&lt;td&gt;Przywiezione w większości kupione gotowe, konserwowe dania.&lt;/td&gt;&lt;td&gt;2100&lt;/td&gt;&lt;td&gt;Wykupione w pensjonacie, porównywalnej jakości do konserw wywiezionych do Austrii&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Kilo mięsa&lt;/td&gt;&lt;td&gt;40-50&lt;/td&gt;&lt;td&gt;Lokalne sklepy nie mają dużego wyboru, zwykle pakowane kawałki kurczaka lub świni&lt;/td&gt;&lt;td&gt;15-25zł&lt;/td&gt;&lt;td&gt;Zwykle nie ma na czym ugotować&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Kawa na mieście&lt;br /&gt;&lt;small&gt;W dobrej kawiarni/knajpie&lt;/small&gt;&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Kawa w trasie&lt;br /&gt;&lt;small&gt;w schronisku lub na górnej stacji kolejki&lt;/small&gt;&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Dobry chleb żytni&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Szynka, 100g&lt;br /&gt;&lt;small&gt;Pakowane w plasterkach, tanie coś, bez makulatury w składzie&lt;/small&gt;&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Masło&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Jajka, 20szt&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Słodka bułka&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;Croissant&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;Drożdżówka z makiem&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;&lt;em&gt;Razem:&lt;/em&gt;&lt;/td&gt;&lt;td&gt;ok. 1300&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;ok. 2153&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Powyższe ceny są orientacyjne. Niektórzy chcą pozostać przy diecie &amp;ldquo;polskiej&amp;rdquo;, inni będą wcinać lokalne specjały, które są droższe, a jeszcze inni zmontują obiad z tego, co jest lokalnie najtańsze. Warto też wiedzieć, że większość knajp w Tyrolu ma zwykle kilka miejsc parkingowych dla gości gratis.&lt;/p&gt;&#10;&lt;h3 id="inne"&gt;Inne&lt;/h3&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&lt;td&gt;Diesel&lt;/td&gt;&lt;td&gt;4,7&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;4,2&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;Benzyna&lt;/td&gt;&lt;td&gt;4,9&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;4,5&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;tr&gt;&lt;td&gt;LPG&lt;/td&gt;&lt;td&gt;3,5&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;2,2&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Jak widać, może mamy wysokie podatki, ale za to ceny są wyższe :) Atrakcje również nieporównywalnie wyższe, co za tym idzie człowiekowi nawet przez myśl nieprzejdzie rozkoszowanie się widokami gór, na które w Tyrolu żeby popatrzeć, trzeba odginać głowę do góry. W Polsce to nie grozi, bo co chwile schyla ją do portfela po kolejne opłaty to tu to tam.&lt;/p&gt;&#10;&lt;p&gt;Jadąc za granicę opłaca się wybrać w więcej osób. Zwykle apartamenty kosztują tyle samo niezależnie od ilości gości, co w Polsce jest żadkością i kasuje się od głowy.&lt;/p&gt;</content:encoded></item><item><title>Czemu mi srand nie działa</title><link>https://nabozny.io/czemu-mi-srand-nie-dziala/</link><dc:creator>maciej</dc:creator><pubDate>Fri, 26 Jun 2020 09:37:47 +0000</pubDate><category>Uncategorized</category><guid isPermaLink="true">https://nabozny.io/czemu-mi-srand-nie-dziala/</guid><description>Czasami człowiek spędzi dwa tygodnie na durny błąd, którego testy ani wszelkie debugowanie w żaden sposób nie zweryfikują. O co poszło tym razem? Wcisnąłem parę dinemic i jego wrapper dla pythona do Flaska. Ot co, alternatywa dla ORM Django i SqlAlchemy, w dodatku nie trzeba się martwić o …</description><content:encoded>&lt;p&gt;Czasami człowiek spędzi dwa tygodnie na durny błąd, którego testy ani wszelkie debugowanie w żaden sposób nie zweryfikują. O co poszło tym razem? Wcisnąłem parę &lt;a href="https://dinemic.io"&gt;dinemic&lt;/a&gt; i jego wrapper dla pythona do Flaska. Ot co, alternatywa dla ORM Django i SqlAlchemy, w dodatku nie trzeba się martwić o uprawnienia, wewnętrzne API i tak dalej&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;Wszystko szło dobrze, natomiast po dłuższym użytkowaniu zauważyłem, że czasami obiekty w bazie nie chcą się tworzyć, może w 1 na 10 lub na 20 przypadkach. Winny oczywiście Sync processor, który prawdopodobnie miał lukę gdzieś w zawiłej logice odpowiedzialnej za procesowanie zmian w klastrze. Zwykle takich problemów nie ma, gdy za każdym mikroserwisem stoi baza danych i tylko ten mikroserwis ją modyfikuje (ewentualnie kilka jego wątków, korzystając z locków). Dinemic daje nieco inne podejście, gdzie każdy może rozesłać zmianę bazy, a dopiero logika naszego programu ma stwierdzić, czy taką zmianę akceptuje, czy nie. W praktyce, ciąg zmian związany ze stworzeniem i cyklem życia obiektu zamiast tak:&lt;br&gt;&#10;&lt;img src="https://nabozny.io/uploads/2020/06/dinemic-chain.png" alt="" width="148" height="814" class="alignnone size-full" loading="lazy" decoding="async"&gt;&lt;/p&gt;&#10;&lt;p&gt;wygląda tak:&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://nabozny.io/uploads/2020/06/dinemic-trees.png" srcset="https://nabozny.io/uploads/2020/06/dinemic-trees_hu_db20e424a9e0d9f0.png 600w, https://nabozny.io/uploads/2020/06/dinemic-trees_hu_f80511eb0f6b181d.png 1200w, https://nabozny.io/uploads/2020/06/dinemic-trees.png 1431w" sizes="(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px" alt="" width="1431" height="669" class="alignnone size-full" loading="lazy" decoding="async"&gt;&lt;/p&gt;&#10;&lt;p&gt;Każdy bloczek w powyższym to mała wiadomość wędrująca po całym klastrze z informacją np. w polu A zmień wartość na X. Kto ją dostanie, może zaaplikować u siebie, zweryfikować podpis obiektu, który zmianę wykonał lub sprawdzić ciągłość całego łańcucha (lub drzewka). Taka komplikacja frameworka miała na celu umożliwienie pracy w niekonsystentnym środowisku, na rozproszonej bazie. Czemu zmiany są aż tak pokomplikowane? Pomyśl, że chcesz się umówić na piwo z 10 znajomymi. Wysyłasz wszystkim SMS, że w piątek o 20 idziecie na piwo. 6 odpisze, że ok, 1 w między czasie umówi się na inne piwo i za godzine odpisze, że jest zajęty, a pozostałych trzech jest poza zasięgiem. To jesteście umówieni? Na piwo trzeba iść, a z pozostałą czwórką umówić się w innym terminie lub skontaktować inaczej. Zwykle rozwiązanie zależy od &amp;ldquo;mózgu&amp;rdquo; operacji i tego co zrobi z pozostałą czwórką. Ot, takie życie. Podobne założenia były w dinemic – kto dostanie informacje o zmianie w bazie, ten (jakoś) zareaguje, a kto nie dostanie, ten musi radzić sobie sam. W takiej architekturze już na wstępie mamy mocno niekonsystentną bazę w obrębie klastra, a jedyne co powinno się zgadzać to cała historia zmian.&lt;/p&gt;&#10;&lt;p&gt;Wróćmy do naszych wiadomości o zmianach (sms z zaproszeniem na piwo). Jako, że wspólnego, konsystentnego indeksu nie mamy, to każda zmiana ma losowy ID, do tego hash poprzedniej zmiany oraz swój podpis. Problem z Flaskiem rozpoczął się dość niewinnie – jakby niektóre zmiany nie były poprawnie procesowane i ignorowane. Po prostu system twierdził, że wiadomość była już przetworzona.&lt;/p&gt;&#10;&lt;p&gt;Wróćmy na chwilę do Flaska i tego, jak działa serwer www. Flask przy uruchamianiu serwera przez skrypt pythona tworzony jest główny wątek. W nim można m.in. zainicjalizować framework dinemic (lub cokolwiek innego) i przygotować wszystko co potrzeba do odpalenia serwisu. Po otrzymaniu nowego połaczenia od klienta serwer tworzy proces potomny i w nim obsługuje request.&lt;/p&gt;&#10;&lt;p&gt;Niby proste, a jednak nie. Jeśli wszystko inicjalizujemy w głównym wątku, to również generator liczb losowych (pseudolosowych), czyli srand(time(NULL)). Niezależnie od tego jaką wartość podamy do srand, to powinien dać pseudolosowe liczby, o dobrym rozkładzie. Jeśli jednak zainicjalizujemy go dwukrotnie tą samą wartością, to zawsze dostaniemy taką samą serię liczb.&lt;/p&gt;&#10;&lt;p&gt;W czym zatem problem? Srand inicjalizujemy w głównym wątku i generuje on X liczb pseudolosowych. Dla każdego klienta Flask tworzy nowy wątek, w którym również potrzebne są nowe liczby losowe (bo na przykład każdy update generowany w takim wątku potrzebuje swoje ID). Czym to skutkuje? Po forku proces potomny generuje X+1 liczbę losową. Dla drugiego klienta fork również generuje liczbę, uwaga uwaga: X+1. I tak dalej&amp;hellip; rand wypluwa zawsze pseudolosową, kolejną liczbę z generowanego ciągu. Jeśli skopiujemy proces (przez fork, pthread z odseparowaną pamięcią lub jakikolwiek sposób), to licznik zaczyna się dublować z innymi procesami. W ten sposób każdy proces potomny dostaje ten sam ciąg kolejnych liczb pseudolosowych, dla danej wartości początkowej z srand.&lt;/p&gt;&#10;&lt;p&gt;Dzięki temu możnaby ze 100% skutecznością zgadywać z procesu-brata jakie liczby wylosuje drugi proces. Na zakończenie warto jeszcze opowiedzieć jak udało się to rozwiązać (chociaż po znalezieniu problemu nie było to trudne). Rand z C++ został zamieniony na generator liczb losowych z libsodium. Praktycznie bez zmiany logiki, algorytmów i dużego grzebania w kodzie. Dużym plusem jest to, że libsodium nie wymaga inicjalizowania generatora liczb pseudolosowych i zwraca za każdym razem losowe wartości, co w przypadku biblioteki takiej jak dinemic ma duże znaczenie – nigdy nie wiadomo czy aplikacja macierzysta nie zacznie się forkować.&lt;/p&gt;&#10;&lt;p&gt;Ot, głupi błąd, 2 tygodnie szukania i przy okazji zrefactorowany najpaskudniejszy kawałek logiki frameworka.&lt;/p&gt;</content:encoded></item></channel></rss>