piątek, 6 listopada 2009

Secure FTP - bezpieczne FTP w praktyce

Nie mam zamiaru opowiadać tu o słabościach protokołu FTP i problemach związanych z konfiguracją takowego serwera. Lepiej pójść na skróty i skorzystać z gotowego, lepszego i prostszego rozwiązania (KISS) jakim jest SFTP. Mając zainstalowany serwer SSH (prawie na pewno będzie to openSSH) dostajemy taką możliwość gratis.

Najprostszym a zarazem najszybszym sposobem jest stworzenie konta i ustawienie domyślnego shella na binarkę serwera sftp - najczęściej jest to sftp-server (w debianie - /usr/lib/sftp-server, w Gentoo - /usr/lib/misc/sftp-server, w innych - poszukajcie sobie sami). Zakładamy konto:

useradd -m -s /usr/lib/misc/sftp-server username


Pozostaje jeszcze dodać sftp-server do listy dozwolonych powłok (shell) zgłoszeniowych (debilne tłumaczenie - login shells), np. tak:

echo "/usr/lib/misc/sftp-server" >> /etc/shells


Szybko i prosto zdefiniowaliśmy serwer SFTP. Jedyne co można zarzucić temu rozwiązaniu to możliwość poruszania się użytkownika po całym filesystemie - w miarę oczywiście posiadanych uprawnień - a tego nie zawsze chcemy.

Drugim sposobem, który jest może trudniejszy w konfguracji jest udostępnienie jedynie dostępu do serwera sftp z możliwością chrootowania katalogu użytkownika (chroot).
Zmieniamy w /etc/ssh/sshd_config

Subsystem sftp internal-sftp

# These lines must appear at the *end* of sshd_config
Match User username
ChrootDirectory /home/userhome
ForceCommand internal-sftp
X11Forwarding no
AllowTcpForwarding no


Restartujemy sshd (/etc/init.d/sshd restart) i już.
Waryo pamiętać o ustawieniu shella użytkownika na /sbin/nologin

Bardzo ważne jest ustawienie właściciela i grupy na katalogu do którego będzie ograniczone środowisko robocze użytkownika na root oraz ustawienie odpowiednich uprawnień aby umożliwić użytkownikowi zapis w tym katalogu.

ps. Zamiast Match User można użyć np. Match Group - polecam poczytanie manuala sshd.

Oracle na Centosie

Zainstalowałem sobie testowego Oracle'a na wirtualnej maszynie. Przy instalacji patch'a wywalił mi komunikat:

[root@centosik Disk1]# ./runInstaller -silent -responseFile response/patchset.rsp
Starting Oracle Universal Installer...

Checking installer requirements...

Checking operating system version: must be redhat-3, SuSE-9, SuSE-10, redhat-4, redhat-5, UnitedLinux-1.0, asianux-1, asianux-2 or asianux-3
Failed <<<<

Exiting Oracle Universal Installer, log for this session can be found at /home/oracle/oraInventory/logs/installActions2009-11-01_12-56-26PM.log


Jak się można domyślić "enterprajsowe" sprawdzenie dystrybucji to naprawdę skomplikowane zadanie.
Jak uruchomić patcha mimo wszystko? A na przykład tak:

echo "Red Hat Linux release 5" > /etc/redhat-release

i już działa - dystrybucja jest w porządku - "enterprajs" rządzi

ps. wszystko jak się wydaje zależy od wersji oracle. Swego czasu musiałem mieć w pliku redhat-release wpis np. redhat-4

czwartek, 5 listopada 2009

Ruby - zabawy z gem chronic

Ostatnio popełniłem skrypt do generowania statystyk z backupów wykonanych w określonych przedziałach czasowych. Uznałem, że bardzo wygodnie było by udostępnić elastyczny mechanizm umożliwiający podanie okresu na podstawie którego ma byc wygenerowana statystyka.

Tu z pomocą przychodzi gem w Ruby co się zowie 'chronic'. Najpierw zainstalujmy gema (niestety nie ma go w portage'u - przynajmniej głownym repo):

gem install chronic


I już mamy gema.
Pobawmy się tym trochę w irb (interaktywny interpreter Ruby - czy jakkolwiek to nazwać)
ja@komp ~ $ irb
irb(main):001:0> require 'chronic'
=> true
irb(main):002:0> Chronic.parse("yesterday")
=> Wed Nov 04 12:00:00 +0100 2009
irb(main):003:0> Chronic.parse("yesterday").class
=> Time
irb(main):004:0>


Jak widać chronic zwraca obiekt klasy Time - klasa wbudowana w Ruby (standard library). Umożliwia nam to proste operowanie w kodzie np. do generowania zapytań SQL (klauzula where time ...)

Oczywiście to dopiero początek:

irb(main):005:0> Chronic.parse("last friday")
=> Fri Oct 30 12:00:00 +0100 2009
irb(main):006:0> Chronic.parse("last friday at 5pm")
=> Fri Oct 30 17:00:00 +0100 2009
irb(main):007:0> Chronic.parse("last month")
=> Fri Oct 16 12:30:00 +0200 2009
irb(main):008:0> Chronic.parse("last wednesday")
=> Wed Nov 04 12:00:00 +0100 2009


To zaledwie parę przykładów - tak żeby pokazać co potrafi sparsować chronic.
Ważnym parametrem przy parsowaniu jest kontekst czasu - w skrócie czy chronic ma szukać w pasującej do opisu daty przeszłości czy w przyszłości:

irb(main):010:0> Chronic.parse("wednesday", :context => :past)
=> Wed Nov 04 12:00:00 +0100 2009
irb(main):011:0> Chronic.parse("wednesday", :context => :future)
=> Wed Nov 11 12:00:00 +0100 2009
irb(main):012:0> Chronic.parse("wednesday")
=> Wed Nov 11 12:00:00 +0100 2009


Jak widać domyślnym kontekstem jest :future.

Opcja :now umożliwia zdefiniowanie daty, która ma być przez parser traktowana jako data aktualna (odnośnik czasowy w stosunku do którego ma być wykonane obliczenie). Domyślnie jest to czas bieżący:

irb(main):024:0> Chronic.parse("wednesday 4:00", :now => Time.local(2005, 1, 1))
=> Wed Jan 05 16:00:00 +0100 2005


Opcja :ambiguous_time_range umożliwia określenie przedziału czasowego, w którym będzie poszukiwana punkt w czasie - zobaczmy to na przykładzie:

irb(main):024:0> Chronic.parse("wednesday 4:00", :now => Time.local(2005, 1, 1))
=> Wed Jan 05 16:00:00 +0100 2005
irb(main):020:0> Chronic.parse("wednesday 6:00", :ambiguous_time_range => 5)
=> Wed Nov 11 06:00:00 +0100 2009
irb(main):021:0> Chronic.parse("wednesday 4:00", :ambiguous_time_range => 5)
=> Wed Nov 11 16:00:00 +0100 2009


Określiłem przeszukiwany przedział czasowy na 5am-5pm - jak widać zwrócone czasy zawierają się w zdefiniowanym przeze mnie przedziale.

Pozostaje jeszcze opcja :guess - to już pozostawiam czytelnikowi

Przydatne linki:
Chronic gem

Na nowym portalu:
Gemcutter gems - chronic

Jak utworzyć nowy dysk dla vmware

Zabrakło mi miejsca na dysku wirtualnej maszyny wmware.
Ponieważ nie mam na stacji pełnej wersji VmWare a jedynie vmplayera - nie mogłem skorzystać z interfejsu graficznego do prostej operacji jaką jest dodanie nowego dysku.
Trochę googlowania i jest rozwiązanie (dla tych co mają zainstalowane qemu).

Nowy, czysty dysk można utworzyć poleceniem:

qemu-img create -f vmdk disk2.vmdk 15G Formating 'disk2.vmdk', fmt=vmdk, size=15728640 kB


Później wystarczy jedynie dodanie tego dysku do konfiguracji maszyny wirtualnej. W tym celu musimy wyedytować plik o rozszerzeniu .vmx. Jest to plik tekstowy. W zależności od typu wygenerowanego dysku tworzymy odpowiedni wpis. W moim przypadku był to dysk IDE więc dodałem dwie linijki:

ide1:0.present = "TRUE"
ide1:0.fileName = "disk2.vmdk"

piątek, 28 sierpnia 2009

Polecenie watch - jak go używać?

Polecenie watch okazuje się często bardzo przydatnym narzędziem w codziennej praktyce administratorskiej. Pozwala nam ono wykonywać cyklicznie komendę podaną jako parametr w wywołaniu watch wyświetlając jej wynik za każdym razem na nowym ekranie:

watch [opcje] polecenie

Pozwala to w dość skuteczny sposób śledzić zmiany zachodzące pomiędzy kolejnymi wykonaniami polecenia.

Przejdźmy do praktyki. Prześledźmy zmiany pamięci dostępnej w systemie:

# watch -n 1 free


Co 1 sekundę wykonujemy polecenie free (wyświetla statystyki pamięci dostępnej w systemie - o tym innym razem).
Polecenie watch pozwala nam na więcej - możemy śledzić zmiany zachodzące w wyniku wykonania między dwoma kolejnymi wywołaniami (opcja -d):

# watch -n 1 -d free


Możemy też użyć wartości =cumulative przy opcji -d - zaznaczone będą wszystkie zmiany jakie zachodzą między wywołaniami polecenia - zmiany te będą kumulowane - nie zostaną skasowane jak w wypadku użycia samej opcji -d

# watch -n 2 free -d=cumulative free


Inne przykłady zastosowania komendy watch:

- śledzenie liczby przerwań (o przerwaniach innym razem)
# watch -n1 -d 'cat /proc/interrupts'


- śledzenie procesów ZOMBIE w systemie - no tak nie całkiem do końca ale powinno zadziałać (o procesach innym razem)

# watch -n2 "ps auxw | grep 'defunct' | grep -v 'grep' | grep -v 'watch'"


grep -v odfiltrowuje linie zawierające tekst pasujący do wzorca - stosuje się to często przy wyszukiwaniu konkretnego procesu w systemie gdy chcemy odfiltrować proces grep w zwróconym wyniku:

# ps ax|grep cron|grep -v grep

Zadanie - Jak inaczej można odfiltrować grep z listy procesów?

- śledzenie nawiązanych połączeń:

# watch -n 1 -d "netstat -tpanl | grep ESTABLISHED"


Zastosowań znajdzie się pewnie mnóstwo - ja często używam watch przy poleceniu dd w celu sprawdzenia ile danych zostało skopiowanych za jego pomocą. Polecenie dd wyświetla aktualny stan kopiowania tylko w momencie gdy proces dd otrzyma sygnał SIGUSR1 (polecam man dd):

# watch -n 2 'kill -SIGUSR1 $pid


$pid określa numer procesu dd w systemie (trzeba go wcześniej zidentyfikować).

Debian - Bash auto uzupełnianie - problemy

Jeżeli jako zwykły użytkownik przy używaniu tabulatora w celu autouzupełnienia tekstu (np. nazwy katalogu) pojawia się nam taka lub podobna linijka:

cd /ho-sh: <( compgen -d -- '/ho' ): No such file or directory


(w tym wypadku chciałem przejść do katalogu /home bez wpisywania całej nazwy a jedynie poprzez wpisanie pierwszej litery 'h' a później naciśnięcie klawisza TAB)

to problemem jest używany przez nasz shell - używamy shella innego niż Bash. Najprostszym rozwiązaniem jest zmiana w pliku /etc/passwd shella na bash (ambitnym pozostawiam analizę narzędzia compgen).

Zobaczmy to a przykładzie. Wyszukam informacje o użytkowniku w pliku passwd:

# grep user1 /etc/passwd
user1:x:1001:1001:Ordinary user:/home/user1:/bin/sh


Każda linijka w tym pliku definuje jednego użytkownika systemowego. Konkretne informacje o użytkowniku oddzielone są dwukropkiem - i oznaczają kolejno:
- nazwę użytkownika
- skrót hasła lub x jeśli skrót jest przechowywany w bezpiecznym pliku - /etc/shadow
- numeryczny identyfikator użytkownika (bodajże typu int) - uid
- numeryczny identyfikator grupy głównej (domyślnej - też typu int) użytkownika - gid
- katalog domowy użytkownika
- opis użytkownika - pełna nazwa - ciąg pozwalający odszyfrować po co i przez kogo jest używany dany login
- domyślny shell użytkownika

Jak widać user1 używa shella sh - żeby wyeliminować opisany błąd należy edytorem tekstowym z poziomu administratora zmienić wpis dotyczący shella z /bin/sh na /bin/bash i już.

A co jeśli nie mamy uprawnień roota?
Można użyć polecenia chsh będąc zalogowanym na swoim koncie:

#chsh -s /bin/bash


Możemy używać tego polecenia również z poziomu administratora jeśli nie chcemy edytować pliku ręcznie - polecenie jako argument może przyjąc login użytkownika, na którym chcemy dokonać zmiany (polecam man chsh).

Jak sprawdzić aktywny shell?
Za pomocą zmiennej shella $0
# echo $0
-bash


Pliki konfiguracyjne, którym warto się przyjrzeć:
/etc/shadow
/etc/login.defs
/etc/shells

Jako zadanie domowe pozostawiam pytania:
Jak działa chsh?
Dlaczego skróty haseł zaleca się trzymać w osobnym pliku /etc/shadow?
Do czego służy polecenie getent?

czwartek, 20 sierpnia 2009

svn: Can't convert string from 'UTF-8' to native encoding:

Ostatnio mi się przydarzył taki błąd. Występuje on gdy klient dostanie z repozytorium plik z nazwą zawierający znak w UTF-8, którego nie jest w stanie zaprezentować używając lokalnego kodowania znaków. W takim wypadku należy odpowiednio zmienić używane kodowanie znaków:

$ export LC_CTYPE=pl_PL.UTF-8
$ locale
LANG=
LC_CTYPE=pl_PL.UTF-8
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=


W moim przypadku zadziałało. Warto to ustawić na stałe. W Gentoo mamy do tego katalog /etc/env.d.
Jako lekturę polecam przewodnik lokalizacji Gentoo