Si të filloni të përdorni Modalitetin e Përdoruesit në Linux

Hyrje nga përkthyesi: Me lloje të ndryshme kontejnerësh që po bëhen pjesë e madhe e jetës sonë, mund të jetë mjaft interesante dhe e dobishme të mësojmë rreth teknologjive që e nisën gjithçka. Disa prej tyre mund të përdoren ende sot, por jo të gjithë i kujtojnë (ose dinë për to, nëse nuk do të ekzistonin gjatë zhvillimit të tyre të shpejtë). Një teknologji e tillë është Modaliteti i Përdoruesit. LinuxAutori origjinal bëri mjaft kërkime, duke kuptuar se cilat praktika të vjetra funksionojnë ende dhe cilat jo, dhe hartoi diçka si një udhëzues hap pas hapi se si të krijoni UML-në tuaj vendase në 2k19. Dhe po, ne e kemi ftuar autorin 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 - kjo është, në fakt, një port kernel Linux në vetvete. Ky modalitet ju lejon të ekzekutoni një kernel të plotë Linux si një proces përdoruesi dhe përdoret zakonisht nga zhvilluesit për testimin e drajverëve. Megjithatë, kjo mënyrë është gjithashtu e dobishme si një mjet izolimi i përgjithshëm, i ngjashëm në parim me mënyrën se si funksionojnë makinat virtuale. Kjo mënyrë ofron izolim më të madh 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, është një mjet i plotë Linux- një kernel që funksionon si një përdorues i paprivilegjuar. Kjo veçori lejon që kodi potencialisht i pabesueshëm të funksionojë pa asnjë kërcënim për makinën pritëse. Dhe meqenëse është një kernel i plotë, proceset e tij janë të izoluara nga makina pritëse, që do të thotë 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-në e kernelit Linux në Modalitetin e Përdoruesit:

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

Kur punoj me kontejnerë Docker, mund të shoh emrat e proceseve që funksionojnë në sistemin mysafir nga hosti. Linux Modaliteti i Përdoruesit është i pamundur. Çfarë do të thotë kjo? Do të thotë që mjetet e monitorimit që funksionojnë përmes nënsistemit të auditimit Linux (Linuxnënsistemi i auditimit të 's) 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

rregullim Linux Modaliteti i përdoruesit kryhet në disa faza:

  • 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 t'i bëni të gjitha këto vetë, ka shumë të ngjarë të bëni gjithçka që përshkruhet në disa Ubuntu ose Debiansistem i ngjashëm me atë të mëparshëm. U përpoqa të zbatoja gjithçka që përshkruhet më sipër në shpërndarjen time të preferuar, Alpine, por asgjë nuk funksionoi, me sa duket sepse kerneli Linux ka një lidhje të fortë me glibc-ism-et për drajverët e modalitetit të përdoruesit. Planifikoj ta raportoj këtë te drejtuesit e sistemit pasi ta kuptoj plotësisht problemin.

Instalimi i varësive nga hosti

Ubuntu kërkon të paktën paketat e mëposhtme për të ndërtuar bërthamën 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)

Ju lutemi vini re se ekzekutimi i programit të konfigurimit të menusë së kernelit Linux do të kërkojë instalim 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

Thelbi Linux Është një program i madh që bën shumë gjëra. Edhe me këtë konfigurim minimal, ndërtimi i tij në harduer më të vjetër mund të zgjasë mjaft kohë. Prandaj, ndërtoni bërthamën duke përdorur 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ë montimin standard 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 është në Linux Krijon një skedar binar të rregullt, kështu që mund ta instaloni si çdo program tjetër. Ja se si e bëra unë:

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

Në thelb Linux, si shumica e programeve të tjera, ka argumente të rreshtit të komandës që mund të aksesohen 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 kemi këtë panik të kernelit sepse kerneli Linux supozon se procesi i inicializimit është gjithmonë në ekzekutim. Pa të, sistemi nuk mund të funksionojë më dhe përfundon. Por, meqenëse ky është një proces në modalitetin e përdoruesit, rezultati që rezulton dërgohet vetë te SIGABRT, e cila rezulton në një dalje.

Konfigurimi i rrjetit të vizitorëve

Por këtu është vendi ku gjërat fillojnë të shkojnë keq. Rrjeti në Modalitetin e Përdoruesit Linux — këtu fillon të shembet i gjithë koncepti i një "modaliteti përdoruesi" të kufizuar. Në fund të fundit, në nivelin e sistemit, rrjeti zakonisht ë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 ndihmën e të cilit Modaliteti i Përdoruesit Linux mund të bashkëveprojë me rrjetin. Funksionon disi si një pirg TCP/IP në nivelin e përdoruesit dhe nuk kërkon leje sistemi për t'u 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 ta shkarkojmë Slirp nga depot. Ubuntu dhe le 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 që ky postim ju ka ndihmuar të kuptoni se si të vini në punë një kernel mysafir. Është paksa i vështirë, por qëllimi ishte të ofroja një udhëzues gjithëpërfshirës mbi ndërtimin, instalimin dhe konfigurimin e Modalitetit të Përdoruesit. Linux 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ë brenda sistemit mysafir. Meqenëse imazhet e kontejnerëve Docker janë thjesht tarball-e të ekzagjeruara, duhet të jeni në gjendje ta 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ë debugging-un e Slirp, nuk do të kisha arritur deri këtu. Nuk e kam idenë se si funksionon siç duhet sistemi i tij Slackware me slirp, por sistemet e mia po. Ubuntu dhe Alpine nuk e pranoi slirp dhe binarja Rkeene ma ofroi mua. Por më mjafton që të paktën diçka funksionon.

Burimi: www.habr.com

Bleni një host të besueshëm për faqet me mbrojtje DDoS, serverë VPS VDS 🔥 Bleni hosting të besueshëm të faqeve të internetit me mbrojtje DDoS, servera VPS VDS | ProHoster