A szövegszerkesztő – vi

Ma egy szövegszerkesztőről van egy körülbelüli elképzelésünk. Na a vi nem ilyen. 🙂

A vi <filenév> paranccsal indul a szövegszerkesztő. Ilyenkor alapban parancs módban vagyunk. 🙂 Billentyűkkel lehet eljutni a szerkesztői módba. Szerkeszteni ugyanis szerkesztői módban lehet. 🙂 “O” (shift+o) billentyűvel egy új sort szerkeszthetünk az aktuális pozíció fölött – ezek között a nyilakkal közlekedhetünk, esetleg “:<sorszám>“-mal, parancs módban. “o” billenyűvel az aktuális pozíció alatt nyílik új sor. “i” betűvel az aktuális pozícióban tudunk beszúrni szöveget, “a” betűvel hozzáfűzhetünk szöveget az aktuális pozíciótól (append). 🙂 Szerkesztői módból az “esc” billentyűvel tudunk parancs módba visszalépni.

Hogy ez miért jó? Mert szinte minden terminálban, bármely UNIX és Linux rendszerben installálva van vagy installálható. Egyébként nem muszáj használni (“:h” -val segítség kérhető, amiből “:q“-val lehet kilépni :)). Van az editor vagy nano, ami jobb műkedvelőknek. Az ctrl szekvenciákkal vezérelhető. 🙂 Hogy mégis miért jó? A jó programozó tud vi-ban, akár osztott ablakban, szintaxis-kiemeléssel, kizárólag billentyűk lenyomásával akármit írni (!).

Nézzük tovább a használatot. Kilépés, ha nem módosítottunk – ellenkező esetben hibaüzenetet kapunk – a “:q“, kilépés módosítások elvetésével “:q!“. Kilépés mentéssel “:wq” vagy “shift+zz“. 🙂

Nem írnám le a teljes kezelést, az szorgalmi++. 🙂 Még részleteznék pár apróságot. Hogyan lehet keresni? Egész egyszerűen parancs módban “/<keresendő_sztring>” – “n” betűvel lehet lépkedni előre, “shift+n“-nel visszafelé a találatok között. Még fontos lehet az “undo”, visszavonás funkció, ez egész egyszerűen az “u” parancs. Egy sort a “dd” paranccsal tudunk törölni. Három sort “3dd” paranccsal. 🙂 Jó, nem?

Akkor nézzük a továbbiakban felsorolásszerűen.

Ugrás a sor végére: “$
Ugrás a sor elejére: “0
Beolvas egy file-t. és beszúrja az adott pozcióba: “:r <filenév>
Képernyő megosztása: “:split <filenév>
Képernyő függőleges megosztása: “:vsplit <filenév>
Navigáció a két osztott képernyő között: “ctrl+ww
Sor másolása: másolás: “yy” (yank), kivágás: “dd” (delete), beillesztés pozíció előtt: “P“, pozíció után: “p” (paste)
Kijelölés másolásra karakterenként: “v“, soronként: “V“, utána “y” vagy “d“, végül “p” vagy “P” a beillesztéshez, osztott képernyők között is működik 🙂
File vége: “shift+g“, eleje “g
Egy szó előre: “w“, hátra: “b

És akkor beszéljünk még egy dologról. Minden editor tudja a keresés és cserét. Nézzük meg ezt vi-ban. A parancs formátuma a következő: “:%s/<keresendő>/<cserélendő>/“, illetve ha minden sorban többször előfordulhat a keresendő és cserélendő sztring, akkor “:%s/<keresendő>/<cserélendő>/g” – a végén van egy “g“. Itt említeni illik a keresett kifejezéssel kapcsolatban az ún. reguláris kifejezéseket (reguar expressions). Ez az a formátum, ahogyan a keresendő sztring megadható. A sed parancs egyébként ugyanilyen formátummal működik, file(ok)-ban cserél sztringeket. (A sztring karakterfüzér.) RegExp részletek az alábbi link alatt. 🙂

http://vbence.web.elte.hu/regex_leiras.html

A végére még egy “elvetemült” dolog. 🙂 Lehet a bash shell-ünket is vi módban használni. Egyébként pl. az előző parancs előhozására a fel nyilat használhatjuk. Igazából a fel/le nyilakkal kereshetünk az előzőleg beírt parancsok között, sőt: a shell-ünk el is menti a .bash_history file-ba az előzőleg beírt parancsainkat, így ha újra kinyitjuk a shell-t is emlékezni fog a parancsainkra. 🙂 Fontos funkcionalitás még “sima” shell-ben az ugrás a sor elejére “ctrl+a“, sor végére “ctrl+e“, továbbá aktuális parancs megszakítása “ctrl+c“. De mi is az a vi módú shell? A home könyvtáramban létrehoztam a .inputrc file-t, a következő tartalommal.

gvamosi@gergo1:~$ cat .inputrc
set editing-mode vi

Újra “beléptem” a shell-be (kilépés ctrl+d-vel, és újraindítás). Innentől az “esc” billentyűvel parancsmódba kerülünk, vi parancsmódba. Minden ugyanúgy működik, ahogy vi-ban. Ez tényleg csak a legkeményebb admin-oknál van így beállítva. 😉

És hogy hogy lehet a szintaxis kiemelést (syntax highlight) bekapcsolni? Nálam, a Debian 10-ben elég egyszerűen. Nézzük.

gvamosi@gergo1:~$ sudo apt-get install vim
..
gvamosi@gergo1:~$ which vi
/usr/bin/vi
gvamosi@gergo1:~$ l /usr/bin/vi
lrwxrwxrwx 1 root root 20 Aug 26 2017 /usr/bin/vi -> /etc/alternatives/vi
gvamosi@gergo1:~$ l /etc/alternatives/vi
lrwxrwxrwx 1 root root 18 Oct 2 00:12 /etc/alternatives/vi -> /usr/bin/vim.basic

Telepítés (install) után az alapértelmezett vi editor a vim lesz, amiben a szintaxis kiemelés bekapcsolt. 🙂 Vi IMproved, a programmer’s text editor.

Debug – hibakeresés, bináris debug, kis lépések módszere, strace

Ha programozunk, debug-olnuk is kell, azaz hibát is kell keresnünk, mivel a hibátlan programozást még nem találták fel. Erre komplett fejlesztő eszközök vannak, melyek használatát itt nem részletezném. Maga a debug szó “bogártalanítást” jelent, és egy urbánus legendába hajló sztori az alapja. Az első számítógépek fizikai relékkel (jelfogókkal) működtek. Egy ilyen őskori gép egyszer elromlott, mivel bele ment egy bogár. 🙂 Azóta debug a hibakeresés.

Nézzük a programozó alap és egyben legvégső fegyverét, a bináris debug-ot. Ehhez binárisan kell gondolkodnunk. Működési elve igen egyszerű.

  1. Felezzük meg a kódunkat, kommentezzük ki a kód egyik felét.
  2. Ha megtaláljuk a hibát az egyik felében, és nem értünk a végére, akkor 1-es lépés (felezzük tovább a kódot). Ha a végére értünk, akkor megvan a hiba. 🙂
  3. Ha nincs benne hiba, akkor cseréljük fel a kikommentezett felet és a nem kikommentezett felet, majd 1-es lépés. 🙂

Látható, hogy nem bonyolult, legfeljebb időigényes. Hamar be lehet a segítségével korlátozni a hiba helyét egy-két sornyi kódra. A lépések száma a kettő hatványainak kitevője, ebben a matematikai mélységi kereséshez hasonlít. Ezzel a módszerrel még akkor is boldogulunk, ha több hiba is előfordul a kódban, mivel “brute force” az algoritmus. 🙂

Ja és hogy mit jelent a “kikommentezés”? Olyan kódrészlet, ami nem hajtódik végre, kisegítő információ a forráskódban a programozók számára (a forráskód általában lefordításra kerül, hogy a számítógép is “megértse”). Ahogy az eddigiekben látható, shell script-ben a hashmark # a sor elején vagy végén a megjegyés helye, C-ben, C++-ban és JAVA-ban pedig a blokk megjegyzés /* megjegyzés */ formátumú, illetve az egy sornyi megjegyés a // jelek után írandó.

A kis lépések módszere még egyszerűbb az előbbinél, és széles körűen alkalmazzák a fejlesztők. A lényege, hogy csak egy vagy legfeljebb pár sor új kódot adunk hozzá az addigiekhez programozás során, illetve csak egy újabb modult fűzünk hozzá, nem egyből egy maréknyit, és természetesen egyből tesztelünk. Így gyorsan kiderül, ha hibás kódot írtunk le, és nem kell három napot egyetlen hiba megtalálásával töltenünk! 🙂

Végül nézzük meg a strace használatát (miután apt-get-tel telepítettem). Ezzel a programmal a rendszerhívásokat és a jelzéseket írathatjuk ki egy tetszőleges program végrehajtása során. Vegyük az egyszerű alma.sh programot.

gvamosi@gergo1:~$ cat alma.sh
#!/bin/sh
ls --color -l

Meglepő lehet, de a kétsoros script hatalmas strace kimenetet generál! Nézzük meg a “nyomkövetés” eredményét.

gvamosi@gergo1:~$ strace alma.sh
execve("./alma.sh", ["alma.sh"], 0x7fffb90cb390 /* 39 vars */) = 0
brk(NULL) = 0x55ffa24e5000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=169286, …}) = 0
mmap(NULL, 169286, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f458d3ff000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260A\2\0\0\0\0\0"…, 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1824496, …}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f458d3fd000
mmap(NULL, 1837056, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f458d23c000
mprotect(0x7f458d25e000, 1658880, PROT_NONE) = 0
mmap(0x7f458d25e000, 1343488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f458d25e000
mmap(0x7f458d3a6000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16a000) = 0x7f458d3a6000
mmap(0x7f458d3f3000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7f458d3f3000
mmap(0x7f458d3f9000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f458d3f9000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f458d3fe580) = 0
mprotect(0x7f458d3f3000, 16384, PROT_READ) = 0
mprotect(0x55ffa169d000, 8192, PROT_READ) = 0
mprotect(0x7f458d450000, 4096, PROT_READ) = 0
munmap(0x7f458d3ff000, 169286) = 0
getuid() = 1000
getgid() = 1000
getpid() = 19358
rt_sigaction(SIGCHLD, {sa_handler=0x55ffa1693380, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7f458d273840}, NULL, 8) = 0
geteuid() = 1000
brk(NULL) = 0x55ffa24e5000
brk(0x55ffa2506000) = 0x55ffa2506000
getppid() = 19355
stat("/home/gvamosi", {st_mode=S_IFDIR|0755, st_size=4096, …}) = 0
stat(".", {st_mode=S_IFDIR|0755, st_size=4096, …}) = 0
openat(AT_FDCWD, "./alma.sh", O_RDONLY) = 3
fcntl(3, F_DUPFD, 10) = 10
close(3) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
geteuid() = 1000
getegid() = 1000
rt_sigaction(SIGINT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x55ffa1693380, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7f458d273840}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7f458d273840}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=SIG_DFL, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7f458d273840}, NULL, 8) = 0
read(10, "#!/bin/sh\n\nls --color -l\n", 8192) = 25
stat("/usr/local/bin/ls", 0x7ffea163b940) = -1 ENOENT (No such file or directory)
stat("/usr/bin/ls", 0x7ffea163b940) = -1 ENOENT (No such file or directory)
stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=138856, …}) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f458d3fe850) = 19359
wait4(-1, total 300
lrwxrwxrwx 1 gvamosi gvamosi 5 Sep 8 11:18 alma.sh -> ls.sh
..
-rwxr-xr-x 1 gvamosi gvamosi 25 Sep 8 11:10 ls.sh
..
drwxr-xr-x 2 gvamosi gvamosi 4096 Aug 26 2017 Videos
[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 19359
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=19359, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn({mask=[]}) = 19359
read(10, "", 8192) = 0
exit_group(0) = ?
+++ exited with 0 +++

Használjuk csak valamire ezt a kimenetet! Látható, hogy az ls parancsot a keresési útvonalban két helyen is “hiába” keresi a programunk. Nézzük meg a which paranccsal, hogy hol található az ls parancs.

gvamosi@gergo1:~$ which ls
/bin/ls

Javítsuk ki a scriptben a dolgot, írjuk bele a teljes útvonalat! Most nézzük csak meg a releváns strace kimeneti részt!

rt_sigaction(SIGTERM, {sa_handler=SIG_DFL, sa_mask=~[RTMIN RT_1], sa_flags=SA_RESTORER, sa_restorer=0x7f52fb075840}, NULL, 8) = 0
read(10, "#!/bin/sh\n\n/bin/ls --color -l\n", 8192) = 30
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f52fb200850) = 13884
wait4(-1, total 300

Nincs is stat hívás az ls-re. Optimalizáltuk a kódot; három rendszerhívással kevesebb. Voila! 🙂

Végezetül köszönettel tartozom JÁ barátomnak a bináris debug-ért, hogy egyszer régen megtanított rá, illetve ide idézem FCs barátom jó tanácsát programozóknak, szintén köszönettel: “Programozni jól, és hibátlanul kell!” 🙂

Fork-bomba (és harakiri) :)

Ma az alábbi scriptről lesz szó, ami nemes egyszerűséggel a fork_bomb.sh nevet kapta. Arra való, hogy padlóra vigye a Linux vagy UNIX rendszert. Ha egy szülő folyamat egy gyermek folyamatot indít, fork történik. Ez a “bomba” saját magát indítja el újra meg újra. Ez egyébként csúnya dolog ebben a formában. 🙂

gvamosi@gergo1:~$ cat fork_bomb.sh
#!/bin/sh
#
# fork test by gvamosi on 2019-09-29
############################################

var1=0
if [ -n "$1" ]; then
var1=$1
fi
echo "$0 $var1"
var1=$((var1 + 1))

while true; do
sleep 2
/bin/sh $0 $var1 & # itt történik a rekurzív hívás, a "fork"
done

Hogy hogyan lehet elindítani?

gvamosi@gergo1:~$ ./fork_bomb.sh &

És leállítani, ha még nem késő? Két másodpercre vettem a sleep-jét, hogy legyen idő beavatkozni. A Linux-unk ugyan korlátozza az egy felhasználó által nyitható processzek számát, de egy másodperces sleep-pel a notebook-omat sikerült úgy megfektetnem, hogy csak a “szentháromság” (ctrl+alt+del) segített. Ugyanis hiába zárja be az operációs rendszer a processzeket, a rekurzív fork miatt újra és újra nyílnak a kis programocskák, így egy tartós leterhelt állapot keletkezik. Ilyenkor nem, vagy csak alig reagál a számítógépünk.

gvamosi@gergo1:~$ killall fork_bomb.sh
gvamosi@gergo1:~$ killall sh

Ez a két parancs segíthet, ebben a sorrendben, ha elég gyorsak vagyunk. 🙂

Utólag nézem, hogy a “kill -9 -1” – ilyet azért root-ként (rendszergazdaként) vagy dba-ként (adatbázis-adminisztrátorként) be ne írjunk, adatvesztés történhet! – úgy kivágta a saját processz-erdőmet egy szemvillanás alatt, hogy öröm volt nézni. 🙂 Megteszi reboot helyett, még jó, hogy a chrome böngészőmben van “restore” funkció a tabfülekre. 🙂

Egyébként a rendelkezésre álló “javakról” az ulimit parancs segítségével tájékozódhatunk.

gvamosi@gergo1:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 30575
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 30575
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

Jól látható, hogy 1024-nél több fork_bomb.sh-t nem igen indíthatunk. A rendszergazda így simán tökön tud rúgni minket, ha garázdálkodunk. Régebben egyébként használtak az adminok ún. “watchdog” démont, ami automtikusan reboot-olta a rendszert, ha nagy volt a baj. 🙂

Van még egy érdekes parancs. Ez a root-ként (rendszergazdaként) kiadott “rm -rf /“. Rákérdezés nélküli rekurzív törlés a gyökérből kiindulva. Használata szigorúan TILOS!!! Letöröl MINDENT a DISZKRŐL!!! VÉGLEGESEN!!! Ezt a parancsot csak egyszer adhatjuk ki. 😦

Titkosítás, DES, AES, Blowfish, MD4, MD5, SHA-2, RSA, DSA, RC4, TKIP, WEP, WPA, WPA2, TLS, SSL, PGP, SSH

Igen sok rövidítés került a címbe. Ezek egy része algoritmus, más része hash függvény vagy protokoll. A teljesség igénye nélkül vegyük sorra őket, hiszen ezekkel találkozhatunk a mindennapi életben.

A DES (Data Encryption Standard) illetve a Triple DES és az AES (Advanced Encryption Standard) ún. szimmetrikus kulcsú vagy “titkos kulcsú” algoritmusok. Ez azt jelenti, hogy minden félnek ismernie kell a kulcsot, mind a titkosításhoz, mind a dekódoláshoz. Ez a fő hibájuk egyébként. A DES már történelem. Több mint 20 éve feltörték. 🙂 Az AES algoritmus a WPA2-ben (Wi-Fi Protected Access) használatos, még ma is biztonságosan működik. A Blowfish pedig az egyik első biztonságos blokk-kódoló – szimmetrikus – algoritmus. Ma már az AES népszerűbb.

https://en.wikipedia.org/wiki/Symmetric-key_algorithm

https://en.m.wikipedia.org/wiki/Blowfish_(cipher)

Vannak az előzőekkel szemben az ún aszimmetrikus kulcsú vagyis nyilvános kulcsú titkosító algoritmusok. Ez a korszerű és a biztonságos(abb) egyébként. Itt kulcspárt generálunk, és a fogadó fél a privát kulcsommal kódolt üzenetemet a rendelkezésére bocsájtott nyilvános kulcsommal tudja elolvasni, és vica versa. Ilyen megoldások az RSA (Rivest–Shamir–Adleman) és a DSA (Digital Signature Algorithm) algoritmusok. Az RSA széles körben elterjedt titkosított adatátvitelhez.

https://en.wikipedia.org/wiki/Public-key_cryptography

https://en.wikipedia.org/wiki/RSA_(cryptosystem)

https://en.wikipedia.org/wiki/Digital_Signature_Algorithm

Aztán nézzük meg az MD4-et illetve az MD5-öt (Message-Digest algorithm 5). Ezek egyirányú kódoló algoritmusok. Mára elavultak, ezért az SHA-2 (Secure Hash Algorithm 2) váltotta ki őket. Linux alatt a jelszók kódolására használják ezt a fajta titkosítást. Csak azt lehet ellenőrizni, hogy a két kódolt karaktersorozat egyezik-e, ezért nem lehet egy elfelejtett jelszót “megmondani”. 🙂 A bitcoin kriptovaluta pl. a SHA-2 családba tartozó SHA-256 kriptografikus hash függvényt használja többek között blokk-láncai kódolásához is. A hash függvény matematikai fogalom, egy értékkészletet képez le egy szignifikánsan (jelentősen) kisebb értéktartományra.

https://hu.wikipedia.org/wiki/MD5

https://en.wikipedia.org/wiki/SHA-2

És akkor még itt van az RC4 (Rivest Cipher 4). Ez folyam kódoló, de sajnos olyan törhető titkosításokhoz használták, mint a WEP (Wired Equivalent Privacy). Ezt ma már nem használjuk még véletlenül sem. Volt még ilyen gyermekbetegség-kódolás, a TKIP (Temporal Key Integrity Protocol). Azt sem fejlesztették tovább. 🙂

https://en.wikipedia.org/wiki/RC4

https://en.wikipedia.org/wiki/Wired_Equivalent_Privacy

https://hu.wikipedia.org/wiki/TKIP

Ma nyilvános kulcsú algoritmusból legalább 2048 bites RSA kulcsokat, szimmetrikusból AES-t, illetve egyirányúból SHA-2-t használunk. 🙂

RSA titkosítást használunk a TLS (Transport Layer Security), SSL (Secure Sockets Layer) és SSH (Secure Shell) protokollokban, illetve PGP (Pretty Good Privacy) folyamán.

https://hu.wikipedia.org/wiki/PGP

A TSL-t az a bizonyos “https://” kezdetű rész használja a böngészőnkben a weszerverrel való kommunikációban – fontos eleme a “kézfogás” (handshaking) -, a PGP pedig egy titkos levelezésnél hasznos. 🙂

https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/

Egy informatikai biztonsággal foglalkozó kollégám mondta egyszer nekem, hogy informatikai biztonság nem létezik. Csak a vasbeton trezorban a konnektorból is kihúzott számítógép, fegyveres őrrel az ajtóban. És valóban. Mit ér mindez, ha a felhasználó hibájából van a notebook-ban egy cetli a jelszóval. 🙂

Linux parancsok IV.

Sort kell kerítsek még néhány parancs bemutatására. Nézzük sorban. Ha belépünk egy Linux szerverre, hasznos lehet az uname parancs.

gvamosi@gergo1:~$ uname -a
Linux gergo1 4.19.0-5-amd64 #1 SMP Debian 4.19.37-5 (2019-06-19) x86_64 GNU/Linux

A parancs kimenetéből egyből megtudhatjuk, hogy az operációs rendszer Linux, Debian Linux, a hoszt neve gergo1, a kernelünk (leírása később) 4.19-es, a rendszerünk x86 alapú és 64 bites, és egy dátumot is láthatunk az oprendszer kibocsátásával kapcsolatban. 🙂

Fontos parancs lehet még a hostname parancs is, hasonlóan sokmindent kideríthetünk az adott hosztról.

gvamosi@gergo1:~$ hostname
gergo1
gvamosi@gergo1:~$ hostname -I
192.168.0.109

Ebből a parancsból megtudjuk a szerver IP-címét. Nem beszéltem még részletesebben a hálózat egyik alapvető protokolljáról, az ICMP-ről (Internet Control Message Protocol). A hálózat diagnosztikájában segítségünkre lehet a ping parancs. Ez egy ICMP üzenet, datagramm jellegű, ahogy az UDP, és válaszüzenete a pong. Milyen meglepő. 🙂

https://hu.wikipedia.org/wiki/ICMP

Nézzünk egy példát a parancs kimenetére, melyben “megpingetjük” a BME névszerverét.

gvamosi@gergo1:~$ ping nic.bme.hu
PING nic.bme.hu (152.66.115.1) 56(84) bytes of data.
64 bytes from nic.bme.hu (152.66.115.1): icmp_seq=1 ttl=55 time=23.5 ms
64 bytes from nic.bme.hu (152.66.115.1): icmp_seq=2 ttl=55 time=22.9 ms
64 bytes from nic.bme.hu (152.66.115.1): icmp_seq=3 ttl=55 time=32.0 ms
^C
— nic.bme.hu ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 22.899/26.133/32.006/4.161 ms

Látható, hogy feloldja az IP-címet, aztán hogy ctrl+c-vel “lépünk ki” belőle, illetve egy rövid kis statisztika. A 0% csomagveszteség a jó, és ezek a milliszekundomok jó válaszidőnek számítanak. A hálózat megfelelően gyors. 🙂

Van még egy parancs, amiről szólni szeretnék, ez a mount. Ezzel a paranccsal lehetett eredetileg egy CD-t vagy DVD-t a Linux filerendszer részévé tenni, “felcsatolni” a /mnt könyvtár alá. De így lehet pl. a teljes filerendszert újracsatolni, pl. read-only (csak olvasható) módban, vagy akár egy hálózati kötetet csatolni, pl. NFS-en (Network File System) keresztül. A külső médiák behelyezésénél ma már automatikusan működik mindez. Ha pl. egy USB stick-et, egy “pendrive“-ot csatlakoztatok a laptopomhoz, akkor azt a rendszer felismeri. 🙂 De nézzük meg a mount parancs kimenetét paraméterek nélkül. Elég cifra!

gvamosi@gergo1:~$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=3965840k,nr_inodes=991460,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=797444k,mode=755)
/dev/sda2 on / type ext4 (rw,relatime,errors=remount-ro)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime)
efivarfs on /sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime)
bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
mqueue on /dev/mqueue type mqueue (rw,relatime)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=44,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=12776)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
/dev/sda1 on /boot/efi type vfat (rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=797440k,mode=700,uid=1000,gid=1000)
gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
tracefs on /sys/kernel/debug/tracing type tracefs (rw,relatime)

Ebben nagyon sok minden van. Látható a “lényeg” is, a root filerendszer: /dev/sda2 on / type ext4 (rw,relatime,errors=remount-ro). Itt az áll, hogy a filerendszer ext4 típusú, és rw – írható módon van csatolva. 🙂

Egyébként az fstab – a /etc könyvtárban – tartalmazza a filerendszer mount-jait (root, swap, etc.)

gvamosi@gergo1:~$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use ‘blkid’ to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda2 during installation
UUID=cab2004d-b7b8-4ba2-9831-cc1a987e2ba2 / ext4 errors=remount-ro 0 1
# /boot/efi was on /dev/sda1 during installation
UUID=B5A5-032A /boot/efi vfat umask=0077 0 1
# swap was on /dev/sda3 during installation
UUID=83144245-6f61-477a-97a3-9f55ca34c3fc none swap sw 0 0

És akkor a mai írásom végére egy apró nüansz. Amikor a konzolon bejelentkezik egy felhasználó, vagy akár SSH-n keresztül, kap egy rövid üzenetet. Ez nem máshol van, mint a /etc/motd file-ban. Ide bármit írhatunk, még ún. vezérlő karaktereket is, ha valami színest vagy fényeset szeretnénk. 🙂

gvamosi@gergo1:~$ cat /etc/motd
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

Mentés (backup)

A mentés a nagyon fontos gyakorlati rendszergazdai teendő. Az informatika egyik alaptétele a következő: ha egy adat csak egy helyen van meg, az nincsen (!).

Ezért fontos mentési stratégiát kialakítani egy szerver, de akár a desktop gépünk, illetve hordozható eszközünk esetében is! Tiszteljük meg annyira saját magunkat, hogy saját munkáinkat, adatainkat, leveleinket, kapcsolatainkat, etc. legalább lementjük egy fizikailag különböző helyre időközönként! Erre szolgál egyébként a felhő is. Azonban nem minden esetben kifizetődő a használata! Egyébként pl. az ownCloud felhőt mi is telepíthetjük. Lehet saját felhőnk is!

https://owncloud.org/

Nézzük azonban a klasszikus backup-ot, mondjuk egy kódolt hálózatit.

A szeptember 16-ai írásomban az SSH-ról leírtam a publikus kulccsal hitelesített jelszó nélküli kapcsolatot. Ez tökéletes alap egy hálózati mentéshez. Hirtelen két stratégia is eszembe jut.

  1. A távoli szerveren fut egy ún. cron job, a felhasználói crontab-ban – ez egy ütemezett feladatot jelent – mondjuk naponta. Egy script. ami ún. .tar.gz vagy .tgz tömörített állományt (archívumot) hoz létre – ez a Linux/UNIX rendszerek saját ZIP megoldása – a menteni kívánt könyvtárból, természetesen rekurzívan. Futhat pl. hajnai 3-kor. Hajnali fél négykor pedig a helyi gépünkön, ahova mentünk, lefut egy másik script, ami scp-vel, jelszó nélküli átvitelben átmásolja, “letölti” a tömörített állományt. 🙂
  2. A második megoldásban az “ssh” parancs segítségével a távoli gépen – amiről a mentést készítjük – egy scriptet futtatunk, amiben tömörítjük a menteni kívánt könyvtárat a “tar czvf <archívum_időbélyeg.tgz> <könyvtár>” paranccsal vagy a tar és a gzip parancsok kombinációjával (tar cvo <könyvtár> | gzip – > <archívum_időbélyeg.tar.gz>), ezt követően pedig scp-vel átmásoljuk a helyi gépünkre. Ezt elég lesz helyileg ütemeznünk, de akár kézzel is indíthatjuk. 🙂

https://www.shellhacks.com/ssh-execute-remote-command-script-linux/

Látható, hogy nem ördöngősség a mentés. Jóllehet azért nagyon nagy mennyiségű adat mentésénél már több eszközre van szükségünk, mint egy-két Linux parancs. 🙂

Meg kell említsem még a bzip2-t, mint egy újabb, és hatékonyabb tömörítő algoritmust használó tömörítő programcsomagot (https://www.sourceware.org/bzip2/). Általában igaz, hogy a tar archivál, a gzip és a bzip2 pedig tömörítenek. Ma már a bzip2 is alapból telepítve van egy Linux-on, sőt tar-ból is elérhető a “-j, –bzip2” kapcsolóval. Az alábbi linken található még néhány hasznos információ az archiválásról.

https://www.thomas-krenn.com/en/wiki/Archive_under_Linux_(tar,_gz,_bz2,_zip)

A log-olás (logging), naplózás alapjai

Linux rendszerünkben – pláne ha szerver – sokféle esmény történik. Ezek nyomot is hagynak – már ha jól van minden beállítva -, alapvető helyük az ún. syslog (rendszer napló), helye a könyvtárstruktúrában “/var/log/syslog“.

Beszélnünk kell még egy alapvető dologról. Minden folyamatnak van egy bemenete (STDIN, száma 0) és két kimenete: a standard kimenet (STDOUT, száma 1) és a standard hibakimenet (STDERR, száma 2).

Nézzük meg, hogyan lehet egy folyamat mindkét kimenetét “log-olni”! 🙂

root@gergo1:~# ls -lR / &> logfile

Ez aztán létrehoz nálam egy cirka 70 MByte-os logfile-t. Benne a “sima” kimenet, és a hibák is. Lássunk erre példát!

root@gergo1:~# grep "proc" logfile | less
..
/proc/11/fd:
/proc/11/fdinfo:
/proc/11/map_files:
/proc/11/net:
/proc/11/net/dev_snmp6:
/proc/11/net/netfilter:
/proc/11/net/stat:
/proc/11/ns:
/proc/11/task:
/proc/11/task/11:
ls: cannot read symbolic link '/proc/11/task/11/exe': No such file or directory
..

Látható a kimenet, és egy hiba is. Az előbbivel ekvivalens a “klasszikus” formájú parancs.

root@gergo1:~# ls -lR / > logfile.1 2>&1

Látható, hogy az STDERR “file” bele van “irányítva” az STDOUT “file”-ba, és mindkettő a “logfile.1”-be.

Vigyázat! A szimpla “kacsacsőr“, a “>” jel lenullázza a kimeneti file-t. Ha csak hozzáírni akarunk egy logfile-hoz, akkor a “dupla kacsacsőrt” kell használnuk: “>>“. Ez a “hozzáfűzés” (append).

Természetesen minden szerverfolyamatnak van log-ja, így pl. a webszerver logfile-jait a “/var/log/apache2” könyvtár alatt találjuk meg.

root@gergo1:~# l /var/log/apache2/
total 116
-rw-r—– 1 root adm 0 Sep 24 00:00 access.log
-rw-r—– 1 root adm 148 Sep 23 22:49 access.log.1
..
-rw-r—– 1 root adm 309 Sep 22 13:10 access.log.2.gz
..
-rw-r—– 1 root adm 239 Sep 24 00:00 error.log
-rw-r—– 1 root adm 869 Sep 24 00:00 error.log.1
..
-rw-r—– 1 root adm 337 Sep 23 00:46 error.log.2.gz
-rw-r—– 1 root adm 337 Sep 22 00:00 error.log.3.gz
..

Látható, hogy a régebbi logok egy számot kapnak, majd tömörítve vannak gzip-pel (a .gz kiterjesztés erre utal), naponta új logfile készül. Van “hozzáférési napló” (access log), illetve “hibanapló” (error log).

Egy logfile-t a “tail -f” paranccsal tudunk úgy megnyitni, hogy folyton lássuk az újabb sorokat, lévén ez is szövegfile. Semmi extra! 🙂

És végezetül szeretném megjegyezni, hogy leht log-olni akár egy terminálra is. Régebben a “/dev/tty12“-re, az utolsó terminálra írtam az összefoglaló logot, hogy egy egyszerű terminál-váltással (ctrl+alt+f12) azonnal láthassam, hol van valami “hiba” a szerveren. 🙂

Init script-ek, kill -HUP, runlevel-ek, boot loader

A Linux rendszert induláskor egy ún. boot loader tölti be, helye fizikailag a rendszerben konfigurált boot-sorrendben megtalálható “merevlemez” – HDD vagy SSD -, USB stick, CD vagy DVD, illetve hasonlóak lehetnek (a jövőre nézve). Ezeken van egy ún. MBR – Master Boot Record, ahol egy apró információt tárol el a boot loader – régebben LILO, ma inkább GRUB -, tudniillik valahova “lépnie” kell, hogy “beolvassa” az operációs rendszer file-jait, így betölti a kernel-t (a “rendszermag”, leírása később), a modulokat, és belép egy előre beállított ún. runlevel-be.

Debian 10 alatt alapban az 5-ösfutási szint” van beállítva. Ez többfelhasználós, grafikus mód. A runlevel paranccsal ellenőrizhetjük. 🙂

root@gergo1:~# runlevel
N 5

Ezen a runlevel-en a “/etc/rc5.d” könyvtár tartalma hajtódik végre. Ez a könyvtár szimbolikus linkeket (hivatkozásokat) tartalmaz a “/etc/init.d” könyvtárban lévő ún. init script-ekre.

root@gergo1:~# l /etc/rc5.d/
total 0
lrwxrwxrwx 1 root root 29 Aug 28 2017 K01apache-htcacheclean -> ../init.d/apache-htcacheclean
lrwxrwxrwx 1 root root 27 Aug 26 2017 K01speech-dispatcher -> ../init.d/speech-dispatcher
lrwxrwxrwx 1 root root 15 Aug 26 2017 S01acpid -> ../init.d/acpid
lrwxrwxrwx 1 root root 17 Aug 26 2017 S01anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root 17 Aug 28 2017 S01apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 22 Aug 26 2017 S01avahi-daemon -> ../init.d/avahi-daemon
lrwxrwxrwx 1 root root 19 Aug 26 2017 S01bluetooth -> ../init.d/bluetooth
lrwxrwxrwx 1 root root 26 Aug 26 2017 S01console-setup.sh -> ../init.d/console-setup.sh
lrwxrwxrwx 1 root root 14 Aug 26 2017 S01cron -> ../init.d/cron
lrwxrwxrwx 1 root root 14 Aug 26 2017 S01dbus -> ../init.d/dbus
lrwxrwxrwx 1 root root 14 Aug 26 2017 S01gdm3 -> ../init.d/gdm3
lrwxrwxrwx 1 root root 13 Sep 4 07:07 S01gpm -> ../init.d/gpm
lrwxrwxrwx 1 root root 17 Jun 19 03:53 S01haveged -> ../init.d/haveged
lrwxrwxrwx 1 root root 18 Aug 26 2017 S01iptables -> ../init.d/iptables
lrwxrwxrwx 1 root root 20 Oct 23 2017 S01irqbalance -> ../init.d/irqbalance
lrwxrwxrwx 1 root root 18 Sep 1 2017 S01libvirtd -> ../init.d/libvirtd
lrwxrwxrwx 1 root root 24 Sep 1 2017 S01libvirt-guests -> ../init.d/libvirt-guests
lrwxrwxrwx 1 root root 23 Sep 1 2017 S01lvm2-lvmpolld -> ../init.d/lvm2-lvmpolld
lrwxrwxrwx 1 root root 19 Aug 26 2017 S01minissdpd -> ../init.d/minissdpd
lrwxrwxrwx 1 root root 15 Aug 28 2017 S01mysql -> ../init.d/mysql
lrwxrwxrwx 1 root root 25 Aug 26 2017 S01network-manager -> ../init.d/network-manager
lrwxrwxrwx 1 root root 14 Jun 7 02:39 S01nmbd -> ../init.d/nmbd
lrwxrwxrwx 1 root root 18 Jun 19 03:53 S01plymouth -> ../init.d/plymouth
lrwxrwxrwx 1 root root 15 Aug 26 2017 S01rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root 17 Aug 26 2017 S01rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root 21 Jun 7 02:39 S01samba-ad-dc -> ../init.d/samba-ad-dc
lrwxrwxrwx 1 root root 15 Aug 26 2017 S01saned -> ../init.d/saned
lrwxrwxrwx 1 root root 14 Jun 7 02:39 S01smbd -> ../init.d/smbd
lrwxrwxrwx 1 root root 13 Sep 15 21:42 S01ssh -> ../init.d/ssh
lrwxrwxrwx 1 root root 14 Jun 19 03:52 S01sudo -> ../init.d/sudo
lrwxrwxrwx 1 root root 29 Aug 26 2017 S01unattended-upgrades -> ../init.d/unattended-upgrades
lrwxrwxrwx 1 root root 15 Aug 26 2017 S01uuidd -> ../init.d/uuidd
lrwxrwxrwx 1 root root 18 Sep 1 2017 S01virtlogd -> ../init.d/virtlogd

Nézzünk meg egy példát. Vegyük a Secure Shell Server-t (démont). Az init script a “/etc/init.d/ssh” file-ban található. Ez egy executable – végrehajtható – shell script. Jól látható a 3 db “x” flag.

root@gergo1:~# l /etc/init.d/ssh
-rwxr-xr-x 1 root root 3939 Apr 8 11:51 /etc/init.d/ssh

Nézzük meg a tartalmából az elindításhoz releváns részt.

case "$1" in
start)
check_privsep_dir
check_for_no_start
check_dev_null
log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd" || true
if start-stop-daemon --start --quiet --oknodo --chuid 0:0 --pidfile /run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
stop)
log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd" || true
if start-stop-daemon --stop --quiet --oknodo --pidfile /run/sshd.pid --exec /usr/sbin/sshd; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
reload|force-reload)
check_for_no_start
check_config
log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd" || true
if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /run/sshd.pid --exec /usr/sbin/sshd; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
..
status)
status_of_proc -p /run/sshd.pid /usr/sbin/sshd sshd && exit 0 || exit $?
;;
*)
log_action_msg "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart|try-restart|status}" || true
exit 1
esac

Jól látható, hogy indítását, leállítását, a konfigurációs file-ok “újraolvasását”, továbbá az újraindítását – ez utóbbi nincsen itt forráskódban – mind a “/sbin/start-stop-daemon” rendszerbináris, azaz parancs végzi.

Felhívnám a figyelmet a “reload|force-reload” case ágra. Itt van egy “start-stop-daemon –stop –signal 1” rész. Ez nem más, mint egy olyan “signal” a szerverprocessznek, hogy olvassa újra a konfigurációs file-jait. Ez régebben a UNIX-okon és Linux-okon a “kill -HUP <pid>” volt. Ez a megoldás ezzel ekvivalens. 🙂

Nézzük meg a POSIX signal-okat. 🙂

First the signals described in the original POSIX.1-1990 standard.
Signal Value Action Comment
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
SIGSEGV 11 Core Invalid memory reference
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers
SIGALRM 14 Term Timer signal from alarm(2)
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at terminal
SIGTTIN 21,21,26 Stop Terminal input for background process
SIGTTOU 22,22,27 Stop Terminal output for background process
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

Bővebb – angol nyelvű – leírást az alábbiakban olvashatunk.

https://www.linux.com/news/introduction-services-runlevels-and-rcd-scripts/

Ha beírod root-ként (rendszergazdaként), hogy “runlevel 6“, akkor reboot-ol (újraindul) a Linux-od. 🙂

Ha ki szeretnéd “dobni” az összes felhasználót – és a konzolnál ülsz, hogy nehogy kizárd magad -, akkor a “runlevel 1” – single-user mode (egy felhasználós mód) – lesz a megfelelő parancs. 🙂

Tűzfal (firewall)

A Linux gépeken már régi téma a tűzfal. A tűzfal arra való, hogy védelmet nyújtson a magánhálózatoknak illetve a számítógépeknek az Interneten garázdálkodó rosszakaratú támadók ellen. Éppen ezért beszélhetünk hálózat-biztonságról – erről nálam itthon a router-en lévő tűzfal gondoskodik -, illetve hoszt-biztonságról, ami a Linux notebookom-on van telepítve. Ma már általában egyszerűek a beállítások, mind hálózati, mind hoszt szinten. Debian 10 alatt már automatikus az alap tűzfal-konfiguráció.

Régebben az ipchains volt, ma már az ún. iptables van használatban. Nézzük meg a Linux-unkat!

root@gergo1:~# iptables -L -v
Chain INPUT (policy DROP 590 packets, 93015 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh
256 20230 ACCEPT all -- lo any anywhere anywhere
6008 2038K ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 ACCEPT tcp -- any any 192.168.0.0/24 anywhere state NEW tcp dpt:netbios-ns
0 0 ACCEPT tcp -- any any 192.168.0.0/24 anywhere state NEW tcp dpt:netbios-dgm
0 0 ACCEPT tcp -- any any 192.168.0.0/24 anywhere state NEW tcp dpt:netbios-ssn
0 0 ACCEPT tcp -- any any 192.168.0.0/24 anywhere state NEW tcp dpt:microsoft-ds
0 0 ACCEPT icmp -- any any anywhere anywhere icmp echo-request
6 336 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 6272 packets, 1041K bytes)
pkts bytes target prot opt in out source destination
256 20230 ACCEPT all -- any lo anywhere anywhere

Látható, hogy a bemeneten (INPUT) az SSH szerver, a Samba szerver (Microsoft hálózathoz) és a HTTP szerver van engedélyezve + az ICMP ping (leírása később), továbbá természetesen a már létrejött kapcsolatok is. Forward szinten semmi sincs “átengedve”. Nem továbbítunk adatot hálózatok között. Kimeneten (OUTPUT) pedig mindent “kiengedünk”.

Hogy hol van beállítva? Van egy pici konfigurációs file a /etc alatt.

root@gergo1:~# cat /etc/network/iptables.up.rules
# Generated by iptables-save v1.6.0 on Sat Aug 26 03:40:19 2017
*filter
:INPUT DROP [9:1026]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [22:3482]
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
#
# added by gvamosi on 2019-06-07
#
-A INPUT -s 192.168.0.0/24 -m state --state NEW -p tcp --dport 137 -j ACCEPT
-A INPUT -s 192.168.0.0/24 -m state --state NEW -p tcp --dport 138 -j ACCEPT
-A INPUT -s 192.168.0.0/24 -m state --state NEW -p tcp --dport 139 -j ACCEPT
-A INPUT -s 192.168.0.0/24 -m state --state NEW -p tcp --dport 445 -j ACCEPT
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
#
# added by gvamosi on 2019-09-22
#
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
#
COMMIT
# Completed on Sat Aug 26 03:40:19 2017

És hogyan “töltődik be”? Az ún. init script-ek között kell keresnünk a választ (leírásuk később).

root@gergo1:~# cat /etc/init.d/iptables
#!/bin/sh
echo -n "Applying firewall rules.."
/sbin/iptables-restore < /etc/network/iptables.up.rules
echo "done."

Ez a kicsi init script tölti be a rendszer elindulásakor a tűzfal konfigurációját az iptables-restore parancs segítségével. Ennyi az egész. 🙂

Írhatnánk még az ún. DMZ (Demilitarizált Zóna) fogalmáról is. Ez egy olyan terület egy cégnél pl., ahonnan szerverek “kifelé”, a nagyvilágba, azaz az Internet felé is látszódhatnak. Határzóna a belső, védett, és a külső, védtelen hálózat között.

Ethernet, bridging, switching, routing és a Linux router táblája

Először beszélnünk kell arról, hogy mi az az Ethernet. Az Ethernet a LAN (Local Area Network – helyi hálózat) hálózatokra kidolgozott szabvány. Működésének lényege, hogy hallgatózik az összes résztvevő, és ha “csend” van, akkor küldik az adatokat. Beszélünk ma 100 MBit-es (megabit per másodperc) Ethernetről és GBit-es (gigabit per másodperc) Ethernetről is. Ez az elméleti átviteli maximum, tipikusan a 66%-át lehet elérni rajta. 🙂

https://hu.wikipedia.org/wiki/Ethernet

Ez az a hálózat, ami otthonunkban, munkahelyünkön vagy akár egy kórházban használatos. Van az ún. CAT5-ös kábel, ez a 100 MBit/s -os átvitelhez szükséges UTP (Unshielded Twisted Pair – árnyékolatlan csavart érpár) kábel. Azért csavart – és ez már fizika a javából -, mert így kiegyenlítődnek rajta a zajok. Azért 230-as kábeltől a falban legalább 30-40 centiméterre illik vezetni, tipikusan kábelcsatornában. Plusz feladat, hogy mi az a patch- és a keresztkábel. 🙂

https://hu.wikipedia.org/wiki/UTP

Aztán a hálózati rétegek az ISO-OSI modellből. A 2-es, adatkapcsolati rétegen dolgozik a bridge és a switch is (ha nem layer 3 switch). A router pedig a hármas, hálózati rétegben. A bridge-ek hálózati szegmenseket kötnek össze, MAC-táblát tartanak nyilván. Hasonlóak a repeater-ekhez, bár ez utóbbiak csak jelismétlők (erősítők), és nagyobb távolágok áthidalására használják őket. Az UTP ugyanis 100-120 métert tud csak! A switch-ek több portos bridge-eknek tekinthetőek. 🙂

https://hu.wikipedia.org/wiki/Switch_(informatika)

Linux-unkkal akár bridge-elhetünk, akár switch-elhetünk, sőt még route-olhatunk is! Csak megfelelő interfészeket kell a “dobozba” tenni. A gyakorlatban egyébként ez is történik, csak kész eszközöket használunk, amik azért kisebbek egy PC-nél, és kevesebbet is fogyasztanak. Belsejükben Linux dolgozik. 🙂

Az én itthoni hálózatomban egy kábelmodemből egy router-be érkezik a jel. A router GigaBit-es Ethernet interfészekkel, két sávú WLAN-nal (vezeték nélküli hálózat) rendelkezik. Az egyik helységben van egy switch is, ami elosztóként működik, akár egy 230 V-os elosztó. 🙂 Van még egy konnektorba dugható picike Wi-Fi lefedettség növelőm, az emeletre – és nagyjából ennyi. Asztali gépek, hordozható számítógépek, tabletek, okostelefonok és az aktív és passzív hálózati eszközök (kábelek). 🙂

Összességben elmondható, hogy a Layer 2-es eszközök fizikai, Ethernet MAC-cím (Media Access Control) alapján végzik az összekapcsolást, a router-ek pedig IP-címeket adnak, tipikusan DHCP-vel (Dynamic Host Configuration Protocol), azaz automatikusan kiosztanak minden hálózati résztvevőnek egy (helyi) IP-címet, továbbá a Layer 3-ban “operálnak”. Ha megnézzük a tegnapi írást a hálózatról és az IP-címről, akkor volt ott egy ifconfig parancs, ami kíírta, hogy a Wi-Fi interfésznek “ether 5c:e0:c5:5d:e2:01” a fizikai, gyárilag beállított címe. Ez a MAC-cím. 🙂

https://hu.wikipedia.org/wiki/MAC-c%C3%ADm

Nézzük meg ezek után a Debian 10-es Linux-om router tábláját. Ezt root-ként (rendszergazdaként) érhetjük el, a route paranccsal. Mára jobbára automatikusan beállítódik minden Linux-on.

root@gergo1:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 600 0 0 wlp2s0
link-local 0.0.0.0 255.255.0.0 U 1000 0 0 wlp2s0
192.168.0.0 0.0.0.0 255.255.255.0 U 600 0 0 wlp2s0

Látható a cél, a gateway, a netmaszk, pár adat és az interfész. Ami itt van az egy “sima” hálózatba kötés, Wi-Fi-n keresztül. A netmaszkról lehetne beszélnünk. Binárisan ÉS kapcsolattal az egy IP-alhálózathoz való tartozást fejezi ki, egyszerűen hozzá kell ÉS-elni az IP-címhez. A gateway-ról is szóljunk. Ez nem más, mint az átjárónk, azaz a router-ünk. IP-címe jelen esetben 192.168.0.1. Ezt ki is deríthetjük egyrészt a route -n, másrészt a traceroute parancs kimenetéből – miután apt-get install paranccsal felinstalláltuk. Keressük meg tehát a nic.bme.hu-t, a BME elsődleges DNS szerverét (Domain Name System). 🙂

root@gergo1:~# traceroute 152.66.115.1
traceroute to 152.66.115.1 (152.66.115.1), 30 hops max, 60 byte packets
1 _gateway (192.168.0.1) 7.562 ms 7.526 ms 7.575 ms
..
7 tg0-2-0-3-1110.rtr.bme.hbone.hu (195.111.103.205) 22.009 ms 25.032 ms 25.496 ms
8 xge0-0-0-0.rax.net.bme.hu (152.66.0.124) 32.333 ms 32.308 ms 32.283 ms
9 hge1-0-49.rio.net.bme.hu (152.66.0.67) 26.305 ms 27.216 ms 26.405 ms
10 nic.bme.hu (152.66.115.1) 29.336 ms 29.489 ms 30.286 ms

A DNS egyébként a névfeloldást végzi az Interneten. Egy szervernévhez szolgáltatja a hozzá tartozó IP-címet elosztott adatbázisból.

Általában igaz, hogy egy számítógép hálózatba kacsolásához IP-cím, netmaszk (ebből jön a hálózat-cím, ÉS kapcsolattal), a gateway és egy-két DNS-szerver szükséges. 🙂