Pierwsze kroki po zainstalowaniu Slackware’a

Posted by Michał ‘mina86’ Nazarewicz on 12th of February 2008

W niniejszym artykule opiszę czynności, jakie zazwyczaj wykonuję zaraz po zainstalowaniu Slackware’a. Nie są to rzeczy, które doprowadzają do idealnego zabezpieczenia, olbrzymiego wzrostu wydajności, czu użyteczności systemu, ale raczej kroki wyważone pomiędzy tymi aspektami. Oczywiście, jest to opis tego co ja robję, więc niekoniecznie wszystko, co zostało tutaj opisane, będzie Ci odpowiadać.

UPDATE 18/04/08: Dodane TMOUT.

Dodawanie użytkownika

Z całą pewnością pierwszą czynnością jaką należy wykonać jest stworzenie nowego użytkownika. Aby to zrobić wystarczy uruchomić polecenie adduser i odpowiadać na kolejne pytania. Najistotniejszym jest nazwa użytkownika oraz pytanie o dodatkowe grupy. To drugie jest zadawane zaraz po pytaniu o grupę podstawową i należy na nie odpowiedzieć root - będzie to bardzo przydatne przy ograniczaniu dostępu do różnych poleceń (nie dodawaj użytkownika do grupy wheel, bo dalsze modyfikacje plików konfiguracyjnych uniemożliwią Ci zalogowanie się do komputera). Na pozostałe pytania wystarczy odpowiedzieć wciskając enter.

Ustawienia logowania

W drugim kroku należy wyedytować plik /etc/login.access, aby miał następującą zawartość:

-:wheel:ALL
-:ALL EXCEPT mina86:ALL

Pierwsza linijka spowoduje, że użytkownicy z grupy wheel nie będą mogli się logować do komputera (do grupy tej należy między innymi root). Druga linijka zabrania logować się wszystkim oprócz użytkownika o podanym loginie. Jeżeli więcej osób ma mieć możliwość logowania się (nie dotyczy to dostępu zdalnego np. przez SSH) to można stworzyć grupę (np. ttylogin), a w omawianym pliku drugą z podanych linijek zamienić na:

-:ALL EXCEPT ttylogin:ALL

W ten sposób, aby zalogować się jako root trzeba najpierw zalogować się jako zwykły użytkownik, a następnie użyć polecenia su, o którym niżej.

Dalej, w pliku /etc/login.defs dokonujemy następujących zmian:

MAIL_CHECK_ENABUstawiamy na no, chyba że rzeczywiście jest to potrzebne. Jeżeli masz wątpliwości to pewnie nie jest to potrzebne.
ISSUE_FILEUstawiamy na /etc/issue. Później jeszcze dodamy w odpowiednie miejsce kod definiujący ten plik.
SU_WHEEL_ONLYUstawiamy na yes. W ten sposób z su będą mogli korzystać jedynie użytkownicy należący do grupy o numerze zero, tj. do grupy root. Należy zauważyć, że w niektórych systemach opcja ta ma nieco inne znaczenie, a mianowicie, zgodnie z nazwą, zezwala na logowanie jedynie użytkownikom z grupy wheel co trochę utrudnia sprawę, gdyż nie da się wówczas w łatwy sposób zablokować możliwości logowania dla użytkowników z tej grupy (tak jak to zrobiliśmy edytując plik login.access). Nie ma się jednak co przejmować - na takich systemach nie należy po prostu zamieniać tej wartości - zabezpieczeniem su jeszcze się zajmiemy.
LOGIN_STRINGKomentarz mówi, że ta opcja nie działa poprawnie, ale nie spotkałem się z żadnymi problemami toteż wystarczy odkomentować linię by opcja LOGIN_STRING przyjęła wartość "%s's Password: ".
GETPASS_ASTERISKSBardzo zabawna opcja, osobiście ustawiam ją na 10 dzięki czemu, w trakcie wpisywania hasła, wpisanie pojedynczej literki powoduje wyświetlenie od jednej do 10 gwiazdek - dobry sposób na zmylenie kogoś, kto spogląda zza ramienia na to co wpisujemy. Śmiesznie też wyglądają ludzie, którzy myślą, że w istocie mam kilkudziesięcio znakowe hasło i wpisałem je w dwie, trzy sekundy.

Zabezpieczanie SSH

Logowanie z konsoli jest już zrobione to teraz należy zabezpieczyć SSH. Przede wszystkim, jeżeli nie używamy sshd to warto ustawić, aby nie włączał się on automatycznie przy starcie (generalnie wszelkie nieużywane lub rzadko używane daemony nie powinny być uruchamiane przy starcie). Aby tego dokonać wystarczy uruchomić polecenie:

chmod 600 /etc/rc.d/rc.sshd

Przy takich ustawieniach, aby wystartować sshd należy wykonać polecenie:

sh /etc/rc.d/rc.sshd start

Po drugie trzeba jeszcze wyedytować plik /etc/ssh/sshd_config ustawiając w nim następujące opcje:

PermitRootLogin no
AllowUsers mina86
DenyUsers root
DenyGroups wheel

Spowoduje to, że jedynie użytkownik mina86 będzie mógł logować się zdalnie przy pomocy ssh. Jeżeli więcej użytkowników ma mieć dostęp zdalny to wystarczy dopisać loginy do opcji AllowUsers oddzielając poszczególne nazwy spacjami. Jeżeli użytkowników miałoby być sporo to lepiej stworzyć nową grupę, np. sshlogin, do pliku sshd_config dodać opcję AllowGroups sshlogin i dodawać użytkowników do tej grupy.

Zabezpieczanie su

Teraz jeszcze pozostaje zabezpieczyć trochę polecenie su. Po pierwsze, do pliku /etc/suauth (w razie potrzeby należy ten plik utworzyć) dodajemy następującą linijkę:

ALL:ALL EXCEPT GROUP root:DENY

Dzięki której, jedynie użytkownicy należący do grupy root będą mogli korzystać z su. W chwili obecnej, do grupy tej powinien należeć root oraz użytkownik stworzony na początku tego artykułu.

Na wszelki wypadek warto jeszcze wykonać następujące dwa polecenia:

chown root:root /bin/su
chmod 4750 /bin/su

Dzięki którym, blokowanie użytkowników nienależących do grupy root będzie się odbywało również na poziomie systemu plików i jądra.

Skrypty startowe

Tutaj będzie trochę zmian. Zarówno zwiększających bezpieczeństwo jak i przyśpieszających start systemu.

rc.M

Zacznijmy od pliku /etc/rc.d/rc.M. Po pierwsze należy w nim zakomentować linijki uruchamiające polecenia ldconfig oraz fc-cache. Wykonują się one bardzo długo i strasznie wydłużają start systemu, a w gruncie rzeczy są niepotrzebne. Należy tylko pamiętać, żeby po zainstalowaniu (lub odinstalowaniu) jakiejkolwiek biblioteki uruchomić ldconfig oraz po dodaniu/skasowaniu czcionek - fc-cache.

W celu przyśpieszenia startu systemu warto uruchomić kilka programów w tle. Ja tak zrobiłem z syslog, acpid, alsa, gpm, oraz całym fragmentem kodu począwszy od inet1, a skończywszy na inet2. W przypadku syslog wystarczy zmienić linijkę:

  . /etc/rc.d/rc.syslog start

na:

  /etc/rc.d/rc.syslog start &

Może to co prawda spowodować, że niektóre komunikaty nie zostaną zapisane w logu systemowym, ale osobiście uznałem, że nie jest to aż tak wielka strata. Analogicznie wygląda sytuacja z acpid, alsa oraz gpm.

W przypadku kodu od inet1 do inet2, wystarczy przed linijkami:

# Initialize the networking hardware.  If your network driver is a module
# and you haven’t loaded it manually, this will be deferred until after
# the hotplug system loads the module below.
if [ -x /etc/rc.d/rc.inet1 ]; then
  . /etc/rc.d/rc.inet1
fi

dodać okrągły nawias otwierający, tj.:

(

# Initialize the networking hardware.  If your network driver is a module
# and you haven’t loaded it manually, this will be deferred until after
# the hotplug system loads the module below.
if [ -x /etc/rc.d/rc.inet1 ]; then
  . /etc/rc.d/rc.inet1
fi

oraz za linijkami:

# Start networking daemons:
if [ -x /etc/rc.d/rc.inet2 ]; then
  . /etc/rc.d/rc.inet2
fi

dodać okrągły nawias zamykający z etką:

# Start networking daemons:
if [ -x /etc/rc.d/rc.inet2 ]; then
  . /etc/rc.d/rc.inet2
fi

) &

Powinno to przyśpieszyć start systemu, choć nie wiem czy użytkownicy hotplug nie napotkają jakiś problemów, oby nie.

Na koniec jeszcze, zdecydowałem się usunąć pliki /etc/rc.d/rc.font i /etc/rc.d/rc.keymap, a ich zawartość wstawić bezpośrednio do pliku /etc/rc.d/rc.M z jednoczesnym uruchomieniem w tle:

# Load a custom screen font
setfont lat2-16 &

# Load a custom keymap
if [ -x /usr/bin/loadkeys ]; then
  /usr/bin/loadkeys pl2.map &
fi

rc.S

Tutaj jedynie zmieniłem kilka uprawnień:

chmod 1733 /tmp/.ICE-unix /tmp/.X11-unix
Dodatkowo, można jeszcze zmienić uprawnienia do pliku /var/run/utmp modyfikując odpowiednią linijkę, tak aby przybrała postać: chmod 600 /var/run/utmp, ale należy wziąć pod uwagę, fakt, że zpowoduje to, iż polecenia takie jak uptime będą jako liczbę zalogowanych użytkowników podawać 0 (słownie zero).

rc.local

Nie rozwodząc się długo, do pliku /etc/rc.d/rc.local proponuję wpisać co następuje:

chown root:root /sbin/shutdown /sbin/halt /sbin/reboot /sbin/poweroff /bin/su
chmod 4750      /sbin/shutdown /sbin/halt /sbin/reboot /sbin/poweroff /bin/su

/usr/sbin/icmpinfo -vvv -s -l

cat >/etc/issue <<END
          ###                 ###
           ##                  ##
    ####   ##   ####    ####   ##  ### ###        ### ####   ### ###   ####
   ##      ##      ##  ##      ## ##    ##   ##   ##     ##   ###  ## ##  ##
|   ###    ##   #####  ##      ####      ## #### ##   #####   ##      ######
|     ##   ##  ##  ##  ##      ## ##      ###  ###   ##  ##   ##      ##
|  ####   ####  ######  ####  ###  ###    ##    ##    ######  ##       #####
+------------------------------------------ l i n u x  `uname -rm`
END
cp -f /etc/issue /etc/issue.net

/usr/sbin/hdparm -c3 -a16 -W1 -u1 /dev/hda >/dev/null

if [ -x /etc/cron.hourly/ntpsync ]; then
        /etc/cron.hourly/ntpsync &
fi

Na początku ustawiane są uprawnienia do różnych poleceń systemowych. Dzięki nim, użytkownicy z grupy root nie muszą korzystać z su, aby móc odpalić polecenia takie jak /sbin/halt. Dalej włączane jest logowanie pakietów ICMP. Następnie generowane są pliku /etc/issue oraz /etc/issue.net po czym ustawiane są różne parametry dysku - prawdopodobnie będziesz chciał je zmodyfikować. Na koniec uruchamiany jest skrypt /etc/cron.hourly/ntpsync o ile takowy istnieje.

rc.alsa

Ponieważ stosunkowo szybko przekompilowuję jądro i wkompilowuję w nim emulację OSS to nie ma potrzeby wczytywania żadnych modułów, więc w pliku /etc/rc.d/rc.alsa zmieniam definicję funkcji load_alsa_oss_modules na następującą:

load_alsa_oss_modules () {
  : Compiled in
}

rc.syslog

Tutaj można minimalnie zmienić parametry wywoływania syslogd oraz klogd:

/usr/sbin/syslogd -m 0
/usr/sbin/klogd -c 3 -x -p

Crontab

Po pierwsze, tworzymy plik /etc/cron.hourly/ntpsync o następującej treści:

#!/bin/sh
# Query time
/usr/sbin/ntpdate -u -s 0.pl.pool.ntp.org 1.pl.pool.ntp.org \
        2.pl.pool.ntp.org || exit $?

# Save the system time to the hardware clock using hwclock --systohc.
if [ -x /sbin/hwclock ]; then
  # Check for a broken motherboard RTC clock (where ioports for rtc are
  # unknown) to prevent hwclock causing a hang:
  if ! grep -q -w rtc /proc/ioports ; then
    CLOCK_OPT="--directisa"
  fi
  if grep -q "^UTC" /etc/hardwareclock 2> /dev/null ; then
    /sbin/hwclock $CLOCK_OPT --utc --systohc
  else
    /sbin/hwclock  $CLOCK_OPT --localtime --systohc
  fi
fi

Po drugie, tworzymy plik /etc/cron.daily/cleanup nadając mu prawa wykonywania o następującej treści:

#!/bin/sh
/usr/bin/find /tmp /var/tmp -atime +7 -exec rm -f -- {} + 2>/dev/null

I na koniec jeszcze warto odpalić crontab -e i pozmieniać godziny z 4. w nocy na np. północ, chyba że nasza maszyna jest zazwyczaj na chodzie o 4. w nocy. Oczywiście obu utworzonym plikom nadajemy prawa do wykonywania, np.:

chmod 700 /etc/cron.hourly/ntpsync /etc/cron.daily/cleanup

Zabezpieczanie Xów

Kilka szybkich zmian zamykających różne dziwne porty:

/usr/X11R6/bin/startx
defaultserverargs="-nolisten tcp"
/etc/X11/xdm/Xservers
:0 local /usr/X11R6/bin/X -nolisten tcp
/etc/rc.d/rc.4
exec /usr/X11R6/bin/xdm -nodaemon -udpPort 0
/etc/X11/fs/config
use-syslog = yes
no-listen = tcp

Kasowanie zbędny userów i grup

Generalnie uruchamiamy następujące polecenia:

find / -user adm -o -user games -o -user gdm -o -user lp -o -user news \
    -o -user operator -o -user pop -o -user rpc -o -user uucp \
    -o -group adm -o -group lp -o -group news -o -group pop \
    -o -group uucp -ls

for USR in adm gdm lp news operator pop rpc uucp halt shutdown sync; do
    userdel "$USR"
done

for GRP in adm news pop; do groupdel "$GRP"; done

grpck

Istotne jest, aby po uruchomieniu find sprawdzić dokładnie, czy dany użytkownik lub grupa nie jest jednak w systemie potrzebny/a. W moim przypadku okazało się, że użytkownik games i uucp oraz grupa uucp były wykorzystywane (tj. istniały pliki należące do tych użytkowników/grup) i z tego powodu tych użytkowników/grup nie usunąłem (co widać brakiem odpowiedniej pozycji w pętli for).

host.conf

Do pliku /etc/host.conf dodajemy:

nospoof on
spoofalert on
spoof warn

Prawa dostępu

chmod -R go-rwx /etc/cron.*
chmod -R go-rwx /etc/rc.d
chmod -R o-rwx /var/log

profile

Na początek pliku /etc/profile dodajemy:

# Check required variables
: ${USER:?Who are you?}
: ${LOGNAME:?Who are you?}
: ${HOME:?The homeless need help}

Partycje

Jeżeli mamy jakieś partycje vfat to warto zmienić w pliku /etc/fstab opcje z jakimi są montowane na następujące: umask=7,shortname=winnt,codepage=852,quiet,iocharset=iso8859-2 Spowoduje to, że root oraz użytkownicy z grupy root będą mogli bez przeszkód odczytywać i modyfikować pliki na partycjach vfat. Jeżeli chcemy, żeby dodatkowo wszyscy mogli odczytywać pliki z partycji Windowsa wystarczy zmienić umask=7 na umask=2. Zmiana na umask=0 spowoduje, że wszyscy będą mogli robić wszystko. By mieć większą kontrolę, można stworzyć grupę vfat, umask ustawić na 7 i jeszcze dodać opcję gid=numer, gdzie numer to identyfikator stworzonej grupy. Spowoduje to, że tylko root oraz członkowie grupy vfat będą mogli szperać po i dokonywać zmian na partycjach vfat.

Na koniec jeszcze, by być bardziej zgodnym z File Hierarchy Standard wykonuję następujące polecenia:

mv -f -- /mnt /media
mkdir -- /mnt
sed -e 's/\/mnt\//\/media\//' -i -- /etc/fstab

Co powoduje, że rzeczy takie jak CD-ROM czy dyskietki są montowane nie w katalogu /mnt, ale /media.

LILO

Zawsze lubiłem, jak system szybko się ładował i zawsze denerwowały mnie długie opóźnienia powodowane przez boot loadery. W związku z czym, w swoim LILO dokonałem następujących zmian:

Po pierwsze, dodałem lba32 i compact; po drugie, timeout ustawiłem na 5 (tj. pół sekundy); po trzecie, install ustawiłem na text; po czwarte, dodałem opcję single-key, która powoduje, że system jest wybierany przez wciśnięcie pojedynczego klawisza; i po piąte, pozmieniałem wszędzie label na jednoliterowe (konkretnie: l - linux, o - linux z poprzednim jądrem, s - linux w trybie single, w - windows). Mój cały plik /etc/lilo.conf wygląda następująco:

boot = /dev/hda
lba32
compact
prompt
install = text
timeout = 5
single-key

image = /boot/bzImage
  root = /dev/hda5
  label = l
  read-only

image = /boot/bzImage~
  root = /dev/hda5
  label = o
  read-only

image = /boot/bzImage
  root = /dev/hda5
  label = s
  read-only
  append = "single"

other = /dev/hda1
  label = w
  table = /dev/hda

Inne

Jeszcze jedna mała sztuczka. Otóż czasami zdarza mi się, że zamiast ls nazwa_katalogu wpisuje less nazwa_katalogu. W ten sposób otrzymuje błąd z informacją, że podany plik to katalog (jakie odkrywcze :P). Jednakże jest bardzo łatwo nauczyć less listowania zawartości katalogu. W tym celu otweiramy plik /usr/bin/lesspipe.sh i jego ostatnia linijkę (tj. lesspipe "$1") zamieniamy na:

if [ -d "$1" ]; then
  /bin/ls -lT0 --color=no -I '*~' -I '#*' -I '.#*' -- "$1"
else
  lesspipe "$1"
fi

Oczywiście można też skorzystać z lesspipe dostępnego w pakiecie Tiny Applications, który ma też różne inne ciekawe funkcje (np. ściąganie plików). Instalacja sprowadza się do dodania linijki $(eval $(/sciezka/do/lesspipe --install-lesspipe) do pliku profilu.

umask

Ponieważ wyznaję zasadę, iż lepiej domyślnie nie dawać jakichś uprawnień i w razie konieczności to zmienić, w skryptach startowych na swoim koncie mam ustawione umask 077, przez co tworzone przeze mnie pliki mają ustawione zerowe uprawnienia dla grupy i innych użytkowników. Jednakże instalowanie jakichkolwiek programów jako root czy tworzenie paczek z taką maską może naprawdę zaboleć, a zwykłe polecenie su pozostawia umask taki jaki był. Z tego powodu, warto, na wszelki wypadek, do skryptów startowych roota dodać wpisy zmieniające umask na domyślny. Uruchamiamy jako root (niektóre linijki zapewne można pominąć):

  for f in shell bash zsh csh ksh; do
    echo umask 022 >>~/.${f}rc
done

TMOUT

Ciekawym pomysłem jest również ustawienie zmiennej TMOUT, w niektórych lub wszystkich skryptach startowych powłoki. Zasadniczo, jeżeli po czasie (w sekundach) określonym przez tą zmienną użytkownik nic nie wpisze do powłoki zostanie on automatycznie wylogowany. Osobiście używam tej opcji w dwóch miejscach: w powłoce super użytkownika oraz powłoce logowania zwykłego użytkownika (jako root, mina86 podmieniamy na nazwę naszego użytkownika):

  for f in '' bash_ z; do
    echo TMOUT=1200 >>~mina86/.${f}profile
done

for f in shell bash zsh csh ksh; do
    echo TMOUT=1200 >>~/.${f}rc
done