Si të filloni të përdorni modalitetin e përdoruesit në Linux

Hyrje nga përkthyesi: Në sfondin e hyrjes masive në jetën tonë të llojeve të ndryshme të kontejnerëve, mund të jetë mjaft interesante dhe e dobishme të zbuloni se me çfarë teknologjish filloi gjithçka. Disa prej tyre mund të përdoren në mënyrë të dobishme edhe sot e kësaj dite, por jo të gjithë i mbajnë mend metoda të tilla (ose e dinë nëse nuk u kapën gjatë zhvillimit të tyre të shpejtë). Një teknologji e tillë është User Mode Linux. Autori i origjinalit bëri shumë gërmime, duke kuptuar se cilat prej zhvillimeve të vjetra funksionojnë ende dhe cilat jo, dhe bashkoi diçka si një udhëzim hap pas hapi se si të merrni një UML homebrew në 2k19. Dhe po, ne e ftuam autorin e postimit origjinal në Habr Kejdi, kështu që nëse keni ndonjë pyetje - pyesni në anglisht në komente.

Si të filloni të përdorni modalitetin e përdoruesit në Linux

Modaliteti i përdoruesit në Linux është, në fakt, një port i kernelit Linux për veten e tij. Kjo mënyrë ju lejon të ekzekutoni një kernel të plotë Linux si një proces përdoruesi dhe përdoret zakonisht nga zhvilluesit për të testuar drejtuesit. Por kjo mënyrë është gjithashtu e dobishme si një mjet për izolimin e përgjithshëm, parimi i të cilit është i ngjashëm me funksionimin e makinave virtuale. Ky modalitet ofron më shumë izolim se Docker, por më pak se një makinë virtuale e plotë si KVM ose Virtual Box.

Në përgjithësi, "Modaliteti i përdoruesit" mund të duket si një mjet i çuditshëm dhe i vështirë për t'u përdorur, por ka përdorimet e veta. Në fund të fundit, ky është një kernel Linux i plotë që funksionon si një përdorues i paprivilegjuar. Kjo veçori lejon që kodi potencialisht i pabesueshëm të ekzekutohet pa ndonjë kërcënim për makinën pritëse. Dhe meqenëse ky është një kernel i plotë, proceset e tij janë të izoluara nga makina pritës, d.m.th. proceset që ekzekutohen brenda modalitetit të përdoruesit nuk do të jenë të dukshme për hostin. Kjo nuk është si një kontejner tradicional Docker, në të cilin makina pritës i sheh gjithmonë proceset brenda ruajtjes. Shikoni këtë pjesë të pstree nga një prej serverëve të mi:

containerd─┬─containerd-shim─┬─tini─┬─dnsd───19*[{dnsd}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─aerial───21*[{aerial}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─s6-svscan───s6-supervise
           │                 │      └─surl
           │                 └─9*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─h───13*[{h}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─goproxy───14*[{goproxy}]
           │                 └─9*[{containerd-shim}]
           └─32*[{containerd}]

Dhe krahasojeni këtë me pstree të kernelit Linux në modalitetin e përdoruesit:

linux─┬─5*[linux]
      └─slirp

Kur punoj me kontejnerët Docker, mund të shoh nga hosti emrat e proceseve që janë duke u ekzekutuar në mysafir. Me modalitetin e përdoruesit Linux, kjo nuk është e mundur. Çfarë do të thotë? Kjo do të thotë se mjetet e monitorimit që kalojnë përmes nënsistemit të auditimit të Linux nuk shoh proceset që funksionojnë në sistemin e mysafirëve. Por në disa situata kjo veçori mund të jetë një thikë me dy tehe.

Në përgjithësi, i gjithë postimi më poshtë është një koleksion kërkimesh dhe përpjekjesh të përafërta për të arritur rezultatin e dëshiruar. Për ta bërë këtë, më duhej të përdorja mjete të ndryshme të lashta, të lexoja burimet e kernelit, të bëja korrigjimin intensiv të kodit të shkruar në ditët kur isha ende në shkollën fillore dhe gjithashtu të ndërtoj ndërtimet e Heroku duke përdorur një binar të veçantë për të gjetur mjetet që më duheshin. . E gjithë kjo punë bëri që djemtë në IRC-në time të më quajnë magji. Shpresoj që ky postim të shërbejë si dokumentacion i besueshëm për dikë që të provojë të njëjtën gjë me kernelet më të reja dhe versionet e OS.

rregullim

Vendosja e modalitetit të përdoruesit Linux kryhet në disa hapa:

  • instalimi i varësive nga hosti;
  • shkarkimi i kernelit Linux;
  • konfigurimi i ndërtimit të kernelit;
  • montimi i kernelit;
  • instalim binar;
  • konfigurimi i sistemit të skedarëve të ftuar;
  • përzgjedhja e parametrave të nisjes së kernelit;
  • krijimi i një rrjeti të ftuar;
  • duke filluar kernelin e mysafirëve.

Unë supozoj se nëse vendosni ta bëni vetë, me shumë mundësi do të bëni gjithçka që përshkruhet në ndonjë sistem të ngjashëm me Ubuntu ose Debian. Unë u përpoqa të zbatoja të gjitha sa më sipër në shpërndarjen time të preferuar - Alpine, por asgjë nuk doli prej saj, me sa duket për shkak të faktit se kerneli Linux ka një glibc-izma të detyrueshme për drejtuesit në modalitetin e përdoruesit. Kam në plan ta raportoj këtë në rrjedhën e sipërme pasi ta kuptoj më në fund problemin.

Instalimi i varësive nga hosti

Ubuntu kërkon të paktën paketat e mëposhtme për të ndërtuar kernelin Linux (duke supozuar një instalim të pastër):

- 'build-essential'
- 'flex'
- 'bison'
- 'xz-utils'
- 'wget'
- 'ca-certificates'
- 'bc'
- 'linux-headers'

Ju mund t'i instaloni ato duke përdorur komandën e mëposhtme (si rrënjë ose duke përdorur sudo):

apt-get -y install build-essential flex bison xz-utils wget ca-certificates bc 
                   linux-headers-$(uname -r)

Vini re se ekzekutimi i programit të konfigurimit të menusë së kernelit Linux do të kërkojë instalimin e libncurses-dev. Ju lutemi sigurohuni që të jetë instaluar duke përdorur komandën e mëposhtme (si root ose duke përdorur sudo):

apt-get -y install libncurses-dev

Shkarkimi i kernelit

Përcaktoni se ku të shkarkoni dhe më pas ndërtoni kernelin. Do t'ju duhet të ndani afërsisht 1,3 GB hapësirë ​​në hard disk për këtë operacion, prandaj sigurohuni që ta keni atë.

Pasi shkoni në kernel.org dhe merrni URL-në për të shkarkuar versionin më të fundit të kernelit të qëndrueshëm. Në momentin e shkrimit të këtij postimi: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Shkarkoni këtë skedar duke përdorur 'wget':

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Dhe ekstraktoni me 'tar':

tar xJf linux-5.1.16.tar.xz

Tani futemi në drejtorinë e krijuar kur shpaketojmë tarballin:

cd linux-5.1.16

Konfigurimi i ndërtimit të kernelit

Sistemi i ndërtimit të kernelit është një grup Skedarët e krijuar с shumë mjetet dhe skriptet e personalizuara për të automatizuar procesin. Së pari, hapni programin e konfigurimit interaktiv:

make ARCH=um menuconfig

Ai do të ndërtojë dhe shfaq pjesërisht një kuti dialogu për ju. Kur '[Select]', do të mund të konfiguroni duke përdorur tastet Space ose Enter. Lundroni në dritare, si zakonisht, me shigjetat e tastierës "lart" dhe "poshtë", dhe zgjidhni elementët - "majtas" ose "djathtas".

Treguesi i pamjes —> do të thotë që jeni në një nënmenu, ku aksesohet duke shtypur tastin Enter. Rruga për të dalë prej saj është padyshim përmes '[Exit]'.

Përfshi opsionet e mëposhtme në '[Select]' dhe sigurohuni që të ketë një simbol '[*]' pranë tyre:

UML-specific Options:
  - Host filesystem
Networking support (enable this to get the submenu to show up):
  - Networking options:
    - TCP/IP Networking
UML Network devices:
  - Virtual network device
  - SLiRP transport

Kjo është e gjitha, ju mund të dilni nga kjo dritare duke zgjedhur në mënyrë sekuenciale '[Exit]'. Vetëm sigurohuni që ju kërkohet të ruani konfigurimin në fund dhe zgjidhni '[Yes]'.

Unë ju rekomandoj të luani me opsionet e ndërtimit të kernelit pasi të keni lexuar këtë postim. Nga këto eksperimente mund të mësoni shumë për mënyrën se si funksionon mekanika e kernelit të nivelit të ulët dhe se si flamuj të ndryshëm ndikojnë në ndërtimin e kernelit.

Ndërtimi i kernelit

Kerneli Linux është një program i madh që bën shumë gjëra. Edhe me një konfigurim kaq minimal në harduerin e vjetër, mund të duhet mjaft kohë për t'u ndërtuar. Pra, ndërtoni kernelin me komandën e mëposhtme:

make ARCH=um -j$(nproc)

Per cfare? Kjo komandë do t'i tregojë ndërtuesit tonë që të përdorë të gjitha bërthamat dhe fijet e disponueshme të CPU-së në procesin e ndërtimit. Ekipi $(nproc) në fund të Build zëvendëson daljen e komandës nproc, e cila është pjesë coreutils në një ndërtim standard të Ubuntu.

Pas ca kohësh, kerneli ynë do të përpilohet në një skedar të ekzekutueshëm ./linux.

Instalimi i binarit

Meqenëse Modaliteti i Përdoruesit në Linux krijon një binar të rregullt, mund ta instaloni atë si çdo mjet tjetër. Ja si e bëra:

mkdir -p ~/bin
cp linux ~/bin/linux

Gjithashtu ia vlen të siguroheni për këtë ~/bin është në tuajën $PATH:

export PATH=$PATH:$HOME/bin

Konfigurimi i sistemit të skedarëve të ftuar

Krijo një direktori për sistemin e skedarëve të ftuar:

mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix

Hapni alpinelinux.org dhe brenda seksioni i shkarkimit gjeni lidhjen aktuale të shkarkimit MINI ROOT FILESYSTEM. Në kohën e shkrimit kjo ishte:

http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Shkarkoni këtë tarball duke përdorur wget:

wget -O alpine-rootfs.tgz http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Tani futni drejtorinë e sistemit të skedarëve të ftuar dhe nxirrni arkivin:

cd uml-demo
tar xf ../alpine-rootfs.tgz

Hapat e përshkruar do të krijojnë një shabllon të vogël të sistemit të skedarëve. Për shkak të mënyrës se si funksionon sistemi, instalimi i paketave përmes menaxherit apk Alpine do të jetë jashtëzakonisht i vështirë. Por kjo FS do të jetë e mjaftueshme për të vlerësuar idenë e përgjithshme.

Ne gjithashtu kemi nevojë për një mjet kazanët për të ndaluar konsumin e kujtesës proceset e zombies kerneli ynë i ftuar.

wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini

Krijimi i një linje komande të kernelit

Kerneli Linux, si shumica e programeve të tjera, ka argumente të linjës së komandës që mund të arrihen duke specifikuar çelësin --help.

Vetë - ndihmë

linux --help
User Mode Linux v5.1.16
        available at http://user-mode-linux.sourceforge.net/

--showconfig
    Prints the config file that this UML binary was generated from.

iomem=<name>,<file>
    Configure <file> as an IO memory region named <name>.

mem=<Amount of desired ram>
    This controls how much "physical" memory the kernel allocates
    for the system. The size is specified as a number followed by
    one of 'k', 'K', 'm', 'M', which have the obvious meanings.
    This is not related to the amount of memory in the host.  It can
    be more, and the excess, if it's ever used, will just be swapped out.
        Example: mem=64M

--help
    Prints this message.

debug
    this flag is not needed to run gdb on UML in skas mode

root=<file containing the root fs>
    This is actually used by the generic kernel in exactly the same
    way as in any other kernel. If you configure a number of block
    devices and want to boot off something other than ubd0, you
    would use something like:
        root=/dev/ubd5

--version
    Prints the version number of the kernel.

umid=<name>
    This is used to assign a unique identity to this UML machine and
    is used for naming the pid file and management console socket.

con[0-9]*=<channel description>
    Attach a console or serial line to a host channel.  See
    http://user-mode-linux.sourceforge.net/old/input.html for a complete
    description of this switch.

eth[0-9]+=<transport>,<options>
    Configure a network device.
    
aio=2.4
    This is used to force UML to use 2.4-style AIO even when 2.6 AIO is
    available.  2.4 AIO is a single thread that handles one request at a
    time, synchronously.  2.6 AIO is a thread which uses the 2.6 AIO
    interface to handle an arbitrary number of pending requests.  2.6 AIO
    is not available in tt mode, on 2.4 hosts, or when UML is built with
    /usr/include/linux/aio_abi.h not available.  Many distributions don't
    include aio_abi.h, so you will need to copy it from a kernel tree to
    your /usr/include/linux in order to build an AIO-capable UML

nosysemu
    Turns off syscall emulation patch for ptrace (SYSEMU).
    SYSEMU is a performance-patch introduced by Laurent Vivier. It changes
    behaviour of ptrace() and helps reduce host context switch rates.
    To make it work, you need a kernel patch for your host, too.
    See http://perso.wanadoo.fr/laurent.vivier/UML/ for further
    information.

uml_dir=<directory>
    The location to place the pid and umid files.

quiet
    Turns off information messages during boot.

hostfs=<root dir>,<flags>,...
    This is used to set hostfs parameters.  The root directory argument
    is used to confine all hostfs mounts to within the specified directory
    tree on the host.  If this isn't specified, then a user inside UML can
    mount anything on the host that's accessible to the user that's running
    it.
    The only flag currently supported is 'append', which specifies that all
    files opened by hostfs will be opened in append mode.

Ky panel thekson parametrat kryesorë të nisjes. Le të ekzekutojmë kernelin me grupin minimal të kërkuar të opsioneve:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  init=/bin/sh

Rreshtat e mësipërme tregojnë kernelin tonë si vijon:

  • Le të supozojmë se sistemi i skedarëve rrënjë është një pseudo pajisje /dev/root.
  • Zgjidhni hostfs si një drejtues i sistemit të skedarëve rrënjë.
  • Montoni sistemin e skedarëve të ftuar që krijuam në pajisjen rrënjë.
  • Dhe po, në modalitetin lexim-shkrim.
  • Përdorni vetëm 64 MB RAM (mund të përdorni shumë më pak në varësi të asaj që planifikoni të bëni, por 64 MB duket si sasia optimale).
  • Kerneli fillon automatikisht /bin/sh si init-procesi.

Ekzekutoni këtë komandë dhe duhet të merrni diçka si më poshtë:

Një fletë më shumë

Core dump limits :
        soft - 0
        hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking environment variables for a tempdir...none found
Checking if /dev/shm is on tmpfs...OK
Checking PROT_EXEC mmap in /dev/shm...OK
Adding 32137216 bytes to physical memory to account for exec-shield gap
Linux version 5.1.16 (cadey@kahless) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 Sun Jul 7 18:57:19 UTC 2019
Built 1 zonelists, mobility grouping on.  Total pages: 23898
Kernel command line: root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Dentry cache hash table entries: 16384 (order: 5, 131072 bytes)
Inode-cache hash table entries: 8192 (order: 4, 65536 bytes)
Memory: 59584K/96920K available (2692K kernel code, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K reserved, 0K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 15
clocksource: timer: mask: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Calibrating delay loop... 7479.29 BogoMIPS (lpj=37396480)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
devtmpfs: initialized
random: get_random_bytes called from setup_net+0x48/0x1e0 with crng_init=0
Using 2.6 host AIO
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: 0, 6144 bytes)
NET: Registered protocol family 16
clocksource: Switched to clocksource timer
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
console [stderr0] disabled
mconsole (version 2) initialized on /home/cadey/.uml/tEwIjm/mconsole
Checking host MADV_REMOVE support...OK
workingset: timestamp_bits=62 max_order=14 bucket_order=0
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered (default)
io scheduler bfq registered
loop: module loaded
NET: Registered protocol family 17
Initialized stdio console driver
Using a channel type which is configured out of UML
setup_one_line failed for device 1 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 2 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 3 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 4 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 5 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 6 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 7 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 8 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 9 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 10 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 11 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 12 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 13 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 14 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 15 : Configuration failed
Console initialized on /dev/tty0
console [tty0] enabled
console [mc-1] enabled
Failed to initialize ubd device 0 :Couldn't determine size of device's file
VFS: Mounted root (hostfs filesystem) on device 0:11.
devtmpfs: mounted
This architecture does not have kernel memory protection.
Run /bin/sh as init process
/bin/sh: can't access tty; job control turned off
random: fast init done
/ # 

Manipulimet e mësipërme do të na japin sistemi i mysafirëve të paktën, pa gjëra të tilla si /proc ose emri i hostit të caktuar. Për shembull, provoni komandat e mëposhtme:

- uname -av
- cat /proc/self/pid
- hostname

Për të dalë nga sistemi i të ftuarve, futni exit ose shtypni kontroll-d. Kjo do të vrasë guaskën e ndjekur nga një panik kernel:

/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag…” terminated by signal SIGABRT (Abort)

Ne e morëm këtë panik të kernelit sepse kerneli Linux mendon se procesi i inicializimit është gjithmonë duke u ekzekutuar. Pa të, sistemi nuk mund të funksionojë më dhe rrëzohet. Por meqenëse ky është një proces i modalitetit të përdoruesit, dalja që rezulton dërgohet vetë te SIGABRT, e cila rezulton në një dalje.

Konfigurimi i rrjetit të vizitorëve

Dhe këtu gjërat fillojnë të shkojnë keq. Rrjetëzimi në modalitetin e përdoruesit Linux është vendi ku i gjithë koncepti i "modalitetit të përdoruesit" të kufizuar fillon të shpërbëhet. Në fund të fundit, zakonisht në nivelin e sistemit, rrjeti është i kufizuar të privilegjuar mënyrat e ekzekutimit për të gjithë ne arsye të kuptueshme.

shënim per.: Mund të lexoni më shumë rreth opsioneve të ndryshme për të punuar me një rrjet në UML këtu.

Udhëtim për në Slirp

Megjithatë, ekziston një mjet i lashtë dhe praktikisht i pambështetur i quajtur rrëshqitje, me të cilin Modaliteti i Përdoruesit Linux mund të ndërveprojë me rrjetin. Ai funksionon shumë si një pirg TCP/IP i nivelit të përdoruesit dhe nuk kërkon asnjë leje sistemi për të ekzekutuar. Ky mjet ishte lëshuar 1995, dhe përditësimi i fundit është i datës 2006. Slirp është shumë i vjetër. Gjatë kohës pa mbështetje dhe përditësime, përpiluesit kanë shkuar aq larg sa që tani ky mjet mund të përshkruhet vetëm si kalbja e kodit.

Pra, le të shkarkojmë Slirp nga depot e Ubuntu dhe të përpiqemi ta ekzekutojmë:

sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Ready ...
fish: “/usr/bin/slirp” terminated by signal SIGSEGV (Address boundary error)

O zot. Le të instalojmë korrigjuesin e Slirp dhe të shohim nëse mund të kuptojmë se çfarë po ndodh këtu:

sudo apt-get install gdb slirp-dbgsym
gdb /usr/bin/slirp
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/slirp...Reading symbols from /usr/lib/debug/.build-id/c6/2e75b69581a1ad85f72ac32c0d7af913d4861f.debug...done.
done.
(gdb) run
Starting program: /usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Ready ...

Program received signal SIGSEGV, Segmentation fault.
                                                    ip_slowtimo () at ip_input.c:457
457     ip_input.c: No such file or directory.

Gabimi rreh tek ne këtë linjë. Le të shohim stacktrace, mbase diçka do të na ndihmojë atje:

(gdb) bt full
#0  ip_slowtimo () at ip_input.c:457
        fp = 0x55784a40
#1  0x000055555556a57c in main_loop () at ./main.c:980
        so = <optimized out>
        so_next = <optimized out>
        timeout = {tv_sec = 0, tv_usec = 0}
        ret = 0
        nfds = 0
        ttyp = <optimized out>
        ttyp2 = <optimized out>
        best_time = <optimized out>
        tmp_time = <optimized out>
#2  0x000055555555b116 in main (argc=1, argv=0x7fffffffdc58) at ./main.c:95
No locals.

Këtu shohim se përplasja ndodh gjatë fillimit të ciklit kryesor kur slirp përpiqet të kontrollojë për afate kohore. Në këtë pikë, më duhej të hiqja dorë nga përpjekjet për korrigjimin e gabimeve. Por le të shohim nëse Slirp i ndërtuar sipas llojit funksionon. Unë e rishkarkova arkivin direkt nga faqja burimforge, sepse tërhiqni diçka nga atje përmes vijës së komandës është një dhimbje:

cd ~/dl
wget https://xena.greedo.xeserv.us/files/slirp-1.0.16.tar.gz
tar xf slirp-1.0.16.tar.gz
cd slirp-1.0.16/src
./configure --prefix=$HOME/prefix/slirp
make

Këtu shohim alarme për funksionet e integruara të papërcaktuara, domethënë për pamundësinë për të lidhur skedarin binar që rezulton. Duket se midis 2006 dhe kësaj pike, gcc ndaloi së prodhuari simbole të përdorura në funksionet e integruara të skedarëve të përpiluar ndërmjetës. Le të përpiqemi të zëvendësojmë fjalën kyçe inline në një koment bosh dhe shikoni rezultatin:

vi slirp.h
:6
a
<enter>
#define inline /**/
<escape>
:wq
make

Jo. As kjo nuk funksionon. Ende nuk mund të gjesh simbole për këto funksione.

Në këtë pikë, hoqa dorë dhe fillova të shikoja në Github Heroku ndërton paketa. Teoria ime ishte se një paketë ndërtimi Heroku do të përmbante binarët që më duheshin. Në fund, kërkimi më çoi ketu. Kam shkarkuar dhe shpaketuar uml.tar.gz dhe gjeti sa vijon:

total 6136
-rwxr-xr-x 1 cadey cadey   79744 Dec 10  2017 ifconfig*
-rwxr-xr-x 1 cadey cadey     373 Dec 13  2017 init*
-rwxr-xr-x 1 cadey cadey  149688 Dec 10  2017 insmod*
-rwxr-xr-x 1 cadey cadey   66600 Dec 10  2017 route*
-rwxr-xr-x 1 cadey cadey  181056 Jun 26  2015 slirp*
-rwxr-xr-x 1 cadey cadey 5786592 Dec 15  2017 uml*
-rwxr-xr-x 1 cadey cadey     211 Dec 13  2017 uml_run*

Ky është binar slirp! A punon ai?

./slirp
Slirp v1.0.17 (BETA) FULL_BOLT

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500]

SLiRP Ready ...

Nuk përplaset - kështu që duhet të funksionojë! Le ta vendosim këtë binar ~/bin/slirp:

cp slirp ~/bin/slirp

Në rast se krijuesi i paketës e heq atë, unë bëri një pasqyrë.

Konfigurimi i rrjetit

Tani le të konfigurojmë rrjetin në bërthamën tonë të ftuar. Le të përditësojmë parametrat e nisjes:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/sh

Tani le të aktivizojmë rrjetin:

mount -t proc proc proc/
mount -t sysfs sys sys/

ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

Dy komandat e para të konfigurimit /proc и /sys të nevojshme për punë ifconfig, e cila vendos ndërfaqen e rrjetit për të komunikuar me Slirp. Ekipi route vendos tabelën e rrugëzimit të kernelit për të detyruar që i gjithë trafiku të dërgohet përmes tunelit Slirp. Le ta kontrollojmë këtë me një pyetje DNS:

nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 dns.google

Name:      google.com
Address 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Address 2: 2607:f8b0:4006:81b::200e lga25s63-in-x0e.1e100.net

Ajo funksionon!

Shënim për.: Me sa duket, postimi origjinal është shkruar në një desktop me një kartë rrjeti me kabllo, ose ndonjë konfigurim tjetër që nuk kërkon drejtues shtesë. Në një laptop me WiFi 8265 nga Intel, ndodh një gabim kur ngrihet rrjeti

/ # ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
slirp_tramp failed - errno = 2
ifconfig: ioctl 0x8914 failed: No such file or directory
/ #

Me sa duket, kerneli nuk mund të komunikojë me drejtuesin e diskut të rrjetit. Një përpjekje për të përpiluar firmware në kernel, për fat të keq, nuk e korrigjoi situatën. Në kohën e publikimit, asnjë zgjidhje nuk mund të gjendej ende në këtë konfigurim të veçantë. Në konfigurimet më të thjeshta (për shembull, në Virtualbox), ndërfaqja ngrihet saktë.

Le të automatizojmë ridrejtimin me skriptin e mëposhtëm të guaskës:

#!/bin/sh
# init.sh

mount -t proc proc proc/
mount -t sysfs sys sys/
ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

echo "networking set up"

exec /tini /bin/sh

Dhe shënojeni si të ekzekutueshme:

chmod +x init.sh

Dhe pastaj do të bëjmë ndryshime në vijën e komandës së kernelit:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/init.sh

Dhe le të përsërisim:

SLiRP Ready ...
networking set up
/bin/sh: can't access tty; job control turned off

nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 dns.google

Name:      google.com
Address 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Address 2: 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.net

Rrjeti është i qëndrueshëm!

skedar docker

Për ta bërë më të lehtë për ju të kontrolloni të gjitha këto, kam mbledhur dockerfile, i cili automatizon shumicën e hapave të përshkruar dhe duhet t'ju ofrojë një konfigurim pune. Unë gjithashtu kam kernel i parakonfiguruar, e cila ka gjithçka që përshkruhet në postim. Por është e rëndësishme të kuptohet se këtu kam përshkruar vetëm cilësimin minimal.

Shpresoj se ky postim ju ka ndihmuar të kuptoni se si të krijoni një kernel të ftuar. Doli të ishte një lloj përbindëshi, por botimi kishte për qëllim si një udhëzues gjithëpërfshirës mbi temën e montimit, instalimit dhe konfigurimit të modalitetit të përdoruesit në Linux nën versionet moderne të sistemeve operative të kësaj familjeje. Hapat pasues duhet të përfshijnë instalimin e shërbimeve dhe softuerëve të tjerë tashmë brenda sistemit të mysafirëve. Meqenëse imazhet e kontejnerëve të Docker janë thjesht tarball të promovuar, duhet të jeni në gjendje të nxirrni imazhin nëpërmjet docker export, dhe më pas përcaktoni shtegun për ta instaluar atë në rrënjën e sistemit të skedarëve të kernelit të ftuar. Epo, atëherë ekzekutoni skriptin e guaskës.

Falënderime të veçanta për Rkeene nga #lobsters në Freenode. Pa ndihmën e tij në korrigjimin e Slirp, nuk do të kisha arritur deri këtu. Nuk e kam idenë sesi sistemi i tij Slackware funksionon siç duhet me slirp, por sistemet e mia Ubuntu dhe Alpine nuk e pranuan slirp-in dhe Rkeene binar më sugjeroi. Por mua më mjafton që të paktën diçka të funksionojë për mua.

Burimi: www.habr.com

Shto një koment