2022-06-24
To bardzo wygodne, kiedy łącząc się przy pomocy putty do Linuxa, nie trzeba podawać hasła. Takie rzeczy są w świecie Linuxowym znane jako uwierzytelnienie kluczem prywatnym. O tym jak taki klucz wygenerować pisałem tutaj: Mobilo » Blog Archive » Linux: Generowanie klucza SSH do logowania bez hasła (mobilo24.eu)
Niestety ten klucz prywatny nie nadaje się do bezpośredniego użycia w putty. Można go skonwertować. Oto jak:
- Otwórz program Putty Gen – jest elementem pakietu putty
- Wybierz polecenie Convertions >> Import Key. Poszukaj pliku klucza prywatnego. Jeśli go nie widzisz w katalogu, to w oknie „Load private key” zmień filtr na wyświetlane pliki na All Files (*.*)
- Jeśli trzeba podaj hasło do otwarcia pliku.
- Zapisz klucz prywatny klikając „Save Private Key”.
- Skorzystaj z klucza w putty:
- Connection >> Data – podaj nazwę użytkownika w polu auto-login username
- Connection >> SSH >> Auth – wskaż na plik ppk z zapisanym w 4-tym kroku kluczem. Ścieżka powinna się pojawić w polu private key file for authentication
- Zapisz zmiany dokonane w sesji
- Wykonaj testowe połączenie
Jeśli masz problem z połączeniem zobacz, jak go zdiagnozować: Mobilo » Blog Archive » Linux: ssh: debug: server refused our key (mobilo24.eu)
2022-06-24
Prosta sprawa – ale prosta, dopiero jak się wie. Póki się nie wiedziało… to efekt był taki, że mimo logowania za pomocą klucza prywatnego i publicznego klient dostawał ciągle odpowiedź „server refused our key”.
Mniej więc tutaj chcę się skupiać na rozwiązaniu konkretnego problemu, a bardziej na tym, jak diagnozować ten problem. A diagnozowanie jest proste.
1. Na serwerze (bo przecież to server odrzuca klucz) przejdź do pliku konfiguracyjnego sshd:
sudo vim /etc/sshd/sshd_config
2. W tym pliku dodaj linijkę:
LogLevel DEBUG3
3. Zrestartuj sshd:
sudo systemctl restart sshd
4. Przeprowadź kolejne logowanie, które pewnie zakończy się błędem „server refused our key”
5. Przeszukaj zawartość pliku /var/log/auth.log lub /var/log/secure (nazwa pliku może się różnić w zależności od wersji).
No i na tym można by skończyć, bo przykładowy wpis w pliku log może być taki:
Jun 24 18:18:48 u20 sshd[22912]: debug1: temporarily_use_uid: 1000/1000 (e=0/0)
Jun 24 18:18:48 u20 sshd[22912]: debug1: trying public key file /home/boss/.ssh/authorized_keys
Jun 24 18:18:48 u20 sshd[22912]: debug1: Could not open authorized keys '/home/XXX/.ssh/authorized_keys': No such file or directory
Jun 24 18:18:48 u20 sshd[22912]: debug1: restore_uid: 0/0
Jun 24 18:18:48 u20 sshd[22912]: debug1: temporarily_use_uid: 1000/1000 (e=0/0)
Jun 24 18:18:48 u20 sshd[22912]: debug1: trying public key file /home/XXX/.ssh/authorized_keys2
Jun 24 18:18:48 u20 sshd[22912]: debug1: Could not open authorized keys '/home/XXX/.ssh/authorized_keys2': No such file or directory
Jun 24 18:18:48 u20 sshd[22912]: debug1: restore_uid: 0/0
Jun 24 18:18:48 u20 sshd[22912]: debug3: mm_answer_keyallowed: publickey authentication test: RSA key is not allowed
Innymi słowy, chociaż klucz publiczny miał być w katalogu .ssh, to jednak go tam nie było 🙂 Głupotka….
Zauważ, że ten rodzaj błędu był logowany na poziomie debug1, a my w pliku konfiguracyjnym napisaliśmy debug3. Ten zwiększony poziom szczegółowości może się przydać np. jeśli w kluczu straciła się jedna literka. Ten rodzaj informacji jest logowany na poziomie 3.
2022-06-19
Kiedy administrator chce utworzyć plik w katalogu systemowym może do tego wykorzystać przekierwoanie polecenia echo. Zazwyczaj katalogi systemowe mają okrojone uprawnienia, dlatego dla pomyślnego utworzenia pliku potrzebne są podniesione uprawnienia. Zwykle robi się to przez sudo. Niestetuy, ta metoda też czasami zawodzi:
rafal@fermat:/var/log$ echo "test" > test.txt
bash: test.txt: Permission denied
rafal@fermat:/var/log$ sudo echo "test" > test.txt
bash: test.txt: Permission denied
Dlaczego tak się dzieje? Otóżn znak przekierowania > ale też znak potoku | jest interpretowane przez bash. Oznaczza to, że w przypadku tego konkretnego polecenia dzieją się następujące rzeczy:
- polecenie sudo pyta o haslo użytkownika
- sudo uruchamia echo z uprawnieniami administratora
- echo kończy swoje działanie
- sudo kończy swoje działanie
- wynik poleceń jest przekierowywany do pliku już z uprawnieniami normalnego użytkownika, co… kończy się błędem
Jak rozwiązać problem? Należy spowodować, żeby zarówno echo jak i przekierowanie były wykonywane z podniesionymi uprawnieniami. Jedną z metod jest uruchomienia bash z opcją -c powodującą uruchomienie tylko jednej, przekazywanej dalej jako parametr komendy. Ta komenda powinna być poprawnym napisem, no i poprawną komendą, tak jak tutaj:
rafal@fermat:/var/log$ sudo bash -c 'echo "test" > test.txt'
[sudo] password for rafal:
rafal@fermat:/var/log$ ls -l test*
-rw-r--r-- 1 root root 5 cze 19 15:14 test.txt
2022-06-09
Był sobie użytkownik. Ten użytkownik łączył się do swojej bazy danych w PostgreSQL korzystając z pgBouncera. Tyle dobrego mówi się o zarządzaniu połączeniami przez pgBouncera, że hohoho, więc użytkownik robił dobrze, że robił tak jak robił.
Pojawił się jednak problem… czasami ni z tego ni z owego pojawiał się komunikat mówiący o tym, że zapytanie wykonywane na serwerze zostało anulowane z powodu przekroczenia statement_timeout. Nie byłoby w tym nic dziwnego, gdyby nie to, że użytkownik przysięgał, że nie ustawiał u siebie statement_timout. Kto by mu tam wierzył!?
ERROR: canceling statement due to statement timeout
Czasami z kolei, użytkownik narzekał, że zmienił mu się parametr search_path. Ten parametr pozwala ustalić jakie schematy mają być przeszukiwane, jeśli użytkownik napisze zapytanie do tabeli, nie podając jawnie, w jakim schemacie ta tabela się znajduje. Dlatego użytkownik od czasu do czasu dostawał błąd „nie ma takiej tabeli” i się strasznie denerwował. Oczywiście przysięgał, że sam tego parameteru nigdy nie zmieniał, ale …. kto by mu tam wierzył!?
Na dodatek, podobno, jeśli użytkownik łączył się bezpośrednio do serwera, a nie przez pgBouncer, to problemu nie było. Hmmm ciekawe, co?
O co chodzi?
PgBouncer może pracować w różnych trybach zarządzania połączeniami (connection pooling). Dwa najpopularniejsze to SESSION i TRANSACTION.
W SESSION, użytkownik otwiera połączenie do pgBouncer, a pgBouncer łączy się do PostgreSQL. Połączenie jest otwarte tak długo, jak długo trwa sesja użytkownika, co daje mniejsze oszczędności zasobów po stronie PostgreSQL. Za to, kiedy połączenie się kończy, to jest wykonywany reset ustawień takiej sesji. Wszystkie jej opcje jak np. wspomniany statement_timeout czy search_path wracają do pierwotnych ustawień. Odpowiada za to parametr pgBouncera o nazwie server_reset_query. Domyślna jego wartość to DISCARD_ALL i ta nazwa właściwie mówi wszystko sama za siebie. Wprawdzie otwarte sesje pozostaną otwarte dość długo, ale jak już zostaną zwolnione, to pgBouncer nie musi ich na nowo budować, więc jednak jakaś oszczędność zasobów jest.
W TRANSACTION, użytkownik otwiera połączenie do pgBouncer, a pgBouncer łączy się do PostgreSQL. Połączenie jest otwarte między pgBouncerem a PostgreSQLem dłużej, ale użytkownik dostaje je do dyspozycji tylko na czas działania jego transakcji. Transakcje powinny być krótkie, więc jedno połączenie pomiędzy PostgreSQL, a pgBouncerem może być wykorzystywane wiele razy. Niestety, podczas przekazywania połączeń między użytkownikami, nie jest odświeżane środowisko sesji, czyli „dziedziczy się” ustawnienia takie jak statement_timeout, czy search_path .
No i wiesz już pewnie jakie ustawienie miał mój nieszczęsny użytkownik? Tak – TRANSACTION. Opcje ustawione w jednej sesji, zaczynały działać w innej i stąd cały problem, Na nieco zmodyfikowanych ustawieniach pgBouncera (tylko 1 połączenie per 1 użytkownik per 1 baza danych w modelu TRANSACTION wyglądało to mniej więcej tak: Czytaj dalej »
2022-06-05
Ponieważ na serwerze występowały pewne problemy z pracą sterownika bazy danych, trzeba było sprawdzić jaka wersja biblioteki libpq-dev jest zainstalowana. Oto kilka metod:
apt-cache
apt-cache policy libpq-dev
libpq-dev:
Installed: 12.11-0ubuntu0.20.04.1
Candidate: 12.11-0ubuntu0.20.04.1
Version table:
*** 12.11-0ubuntu0.20.04.1 500
500 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages
500 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages
100 /var/lib/dpkg/status
12.2-4 500
500 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 Packages
apt list
apt list -a libpq-dev
Listing... Done
libpq-dev/focal-updates,focal-security,now 12.11-0ubuntu0.20.04.1 amd64 [installed]
libpq-dev/focal 12.2-4 amd64
aptitude
aptitude versions libpq-dev
p 12.2-4 focal 500
i 12.11-0ubuntu0.20.04.1 focal-security,focal-updates 500
ldd
Dodatkowo, jeśli trzeba przeprowadzić niewielką „reverse-engineering” i odpowiedzieć na pytanie, jaki inne biblioteki zostały wykorzystane podczas kompilacji tej jednej biblioteki można posłużyć się poleceniem ldd:
ldd ./_psycopg.cpython-38-x86_64-linux-gnu.so
linux-vdso.so.1 (0x00007fff09ce7000)
libpq.so.5 => /lib/x86_64-linux-gnu/libpq.so.5 (0x00007f71f6dcc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f71f6da9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f71f6bb7000)
libssl.so.1.1 => /lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f71f6b24000)
[...]
pg_config
A jeśli mowa jest konkretnie o bibliotece dla PostgreSQL, to można też wykorzystać polecenie pgconfig –version
ls /usr/bin/pg_con*
/usr/bin/pg_config /usr/bin/pg_config.libpq-dev /usr/bin/pg_conftool
/usr/bin/pg_config.libpq-dev --version
PostgreSQL 12.11 (Ubuntu 12.11-0ubuntu0.20.04.1)
Python
I na zakończenie jeszcze metoda z Pythona. Jeśli korzystasz z modułu psycopg2, to odwołując się do
psycopg2.__libpq_version__
możesz wyświetlić numer wersji libpq, z jaką został skompilowany moduł psycopg2
The psycopg2 module content — Psycopg 2.9.3 documentation
2022-05-24
Bezpieczeństwo swoją drogą a admini swoją. Nie no, bez przesady. Jeśli masz serwer ćwiczeniowy, na którym chcesz zminimalizować podawanie hasła, to przełączenie sudo w tryb bez hasła jest całkiem sensowne.
Żeby wyłączyć konieczność podawania hasła w sudo uruchom (ostatni raz podając hasło) polecenie
sudo visudo
visudo to specjalny edytor do pliku sudoers. Plik jest ważny i byłoby szkoda, gdyby się uszkodził poprzez modyfikację przez kilku użytkowników na raz. Następnie na samym końcu dodaj coś w tym stylu:
myuser ALL=(ALL) NOPASSWD:ALL
To istotne, żeby ta linijka była na końcu, bo w dokumentacji pliku sudoers (sudoers(5): default sudo security policy module – Linux man page (die.net)) czytamy:
When multiple entries match for a user, they are applied in order. Where there are multiple matches, the last match is used (which is not necessarily the most specific match).
I gotowe. Od tej pory użytkownik myuser nie będzie pytany o hasło podczas pracy z sudo!
2022-05-19
Modyfikacja ustawień maszyny wirtualnej w chmurze to czysta przyjemność. Wszystko dzieje się samo, wystarczy tylko wyklikać nowe zasoby i już. Czy jednak aby na pewno? Załóżmy, że na AWS chcę dodać do instancji EC2 z Linuxem dodatkowy zasób dyskowy.
Zaczyna się przyjemnie od dodania nowego wolumenu EBS w EC2 >> Volumes >> Create Volume
Najważniejsze parametry, to oprócz typu i rozmiaru, również region, w kórym ten dysk jest utworzony. Dysk da się podłączyć tylko do maszyn, które są w tym samym regionie.
Po utworzeniu wolumenu można wejść do jego właściwości i z menu Action wybrać Attach:
W formularzu podajemy, dla jakiej instancji ten wolumen ma być dostępny. Można też skonfigurować nazwę urządzenia dyskowego:
Tutaj utworzony wolumen zostanie podłączony do Linuxa poprzez urządzenie /dev/sdg
Teraz pora na zabawę po stronie systemu operacyjnego. Najpierw wylistujmy wolumeny. Jak widać w wyniku tej komendy, nowe urządzenie xvdg pojawiło się na liście:
ubuntu:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 25.1M 1 loop /snap/amazon-ssm-agent/5656
loop1 7:1 0 55.5M 1 loop /snap/core18/2409
loop2 7:2 0 61.9M 1 loop /snap/core20/1518
loop3 7:3 0 79.9M 1 loop /snap/lxd/22923
loop4 7:4 0 47M 1 loop /snap/snapd/16010
xvda 202:0 0 8G 0 disk
├─xvda1 202:1 0 7.9G 0 part /
├─xvda14 202:14 0 4M 0 part
└─xvda15 202:15 0 106M 0 part /boot/efi
xvdf 202:80 0 1G 0 disk /newvolume
xvdg 202:96 0 1G 0 disk
Operacje na dyskach niestety należą do tych bardziej krytycznych, bo łatwo zamazać istniejące dane przez przypadek. Dlatego warto zawsze sprawdzać, czy dysk jest rzeczywiście pusty. Można się w tym celu posłużyć poleceniem file. W zaprezentowanym poniżej wyniku widać, że dysk xvdg jest pusty, ale dysk xvdf ma już istniejący file system:
ubuntu:~$ sudo file -s /dev/xvdg
/dev/xvdg: data
ubuntu:~$ sudo file -s /dev/xvdf
/dev/xvdf: Linux rev 1.0 ext4 filesystem data,
UUID=1865b1e2-0734-47f6-8ed9-9492bab0348a (needs journal recovery)
(extents) (64bit) (large files) (huge files)
Mając pewność, że to TEN dysk, można na nim utworzyć system plików:
ubuntu:~$ sudo mkfs -t ext4 /dev/xvdg
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 12e55613-5f1a-4ca1-9316-e8541fd6a48e
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
Teraz pozostaje zmontować nowy dysk. Zaczynamy od utworzenia nowego katalogu, a następnie ręcznie montujemy system plików z nowego wolumenu. Poleceniem df można sprawdzić, że montowanie powiodło się:
ubuntu:~$ sudo mkdir /vol_g
ubuntu:~$ sudo mount /dev/xvdg /vol_g/
ubuntu:~$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 7.6G 2.2G 5.5G 29% /
tmpfs 484M 0 484M 0% /dev/shm
tmpfs 194M 880K 193M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/xvdf 974M 24K 907M 1% /newvolume
/dev/xvda15 105M 5.3M 100M 5% /boot/efi
tmpfs 97M 4.0K 97M 1% /run/user/1000
/dev/xvdg 974M 24K 907M 1% /vol_g
Jeśli system plików miałby się montować każdorazowo przy uruchomieniu Linuxa pozostanie jeszcze modyfikacja pliku /etc/fstab. Należy w nim dodać linijkę podobną do ostatniej poniżej:
LABEL=cloudimg-rootfs / ext4 discard,errors=remount-ro 0 1
LABEL=UEFI /boot/efi vfat umask=0077 0 1
/dev/xvdf /newvolume ext4 defaults,nofail 0 0
/dev/xvdg /vol_g ext4 defaults,nofail 0 0
Żeby przetestować tą konfigurację można teraz odmontować system plików i zmontować go ponownie poleceniem mount -a
ubuntu:~$ sudo umount /vol_g
ubuntu:~$ sudo mount -a
Ponowne uruchomienie df pozwoli sprawdzić, że system plików jest dostępny:
ubuntu:~$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 7.6G 2.2G 5.5G 29% /
tmpfs 484M 0 484M 0% /dev/shm
tmpfs 194M 880K 193M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/xvdf 974M 24K 907M 1% /newvolume
/dev/xvda15 105M 5.3M 100M 5% /boot/efi
tmpfs 97M 4.0K 97M 1% /run/user/1000
/dev/xvdg 974M 24K 907M 1% /vol_g