לומדים לינוקס
322 subscribers
3 links
Download Telegram
ניהול וניטור השרת על ידי קוקפיט
https://cockpit-project.org/

כדי למצוא באגים שנמצאים במעבד ולא תוקנו
$ cat /proc/cpuinfo | grep bugs

תיקיית /proc מכילה מידע על התהליכים שרצים במערכת, כל תהליך מקבל תיקייה, שם התיקייה הוא מספר התהליך, ניתן לתשאל את התיקייה

שני כלים לניטור התעבורה במערכת, iftop and nethoge שניהם מציגים איזה תוכנה שולחת כמה ומתי.

בכדי לדבג תהליך ניתן להריץ את journalctl _PID=1233 כשהמספר הוא מספר התהליך
בכדי לחקור מעט יותר תוכניות exec בלינוקס אפשר להשתמש בפקודת strings שישלוף מהבינרי את כל המחרוזות שהוא מכיל, לדוגמה
strings /proc/1/exe
לקבל מידע על החומרה שבמחשב dmidecode, lshw

כל מערכת הפעלה פועלת על חומרה ממנה בנוי המחשב, בכדי לקבל את המידע על חומרת המחשב ישנה טבלה שמחזיקה את כל הערכים דבר הנקרא SMBIOS בעבר זה נקרא DMI ושם לינוקס נמצאת, את המידע אפשר להשיג על ידי פקודת dmidecode

בהרצה פשוטה הפקודה תחזיר מלל ארוך מאוד בקשר לכל הידוע לה על החומרה, כדי לקבל את המידע הרלוונטי שאנו מחפשים על המערכת אפשרי להשתמש בדגלים -t או -s כשהראשון מאפשר לנו לחפש לפי type והשני לפי מחרוזת

להלן דוגמאות
$ sudo dmidecode -s chassis-manufacturer 
ASUSTeK COMPUTER INC.

$ sudo dmidecode -s processor-version
Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz

$ sudo dmidecode -t bios
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 3.0.0 present.

Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
Vendor: American Megatrends Inc.
...

כלי נוסף שמציג מידע על המערכת הוא lswh, בשביל לא לטבוע בכמות המידע אפשר לפלטר את הפלט על ידי שימוש בקטגוריה (Class) של החלק שמעניין אותנו, לדוגמה
$ sudo lshw -C CPU
*-cpu
description: CPU
product: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
vendor: Intel Corp.
physical id: 11

או להשתמש עם דגל -short שיציג תצוגה מקוצרת שמחולקת לפי קטגוריות
$ sudo lshw -short
H/W path Device Class Description
======================================================
system X556URK
/0 bus X556URK
/0/0 memory 64KiB BIOS
אחסון smarctl, lsblk

בכדי לקבל רשימה ויזואלית של התקני האחסון שקיימים במערכת ותצוגת המחיצות שלהם ניתן להריץ את lsblk, כך ניתן לדעת איזה התקן מעוגן לאיזה סוקט
$ lsblk
...
sda 8:0 0 238.5G 0 disk
├─sda1 8:1 0 260M 0 part /boot/efi
├─sda2 8:2 0 16M 0 part
├─sda3 8:3 0 79.4G 0 part
...

בכל דיסק מודרני ישנה מערכת שמספקת נתונים על בריאות הדיסק ואם הוא לקראת סוף חייו נקרא בימינו smart בכדי לקבל נתונים על הדיסק אותו אנו רוצים לחקור ניקח את שם הדיסק ונעביר לתוכנת smartctl שהיא בעצם תוכנה שיודעת לבדוק את הדיסק לקבל את הנתונים ולתת אינפורמציה על הדיסק

דגל -i יתן מידע על החומרה עצמה ואם היא תומכת ב SMART
$ sudo smartctl -i /dev/sda

תגית short מסמלת טסט מקוצר
$ sudo smartctl -t short /dev/sda

ניתן לחזור לבדוק תוצאות לאחר הבדיקה על ידי -l
לייבל devstat יחזיר נתונים חשובים על הדיסק, טמפרטורה, כמות reboots שהדיסק עשה ועוד
$ sudo smartctl -l devstat /dev/sda

לייבל xerror יחזיר את השגיאות מהבדיקה שנעשתה
$ sudo smartctl -l xerror /dev/sda
לייבל selftest יציג סיכום של הבדיקה
$ sudo smartctl -l selftest /dev/sda
גראב וקרנל

הקרנל הוא החלק הכי נמוך במערכת שמתקשר עם החומרה, ניתן להרחיב את הקרנל עם מודולים וכך להרחיב את התמיכה של לינוקס בחומרה נוספת.

כל עדכון של קרנל שומר את הגרסאות האחרות שהיו במערכת.
גראב הוא התהליך שמנהל את עליית המערכת, הוא בוחר עם איזה קרנל לעלות ועם אלו הגדרות, בכדי לערוך את גרסת הקרנל שאיתה המערכת תעלה ניתן לבחור בתפריט עליית הגראב "מתקדם" ושם לבחור קרנל מהרשימה.
דרך קבועה יותר(?) שתעלה את המערכת לקרנל מסויים היא להקיש C בתפריט הגראב ובקובץ שנפתח לשנות את ערך הקרנל לגרסה ישנה.

נהוג לשמור 2 גרסאות קרנל דבר שהמערכת תעשה לבד על ידי הרצה של
# Ubuntu
$ apt —purge autoremove

# CentOS
$ rpm -q kernel
$ yum install yum-utils
$ package-cleanup —oldkernels —count=2

שינוי ברירת מחדל של עליית המערכת נעשה על ידי עריכת הקובץ
/etc/default/grub
ושינוי הערך המספרי של GRUB_DEFAULT=0 לאינדקס הרצוי
בניית חבילת deb ו-repo
בצורה הבסיסית ביותר

בניה של חבילה להפצות מבוססות debian נעשית על ידי יצירת ההיררכיה הבאה כשהבינרי אותו אנו רוצים לארוז נמצא בתיקיית bin במקרה שלי זה הקובץ mycode
test
├── DEBIAN
│ └── control
└── usr
└── bin
└── mycode

הקובץ control מכיל את הוראות האריזה ולאיזה ארכיטקטורה, הוא נראה כך
Package: mycode
Version: 1.0
Section: custum
Priorty: optional
Architecture: all
Essential: no
Installed-size: 1024
Maintainer: any@email.com
Description: POC

הרצה של הפקודה הבאה תיצור לנו קובץ deb במיקום בו הרצנו, כשהערך test הינו התיקייה בה נמצא הקוד והוראות האריזה
$ dpkg-deb --build test

בכדי ליצור repo עצמאי ניצור תיקיית debian בתיקיית השרת ונעתיק לשם את קובץ ה-deb אותו ארזנו, הרצה של הפקודה הבאה תאגד את חבילות הdeb שזמינות בשרת
$ cd /var/www/html/debian
$ dpkg-scanpackages . | gzip -c9 > Packages.gz

כעת אפשרי להוסיף את ה-repo הזה מכל מחשב אחר, כדי להוסיף את ה-repo לרשימת המקורות של המחשב כל שיש לעשות הוא להוסיף את השורה הבאה (וזה בהנחה שהמקור אכן מהימן)
deb [trusted=yes] https://myrepo_address/debian ./
לקובץ המקורות של המערכת הלא הוא
/etc/apt/sources.list

רק לרענן את מנהל החבילות עם sudo apt update וניתן להתקין את החבילה שיצרנו כמו כל חבילה אחרת
👍1
לקבל מידע על המערכת

פקודת hostnamectl מאפשרת לנו לקבל מידע על המערכת שאנו רצים ממנה, סוג הוירטואליזציה אם ישנה, איזו גרסה היא, גרסת קרנל, ארכיטקטורה ועוד נתונים מעניינים

$ hostnamectl
Static hostname: home
Icon name: computer-desktop
Chassis: desktop
Machine ID: 3409d191261833093f3d3a64c8eac6bd
Boot ID: 63763ffab2a9432490a5bbffd272ee65
Operating System: Ubuntu 20.04 LTS
Kernel: Linux 5.4.0-40-generic
Architecture: x86-64


@learnlinuxnote
קובץ /etc/shadow
והגדרות ברירת מחדל


קובץ /etc/shadow מכיל את שמות המשתמשים שבמערכת ואת המידע עליהם, אם נפתח את הקובץ שורות יראו בצורה מבולגנת מאוד, להלן הסבר מה נמצא ומה הוא אומר.

כך נראות הקובץ, כפי שניתן לראות לא כל משתמש הכוונה ליוזר ממשי אלא ליוזר בהגדרת המערכת

$ sudo tail /etc/shadow
...
nvidia-persistenced:*:18364:0:99999:7:::
libvirt-qemu:!:18373:0:99999:7:::
libvirt-dnsmasq:!:18373:0:99999:7:::
user:$6$X.69XaHtriY5x.SZ$Dj4aF9ebhQxn6Sr5DlVjUpJ4TPp7gpIsnugMV8gSJEHA01h4BwymJJgeZ4JzlBGhZJ/SxPnbZZC7a5K/f3di01:18382:0:99999:7:::

נתחיל בזה שמדובר על שורה של ערכים בהם כל ערך מופרד על ידי :, לשם הדוגמה אני בוחר להדגים על משתמש "אמיתי" שממלא כמעט את כל הערכים.

אם כן מה יש לנו

1.
user:
2. $6$X.69XaHtriY5x.SZ$Dj4aF9ebhQxn6Sr5DlVjUpJ4TPp7gpIsnugMV8gSJEHA01h4BwymJJgeZ4JzlBGhZJ/SxPnbZZC7a5K/f3di01:
3. 18382:
4. 0:
5. 99999:
6. 7:
7. :
8. :

ולהלן ההסבר

1.
שם המשתמש
2. חלק זה מורכב מ3 חלקים שמופרדים בנקודה $type$salt$hashed
הראשון type סוג ההצפנה בה הסיסמה מוצפנת, להלן מפתח
$1$ – MD5
$2a$ – Blowfish
$2y$ – Eksblowfish
$5$ – SHA-256
$6$ – SHA-512

השני salt הוא מידע נוסף שנועד לחזק את ההצפנה.
השלישי hashed גיבוב הטקסט של ההצפנה.
סימן קריאה או כוכבית במיקום הסיסמה, מסמל שהסיסמה אינה תקינה.
3. תאריך שינוי אחרון של הסיסמה (מספר הימים מ1970)
4. מספר הימים שחייבים לעבור כדי שהמשתמש יוכל להחליף את הסיסמה שלו.
5. פג התוקף של הסיסמה (ימים)
6. מספר ימים לפני פג התוקף בהם תוצג הזהרה למשתמש.
7. מספר הימים שחשבון המשתמש יחסם לאחר שסיסמת המשתמש פגה.
8. הזמן בו החשבון נחסם

את המידע המעניין הזה נוכל לראות ולערוך על ידי הרצת הפקודה הבאה

$ chage -l user
Last password change : 12 19, 2019
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7


בכדי לקבוע ערכי ברירת מחדל לכל משתמש חדש שיוצר, ניתן לערוך את הקובץ הבא

$ less /etc/login.defs
...
# Password aging controls:
PASS_MAX_DAYS 99999
PASS_MIN_DAYS 0
PASS_WARN_AGE 7
...


לינוקס מספקת לנו אפשרות להגדיר ערכי ברירת מחדל לכל משתמש שיווצר, כפי הערכים שמוגדרים בקובץ /etc/login.defs, כדי לראות אלו הגדרות ברירת מחדל יש ליצירת משתמש.

$ sudo useradd -D
[sudo] password for myuser:
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/sh
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no

קובץ זה של הגדרות ברירת המחדל ממוקם בנתיב של כל הגדרות ברירת המחדל של כלי המערכת /etc/default/ תחת שם הפקודה useradd

@learnlinuxnote
👍1
רישום למערכת
אתחול מעטפת

ישנן שני אפשרויות כניסה של משתמש למערכת, האחת טוענת את כל הסביבה של המשתמש, ומוכרת בשם login shell.
והאחרת פשוט מחליפה את המשתמש אבל לא טוענת את כל הסביבה, מוכרת בשם non login shell.

כניסה רגילה למערכת טוענת את כל סביבת המעטפת, ומחפשת לטעון את הקבצים שברשימה אם הם קיימים, ברגע שאחד מהם זוהה האחרים לא יטענו פרט לקובץ /etc/bashrc שיטען תמיד

/etc/profile
~/.bash_profile
~/.bash_login
~/.bashrc

מצד שני אם מחליפים משתמש על ידי su לא כל הסביבה של המשתמש שהוחלף נטענת, והקבצים שיטענו הן רק

/etc/bashrc
~/.bashrc

בכדי לטעון משתמש אחר עם su ולטעון את כל הסביבה שלו ציך לציין זאת במפורש על ידי דגל -l או על ידי הקיצור שלו שמוכר יותר su -

$ su -l
$ su -

אם כן למדנו טריק נחמד, ברגע שרוצים לטעון מחדש את סביבת המשתמש בלי לעשות login logout, ניתן פשוט להריץ

$ su - user

ישנן עוד השפעות non shell login כגון משתני סביבה שלא מוגדרים ועוד
עוד מידע בנושא ניתן למצוא ב man bash INVOCATION

@learnlinuxnote
👍1
לקבל את רשומי המערכת getent

לינוקס מלאה בקבצים שמכילים מידע על משתמשים, תהליכים, הגדרות וכו', במקום לרוץ ולאסוף את כל המידע הזה ולזכור היכן הוא ממוקם ישנה פקודה שמנגישה את המידע, קובץ ההגדרות נמצא בנתיב /etc/nsswitch.conf ומאפשר להגדיר מהיכן לאסוף את המידע, להלן רשימת המידע אותו היא מספקת ברירת מחדל

$ getent --help
...
Supported databases:
ahosts ahostsv4 ahostsv6 aliases ethers group gshadow hosts initgroups
netgroup networks passwd protocols rpc services shadow
...

בכדי לקבל מידע במלואו ניתן להריץ

$ getent hosts 
127.0.0.1 localhost
192.168.39.12 myrancher.com
178.62.121.30 playground


או לבחור לקבל מידע על ערך ספציפי

$ getent services 67
bootps 67/udp

$ getent services git
git 9418/tcp

@learnlinuxnote
לינוקס וקבצים lsof

אנו מכירים את הכלל בלינוקס לפיו כל אובייקט הוא קובץ, לכן כלי שעוקב אחרי קבצים במערכת הוא כלי נורא חשוב, נעים להכיר פקודת lsof

פקודת lsof היא בעצם פקודה שבודקת קבצים, אבל במונח הרחב יותר היא בעצם מספקת כלי בדיקה להרבה חלקים מהמערכת (הכל קבצים זוכרים), רוצים לבדוק לאיזה מקום תהליך מסויים רושם את הלוגים שלו? או לחילופין איזה תהליך מאזין לאיזה פורט? הפקודה מציגה את כל אלו ומאפשרת לשלב בין היכולות השונות כדי לפלטר את המידע

לדוגמה אנו רוצים לקבל מידע על כל תהליך שרץ במערכת

$ lsof
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 8,1 4096 2 /
systemd 1 root rtd DIR 8,1 4096 2 /
systemd 1 root txt REG 8,1 1698400 1842178 /usr/lib/
...
...

הרבה מהמידע שמוצג נראה ג'בריש ולא ברור להלן הסבר קצר על שתי עמודות חשובות שישפוך קצת אור על הנושא
עמודת FD מציגה תיאור על הקובץ המדובר (קיצור של File Descriptor)

cwd: current working directory
err: FD information error
ltx: shared library text (code and data)
Mxx: hex memory-mapped type number xx.
m86: DOS Merge mapped file
mem: memory-mapped file
mmap: memory-mapped device
pd: parent directory
rtd: root directory
txt: program text (code and data)
v86: VP/ix mapped file

לעמודה הזאת יש עוד סוג של מידע שנראה ממש מוזר
99r
104w
113u

ובעצם בא לספר לנו באלו הרשאות נפתח אותו הקובץ על ידי התהליך

r: read
w: write
u: read & write

עמודת TYPE מציגה את סוג הקובץ עליו אנו מסתכלים, הסוגים הנפוצים

DIR = תיקייה
REG = קובץ רגיל
CHR = קובץ בעל תווים מיוחדים
FIFO = קובץ pipe

אז מה בעצם אפשר לעשות עם פקודת lsof?

תהליך
שימוש בדגל p יאפשר לחקור לאלו קבצים תהליך מסוים ניגש ועם אלו הרשאות

$ lsof -p 1
OMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
dumb-init 1 root cwd DIR 0,54 4096 9964742 /
dumb-init 1 root rtd DIR 0,54 4096 9964742 /
dumb-init 1 root txt REG 0,54 54744 9
309915 /u...
dumb-init 1 root mem REG 8,1 9309915 /usr/bin/...
...


פקודה
שימוש בדגל c יאפשר לקבל רק מידע שקשור לפקודה לסויימת

$ lsof -c firefox

תקשורת
שימוש בדגל i יאפשר לראות קבצים ותהליכים פונים לרשת

$ lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
kdeconnec 2292 user 11u IPv6 49368 0t0 UDP *:1716
kdeconnec 2292 user 12u IPv6 49369 0t0 TCP *:1716 (LISTEN)



פילטר
פקודת lsof מאפשרת ליצור מגוון פילטרים על המידע אותו אנו מבקשים, להלן כמה שימושיים במיוחד

כל התהליכים שמשתמשים בפרוטוקול מסויים ועוברים דרך פורט 80
דרך טווח של פורטים (300-1000)
דומיין מסויים (@whatsapp.com)
וכמובן ניתן ליצור קומבינציות משולבות של פילטרים

$ lsof -i TCP:80
$ lsof -i UDP:3000-10000
$ lsof -i @whatsapp.com

תאחזר את כל הקבצים אליהם ניגש משתמש מסויים (-u)
כל המשתמשים האחרים חוץ ממשתמש מסויים (^)
אלו קבצים בתיקייה הנוכחית פתוחים על ידי איזה תהליך (+D)

$ lsof -u user
$ lsof -u ^root
$ lsof +D Project/test/

לסיכום זאת רק טעימה, יש עוד הרבה אפשרויות שהכלי מספק
כדאי לעבור על הman שלו ולראות עוד אלו הפתעות הוא מחזיק בשרוול

@learnlinuxnote
👎1
Forwarded from ToCode
# על ההבדל בין -c ו -s ב su ו runuser
הפקודות su ו runuser נועדו כדי שנוכל להחליף משתמש או להריץ פקודות בתור משתמש אחר. ב su אנחנו משתמשים כדי לעבור ממשתמש רגיל למשתמש רגיל אחר, וב runuser נשתמש כדי לעבור ממנהל מערכת למשתמש רגיל. בשתי הפקודות האפשרויות -c ו -s משמשות לבחירת התוכנית שצריך להפעיל. בואו נראה את ההבדלים ביניהן.

## חיבור בתור משתמש אחר
פקודת su או runuser תפעיל את shell ברירת המחדל של המשתמש אליו אנחנו עוברים אם לא נציין במפורש פקודה אחרת. לכן אם אני משתמש מנהל מערכת ורוצה לעבור למשתמש postgres כדי לנהל בסיס נתונים אוכל להפעיל:

runuser - postgres


וכן רבים מאיתנו ישתמשו ב su כי זה יותר קצר:

su - postgres


ההבדל בין השתיים הוא ש runuser לא כוללת מנגנון אימות למשתמש ולכן רק מנהל מערכת יכול להפעיל אותה, ונועדה להפעלה על מערכות SELinux במקומות שיש הגבלות על הפעלת su.

## הפעלת תוכנית בתוך ה Shell הדיפולטי של משתמש אחר
אבל לא באנו לדבר על runuser אלא בשביל לדבר על שתי האפשרויות הנוספות של su (ולכן גם של runuser), לבחירת תוכנית להרצה או לבחירת Shell.

נתחיל בתוכנית להרצה: הרבה פעמים בסקריפטים אנחנו לא צריכים Shell אינטרקטיבי ומספיק לנו להריץ תוכנית ספציפית בתור משתמש אחר. במצב כזה נוכל להשתמש ב -c כדי להעביר את הנתיב לתוכנית ואת הפרמטרים שאנחנו רוצים להעביר. התוכנית תופעל מתוך ה Shell הדיפולטי של המשתמש ולכן אפשר להעביר גם משתנים והם יפוענחו בתוך הקונטקסט של המשתמש. הנה כמה דוגמאות:

root@60275c574ad5:/# runuser -c 'echo $USER' - postgres
postgres
root@60275c574ad5:/# runuser -c 'echo $HOME' - postgres
/var/lib/postgresql
root@60275c574ad5:/# runuser -c "python3 --version" - postgres
Python 3.8.5


בכל המקרים הרצת su -c לא טוענת את התוכן של ~/.bashrc או ~/.profile בגלל שמדובר ב Shell לא אינטרקטיבי.

## הפעלת Shell חלופי
במקרים אחרים נרצה להתחבר בתור משתמש שלא מוגדרת עבורו Default Shell. שימו לב לשורה הבאה מתוך הקובץ /etc/passwd:

irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin


המשתמש irc הוא משתמש פיקטיבי שנועד רק לצורך הפעלת ה IRC Daemon על המכונה. בגלל זה ה Shell שלו מוגדרת להיות nologin. ניסיון להתחבר בתור משתמש זה באמצעות runuser לא יצליח:

root@60275c574ad5:/# runuser - irc
runuser: warning: cannot change directory to /var/run/ircd: No such file or directory
This account is currently not available.


במצב כזה אנחנו צריכים לשנות את ה Shell באופן זמני רק עבור הפעלת ה runuser הספציפית, ואת זה עושים עם -s:

root@60275c574ad5:/# runuser -s /bin/bash - irc
runuser: warning: cannot change directory to /var/run/ircd: No such file or directory
irc@60275c574ad5:/$


למרות שאין תיקיית בית לעבור עליה, ולמרות שאין Default Shell, עדיין הצלחתי לקבל Shell אינטרקטיבי עם המשתמש irc.
👍2
לקפוץ מעל jumpbox

בלא מעט מערכות יש נוהל אבטחה שאין גישת ssh ישירה לשרת, אלא יש מכונה אחת שמורשת להתחבר לשרת ב ssh וכל מי שרוצה להתחבר לשרת חייב לעבור בדרך זו, המושג הזה ברשת מוכר בשם מכונת jumpbox

אוקי אז יש לנו מכונה jumpbox ואנו רוצים להתחבר אליה, המסלול שנצטרך לעבור הוא כזה

1. העתקה של המפתח הציבורי שלנו למכונת ה jumpbox
2. העתקת מפתח של מכונת ה jumpbox לשרת אליו אנו רוצים להתחבר

ואז לבצע את אותה הדרך עם חיבורי ssh
התחברות ssh לשרת ה jumpbox
התחברות נוספת משרת הjumpbox לשרת

נשמע ארוך לא?

במקום זאת אפשר להשתמש בתכונה של ssh ולהגדיר לו רצף של מכונות שבכולן הוא ישתמש באותו מפתח פרטי כדי להזדהות במידה ויש לנו מפתח ציבורי במכונה נוכל להמשיך למכונת היעד, זה נראה כך

ssh -J myuser@jumpbox myuser@isolated.server

אנו משתמשים בדגל -J כדי להכריז מהי מכונת ה jumpbox שלנו, ולאחר מכן לאיזה שרת אנו רוצים להתחבר דרכה, ssh הולך למכונה הראשונה מכונת ה jumpbox ומנסה למצוא התאמה בין המפתח הציבורי שנמצא במכונה למפתח הפרטי שנמצא אצלנו על המחשב

במידה והמפתח הציבורי שלנו נמצא במכונה, ssh יעבור למכונה הבאה דרך מכונת ה jumpbox וינסה להתחבר ממכונת ה jumpbox לשרת, אם המפתח הציבורי שלנו נמצא גם על השרת, ssh יבדוק התאמה של המפתח הציבורי מול המפתח הפרטי שנמצא על המחשב שלנו ונוכל לעבוד על השרת בצורה "ישירה"

#ssh
#jumpbox

@learnlinuxnote
👍3