Roundcube przez HTTPS czyli nginx i self-signed certificate

Powinienem to zrobić dawno temu, ale dopiero teraz zabrałem się za zabezpieczenie SSL-em mojego webmaila opartego na Roundcube. Ponieważ poza mną nikt z niego nie korzysta, a sam sobie zazwyczaj ufam, to zdecydowałem się nie korzystać z żadnego centrum certyfikacji i wygenerować certyfikat własnoręcznie.

W sieci nie brakuje instrukcji generowania certyfikatów, ja staram się robić wszystko po debianowemu, więc kierowałem się opisem z debianowej wiki. Dlatego certyfikat wylądował w katalogu /etc/ssl/localcerts, który musiałem stworzyć:

mkdir -p /etc/ssl/localcerts

Polecenie generowania klucza i certyfikatu:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/localcerts/mail.komitywa.net.key -out /etc/ssl/localcerts/mail.komitywa.net.crt

Przed wygenerowaniem certyfikatu zostaniemy zapytani o dane certyfikowanego podmiotu:

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:PL
State or Province Name (full name) [Some-State]:Mazowieckie
Locality Name (eg, city) []:Warsaw
Organization Name (eg, company) [Internet Widgits Pty Ltd]:komitywa.net
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:mail.komitywa.net
Email Address []:moj-adres-email@komitywa.net

Na koniec warto ograniczyć dostęp do wygenerowanych plików:

chmod 600 /etc/ssl/localcerts/mail.komitywa.net.*

Teraz można już SSL do konfiguracji nginx’a. Do działającego wirtualnego hosta dodałem:

listen 443 ssl;
ssl_certificate /etc/ssl/localcerts/mail.komitywa.net.crt;
ssl_certificate_key /etc/ssl/localcerts/mail.komitywa.net.key;

Po przeładowaniu nginx’a i przetestowaniu, że połaczenie po HTTPS działa postanowiłem jeszcze dodać przekierowanie z HTTP na HTTPS:

server {
       listen 80;
       server_name mail.komitywa.net;
       return 301 https://mail.komitywa.net$request_uri;
}

Wygenerowany certyfikat jest ważny przez rok, więc w kwietniu 2016 będę musiał wygenerować nowy certyfikat.

Katalogi przed plikami w Gnome Shell

Jestem otwarty na nowe rozwiązania w dziedzinie interfejsu graficznego aplikacji, ale wyświetlanie katalogów przed plikami w managerze plików jest dla mnie aksjomatem. Tymczasem po którejś aktualizacji Debiana Nautilus zaczął pokazywać pliki wymieszane z katalogami (w kolejności alfabetycznej). Co gorsza, nie dało się tego zmienić przez wyklikanie bezpośrednio w Nautilusie. Musiałem uciec się do googlania, który podpowiedział w użycie dconf-editor i kluczu org.gnome.nautilus.preferences zaznaczenie opcji sort-directories-first.

dconf

aptitude: Błędna suma kontrolna

Kilka dni temu aptitude po aktualizacji dostępnych pakietów powiedział mi:

W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/main/source/SourcesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/contrib/source/SourcesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/non-free/source/SourcesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/main/binary-amd64/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/contrib/binary-amd64/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/non-free/binary-amd64/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/main/binary-i386/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/contrib/binary-i386/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/non-free/binary-i386/PackagesIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/contrib/i18n/Translation-enIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/main/i18n/Translation-plIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/main/i18n/Translation-enIndex: Błędna suma kontrolna
W: Nie udało się pobrać http://ftp.pl.debian.org/debian/dists/testing/non-free/i18n/Translation-enIndex: Błędna suma kontrolna
E: Nie udało się pobrać niektórych plików indeksu, zostały one zignorowane lub użyto ich starszej wersji.
E: Nie można przebudować informacji o pakietach

Poproszony o upgrade odparł zaś, że ma milion niespełnionych zależności i jeśli chcę to mogę go uruchomić z opcją --full-resolver. Na takie dictum acerbum chwilowo skapitulowałem, wszak nie muszę codziennie mieć najświeższych pakietów. Zakładałem, że coś się skopało na debianowym serwerze i zaraz to naprawią. Jednak i dzień później i w kolejne dni aptitude twardo obstawał przy swoim. Tego już było za wiele. Trzeba było pokazać, kto tu rządzi:

aptitude update -o Acquire::Pdiffs=false

Powyższa opcja wymusza pobranie pełnych list pakietów, a nie tylko diffów. Pomogło.

Edycja boot menu UEFI w Debianie

Mój służbowy laptop (HP Pavilion G6) musiał powędrować do serwisu, więc admin przełożył dysk i pamięć z mojego komputera do identycznego modelu. Na chłopski rozum wszystko powinno ruszyć bez problemu, ale niestety po takiej operacji komputer przywitał mnie komunikatem „Hard Disk – (3F0) BootDevice not found”. Oczywiście opcje UEFI były identycznie ustawione w obydwu komputerach.

Z problemem biedziłem się kilka godzin, zastanawiałem się czy to problem z szyfrowaniem dysku (LUKS), flagą boot partycji, a może identyfikatorami partycji. Problem musiał być trywialny, bo po uruchomieniu systemu z LiveCD partycje można było podmontować, a dane były na miejscu. Na wszelkie wypadek dodam, że ponowna instalacja GRUB-a nie pomogła.

Odkryłem, że jeśli wystartuję komputer z LiveCD, ale zamiast uruchamiać Linuksa wyjdę z menu GRUB-a (Escape, a potem exit) to komputer pokazuje menu UEFI, z którego mogę wybrać urządzenie i plik uruchomieniowy. Na moim dysku komputer widział plik EFI/debian/grubx64.efi, po wybraniu którego system startował normalnie.

Z pomocą kolegi trafiłem na trop programu efibootmgr, który służy do edycji menu uruchomieniowego UEFI. Po kilku próbach doszedłem do polecenia, które postawiło mój system na nogi:

efibootmgr --create --label "Debian" --loader \\EFI\\debian\\grubx64.efi

Powyższe polecenia zakłada, że partycja EFI jest na /dev/sda i jest podmontowana jako /boot/efi. Jeżeli jest inaczej należy je wskazać odpowiednio przez --disk i --part. Użycie backslashy w parametrze --loader jest istotne.

Efekt działania można sprawdzić poleceniem efibootmgr --verbose. U mnie wygląda to tak:

BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 3001,2001,2002,2003
Boot0001* Debian	HD(1,800,f3800,b865a07b-fdff-428d-9443-9fb85820b4f6)File(\EFI\debian\grubx64.efi)
Boot2001* USB Drive (UEFI)	RC
Boot2002* Internal CD/DVD ROM Drive (UEFI)	RC
Boot3001* Internal Hard Disk	RC

SSHFS – problemy i rozwiązania

Trochę wody w Wiśle upłynęło odkąd ostatnio używałem SSHFS, więc kiedy przyszło mi podmontować udział z serwera przez ten protokół nie obyło się bez problemów.

Instalacja

O ile wcześniej tego nie zrobiliśmy to SSHFS trzeba zainstalować:

aptitude install sshfs

Montowanie:

sshfs mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt

Moja nazwa użytkownika na zdalnej maszynie jest inna niż na lokalnej, więc musiałem ją podać w ścieżce.

Tu może pojawić się pierwszy problem:

failed to open /dev/fuse: Permission denied

Rozwiązanie jest proste:

usermod -aG fuse joe

Następnie trzeba się przelogować, lub, jeśli ktoś lub starą windowsową szkołę, ponownie uruchomić komputer.

Dla pewności można sprawdzić czy użytkownik trafił do grupy fuse.

groups joe
joe : joe cdrom floppy audio dip video plugdev fuse scanner netdev bluetooth

Problem z właścicielem plików

Jeśli nazwy i identyfikatory użytkowników są różne na obu maszynach to wystąpią problemy z dostępem do plików ponieważ SSHFS w lokalnym systemie pokaże takiego właściciela jak na zdalnym systemie.

-rw-r--r-- 1 1001 1001   141 sty  9 11:13 AppCache.php
-rw-r--r-- 1 1001 1001  2395 sty  9 11:13 AppKernel.php
-rw-r--r-- 1 1001 1001   267 sty  9 11:13 autoload.php
-rwxr-xr-x 1 1001 1001   865 sty  9 11:13 console

Można temu zaradzić używając opcji idmap=user

sshfs -o idmap=user mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt

Dzięki temu użytkownik dokonujący montowania zostanie zmapowany na użytkownika, na którego się łączymy.

-rw-r--r-- 1 joe 1001   141 sty  9 11:13 AppCache.php
-rw-r--r-- 1 joe 1001  2395 sty  9 11:13 AppKernel.php
-rw-r--r-- 1 joe 1001   267 sty  9 11:13 autoload.php
-rwxr-xr-x 1 joe 1001   865 sty  9 11:13 console

Problem z grupą plików

Jak widać na liście plików z poprzedniego akapitu, pliki mają poprawnego właściciela, ale grupa ciągle nie jest zmapowana. To może powodować problemy z dostępem, ale i na to jest remedium:

sshfs -o idmap=user -o uid=1000 -o gid=1000 mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt

Po takim zabiegu również grupy są poprawne:

-rw-r--r-- 1 joe joe   141 sty  9 11:13 AppCache.php
-rw-r--r-- 1 joe joe  2395 sty  9 11:13 AppKernel.php
-rw-r--r-- 1 joe joe   267 sty  9 11:13 autoload.php
-rwxr-xr-x 1 joe joe   865 sty  9 11:13 console

SSHFS w /etc/fstab

Żeby nie wpisywać wszystkiego z palca z każdym razem można definicję zasobu wrzucić do /etc/fstab. W takim wypadku trzeba podać ścieżkę do klucza, który ma zostać użyty do autoryzacji.

sshfs#mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt fuse defaults,IdentityFile=/home/joe/.ssh/id_rsa,uid=1000,gid=1000 0 0

Jeśli zasób możne być niedostępny podczas uruchamiania komputera to nie warto montować go automatycznie, lepiej umożliwić montowanie go przez użytkowników na żądanie.

sshfs#mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt fuse defaults,noauto,user,uid=1000,gid=1000 0 0

bash: brak dostępu

Ostatni problem, na który się nartknąłem był związany z uruchamianiem skryptów:

app/console
bash: app/console: Brak dostępu

Dzieje się tak ponieważ parametr user w opcjach montowania implikuje noexec, co można łatwo sprawdzić poleceniem

mount -l

Oczywiście zamiast app/console można posługiwać się php app/console, ale jeśli chcemy korzystać z dobrodziejstw autouzupełniania poleceń albo po prostu oszczędzać klawiaturę to należy dodać parametr exec:

sshfs#mdurys@10.0.0.2:/home/mdurys/projekt /home/joe/Projekty/projekt fuse defaults,noauto,user,exec,uid=1000,gid=1000 0 0

Lektura dodatkowa

Dlaczego drukowanie dwustronne przestało działać?

Drukowanie dwustronne to obok majtek z gumką jeden z najprzydatniejszych wynalazków naszej ery. Zrozumiecie zatem moje zdumienie i zaniepokojenie, kiedy to po świeżej instalacji systemu stosowna opcja zniknęła z okienka ustawień wydruku.

Przyczyna problemu tkwi w wybranym sterowniku drukarki. Jak widzicie na obrazku, do mojego Lexmarka E450DN Debian proponuje trzy sterowniki. W tej chwili nie pamiętam czemu wybrałem lj5gray, jednak ten sterownik nie pozwala korzystać z dobrodziejstw druku dwustronnego. Po zmianie sterownika na Postscript znowu mogę drukować dwustronnie.

Wybór sterownika drukarki

Serwer na Debianie: nginx, PHP i bazy danych

Przedstawiam mój przepis szybkie postawienie serwera, na którym działa nginx, PHP i bazy danych. Ja z powodzeniem używam takiej konfiguracji na maszynie deweloperskiej, ale można jej też użyć jako punktu wyjścia do konfiguracji serwera produkcyjnego, jednak w tym wypadku radzę uważnie przeczytać zastrzeżenia na końcu.

W przepisie używam Debiana Squeeze, ale po dodaniu sudo przed większością poleceń będzie go można zastosować do Ubuntu. ;-)

Opisywana konfiguracja spełnia następujące założenia:

  • Na serwerze mają działać nginx, PHP, MySQL, PostgreSQL, MongoDB i memcached.
  • Oprogramowanie powinno być w możliwie aktualnych stabilnych wersjach.
  • Skrypty PHP mają działać z prawami użytkownika.
  • Serwer powinien mieć możliwość uruchamiania skryptów PHP zabezpieczonych ionCube’em.

Czytaj dalej „Serwer na Debianie: nginx, PHP i bazy danych”

su: Uwierzytelnienie nie powiodło się

Na jednym VPS-ie z Debianem 6 nie mogłem przejść na konto roota korzystając z polecenia su. Próba jego wykonania kończyła się tak:

joe@dejiko:~$ su -
Hasło:
su: Uwierzytelnienie nie powiodło się

W /var/log/auth.log pojawiały się takie wpisy:

Feb 21 10:48:30 dejiko unix_chkpwd[4123]: check pass; user unknown
Feb 21 10:48:30 dejiko unix_chkpwd[4123]: password check failed for user (root)
Feb 21 10:48:30 dejiko su[4122]: pam_unix(su:auth): authentication failure; logname=joe uid=1000 euid=1000 tty=/dev/pts/1 ruser=joe rhost=  user=root

Początkowo myślałem, że problem tkwi w tym, że użytkownik joe nie należy do grupy sudoers, ale ten trop okazał się mylny. W wyniku śledztwa okazało się, że winne są uprawnienia pliku /bin/su. Na działającym systemie wyglądały one tak:

-rwsr-xr-x 1 root root 34024 2011-02-15  /bin/su

zaś na problematycznej maszynie tak:

-rwxr-xr-x 1 root root 34024 2011-02-15  /bin/su

Innymi słowy brakowało bitu „set UID”, więc problem rozwiązałem poleceniem:

chmod u+s /bin/su

Na inkryminowanym systemie ten sam problem dotyczył polecenia passwd, objawy były następujące:

joe@dejiko:~$ passwd
Zmienianie hasła dla joe.
(obecne) hasło UNIX:
passwd: Błąd podczas modyfikowania tokenu uwierzytelniania
passwd: password unchanged

Tu również pomógł chmod.

/var/lock i /var/run w RAM-ie na Debianie

Na co dzień mam do czynienia z Debianem, Gentoo i Ubuntu. W tych dwóch ostatnich systemach katalogi /var/lock i /var/run zamontowane są na ramdysku. Ma to sporo sensu ponieważ do tych katalogów dość często zapisywane są małe pliczki, a dane są ulotne (po resecie i tak tracą znaczenie). Dzięki przeniesieniu tych danych do RAM-u oszczędzamy mechanikę dysku, miejsce, a i pewnie trochę przyspieszamy działanie systemu.

Debian prezentuje bardziej konserwatywne podejście, wspomniane katalogi są tworzone w głównym katalogu. Na szczęście przeniesienie ich do RAM-u sprowadza się do zmiany dwóch linijek w pliku /etc/default/rcS:

TMPTIME=0
SULOGIN=no
DELAYLOGIN=no
UTC=yes
VERBOSE=no
FSCKFIX=no
RAMRUN=yes
RAMLOCK=yes

Zmienione linijki pogrubiłem. Po wykonaniu tych zmian trzeba wykonać reset i voila:

System plików         rozm. użyte dost. %uż. zamont. na
/dev/mapper/gt500-root
                      7,4G  1,6G  5,5G  23% /
tmpfs                 999M     0  999M   0% /lib/init/rw
varrun                999M  420K  998M   1% /var/run
varlock               999M     0  999M   0% /var/lock
udev                  994M  160K  993M   1% /dev
tmpfs                 999M     0  999M   0% /dev/shm
/dev/sda1              89M   16M   69M  19% /boot
/dev/mapper/gt500-home
                      104G   17G   88G  16% /home

Jak wyczytałem w dokumentacji Debiana, niektóre starsze programy źle działają jeśli /var/lock i /var/run nie są obecne na dysku. Na moim serwerku mam sporo softu (m.in. Apache, MySQL, PostgreSQL, Exim, ProFTPd, memcached) i nie zauważyłem żadnych problemów. Dlatego zgaduję, że w większości instalacji Debiana, zarówno desktopowych jak i serwerowych, warto pokusić się o wykonanie omawianej zmiany.

Powiązanie nazwy interfejsu sieciowego z adresem MAC

Numerowanie interfejsów sieciowych w Linuksie jest dość tajemniczym procesem, przynajmniej dla mnie. Dość powiedzieć, że przeważnie system nadaje im inne numerki niż bym sobie życzył. Co więcej, jeśli mamy już w systemie interfejs eth0, nie ma gwarancji, że po dołożeniu drugiej karty sieciowej zostanie ona wykryta jako eth1. Na szczęście obecnie można w łatwy sposób przekonać system do swoich racji. W Debianie (i Ubuntu) należy skierować się ku plikowi /etc/udev/rules.d/70-persistent-net.rules. Właśnie w tym pliku system zapisuje powiązanie pomiędzy adresem MAC karty sieciowej a nazwą interfejsu. Przykładowa zawartość pliku:

# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="70:71:bc:b1:93:94", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# PCI device 0x10ec:0x8139 (8139too)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:02:44:70:1f:3e", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

W tym konkretnym wypadku chciałem zamienić interfejsy kolejnością, tak aby eth0 był połączony z modemem, a gigabitowy eth1 z siecią lokalną. Żeby to osiągnąć wystarczyło zamienić cyferki w parametrze NAME:

# PCI device 0x10ec:0x8168 (r8169)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="70:71:bc:b1:93:94", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

# PCI device 0x10ec:0x8139 (8139too)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:02:44:70:1f:3e", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Korzystając z tego pliku można pójść dalej i nadać interfejsom bardziej czytelne nazwy np. eth-wan, eth-lan czy eth-intel.