Kako početi koristiti korisnički način rada u Linuxu

Uvod prevodioca: U pozadini masovnog ulaska raznih vrsta kontejnera u naše živote, može biti prilično zanimljivo i korisno saznati s kojim tehnologijama je sve nekada počelo. Neki od njih se mogu korisno koristiti do danas, ali se ne sjećaju svi takvih metoda (ili znaju da nisu bili uhvaćeni tokom njihovog brzog razvoja). Jedna takva tehnologija je User Mode Linux. Autor originala je dosta kopao, otkrivajući koji od starih razvojnih programa još radi, a koji ne, i sastavio je nešto poput uputstva korak po korak kako da sebi nabavite domaći UML u 2k19. I da, pozvali smo autora originalnog posta u Habr Cadey, pa ako imate pitanja - pitajte na engleskom u komentarima.

Kako početi koristiti korisnički način rada u Linuxu

Korisnički način rada u Linuxu je, u stvari, port Linux kernela za sebe. Ovaj način vam omogućava da pokrenete cijeli Linux kernel kao korisnički proces i obično ga koriste programeri za testiranje drajvera. Ali ovaj način je također koristan kao opći alat za izolaciju, čiji je princip sličan radu virtualnih mašina. Ovaj način pruža veću izolaciju od Dockera, ali manje od punopravne virtualne mašine kao što je KVM ili Virtual Box.

Općenito, korisnički način rada može izgledati kao čudan i težak alat za korištenje, ali ipak ima svoje koristi. Na kraju krajeva, ovo je punopravni Linux kernel koji radi od neprivilegiranog korisnika. Ova funkcija omogućava pokretanje potencijalno nepouzdanog koda bez ikakve prijetnje glavnom računalu. A pošto je ovo potpuno jezgro, njegovi procesi su izolovani od host mašine, tj procesi koji se pokreću unutar korisničkog moda neće biti vidljivi hostu. Ovo nije kao uobičajeni Docker kontejner, u kom slučaju host mašina uvijek vidi procese unutar spremišta. Pogledajte ovaj komad pstree sa jednog od mojih servera:

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}]

I uporedite ovo sa pstree Linux kernela u korisničkom modu:

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

Kada radim sa Docker kontejnerima, mogu vidjeti sa hosta imena procesa koji se pokreću u gostu. Sa Linux korisničkim načinom, to nije moguće. Šta to znači? To znači da alati za praćenje koji rade kroz Linuxov revizijski podsistem ne vidim procesi koji se izvode u sistemu za goste. Ali u nekim situacijama ova karakteristika može postati mač sa dvije oštrice.

Općenito, cijeli post ispod je zbirka istraživanja i grubih pokušaja da se postigne željeni rezultat. Da bih to uradio, morao sam da koristim razne drevne alate, čitam izvore kernela, radim intenzivno otklanjanje grešaka u kodu napisanom u danima kada sam još bio u osnovnoj školi, a takođe i da petljam u Heroku build-ovima koristeći poseban binarni fajl da pronađem alate koji su mi potrebni . Sav ovaj rad naveo je momke na mom IRC-u da me nazovu magičnim. Nadam se da će ovaj post poslužiti kao pouzdana dokumentacija za nekoga da pokuša istu stvar sa novijim kernelima i verzijama OS-a.

podešavanje

Podešavanje Linux korisničkog načina rada vrši se u nekoliko koraka:

  • instaliranje zavisnosti na hostu;
  • preuzimanje Linux kernela;
  • konfiguracija izrade kernela;
  • sklop kernela;
  • binarna instalacija;
  • konfigurisanje sistema datoteka za goste;
  • izbor parametara pokretanja kernela;
  • postavljanje mreže gostiju;
  • pokretanje gostujućeg kernela.

Pretpostavljam da ćete, ako odlučite to učiniti sami, najvjerojatnije učiniti sve što je opisano u nekom Ubuntu ili Debian sistemu. Pokušao sam da implementiram sve gore navedeno u svojoj omiljenoj distribuciji - Alpine, ali ništa nije bilo od toga, očigledno zbog činjenice da Linux kernel ima hard-binding glibc-isms za drajvere u korisničkom režimu. Planiram prijaviti ovo upstream nakon što konačno shvatim problem.

Instaliranje zavisnosti na hostu

Ubuntu zahtijeva najmanje sljedeće pakete za izgradnju Linux kernela (pod pretpostavkom čiste instalacije):

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

Možete ih instalirati sa sljedećom naredbom (kao root ili sa sudo):

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

Imajte na umu da će pokretanje programa za podešavanje menija jezgra Linuxa zahtijevati instalaciju libncurses-dev. Uvjerite se da je instaliran sa sljedećom naredbom (kao root ili sa sudo):

apt-get -y install libncurses-dev

Preuzimanje kernela

Odlučite gdje ćete preuzeti, a zatim izgradite kernel. Za ovu operaciju morat ćete izdvojiti oko 1,3 GB prostora na tvrdom disku, pa se pobrinite da ga imate.

Nakon idite na kernel.org i dobijete URL za preuzimanje najnovijeg stabilnog kernela. U vrijeme pisanja ovo je: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Preuzmite ovu datoteku koristeći 'wget':

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

I izvucite ga sa 'tar':

tar xJf linux-5.1.16.tar.xz

Sada ulazimo u direktorij kreiran prilikom raspakivanja tarball-a:

cd linux-5.1.16

Podešavanje izrade kernela

Sistem izgradnje kernela je skup Makefiles с mnogi prilagođene alate i skripte za automatizaciju procesa. Prvo otvorite interaktivni program za podešavanje:

make ARCH=um menuconfig

Djelomično će izgraditi i prikazati dijaloški okvir za vas. Kada '[Select]', moći ćete konfigurirati pomoću tipki za razmak ili Enter. Krećite se kroz prozor, kao i obično, sa strelicama na tastaturi "gore" i "dole" i izaberite elemente - "levo" ili "desno".

Pokazivač prikaza —> znači da se nalazite u podmeniju kojem se pristupa pomoću tipke Enter. Izlaz iz toga je očigledno kroz '[Exit]'.

Uključite sljedeće opcije u '[Select]' i pobrinite se da imaju '[*]' pored sebe:

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

To je to, možete izaći iz ovog prozora uzastopnim odabirom '[Exit]'. Samo se pobrinite da na kraju budete upitani da spremite konfiguraciju i odaberite '[Yes]'.

Preporučujem da se poigrate sa opcijama izgradnje kernela nakon što pročitate ovaj post. Kroz ove eksperimente možete naučiti mnogo u smislu razumijevanja rada mehanike kernela niskog nivoa i utjecaja različitih zastavica na njegovo sklapanje.

Izgradnja kernela

Linux kernel je veliki program koji radi puno stvari. Čak i sa tako minimalnom konfiguracijom na starom hardveru, može potrajati dosta vremena za izradu. Dakle, napravite kernel sa sljedećom naredbom:

make ARCH=um -j$(nproc)

Za što? Ova naredba će reći našem graditelju da koristi sve dostupne CPU jezgre i niti u procesu izgradnje. Tim $(nproc) na kraju Build zamjenjuje izlaz naredbe nproc, koji je dio coreutils u standardnoj Ubuntu verziji.

Nakon nekog vremena, naš kernel će biti preveden u izvršnu datoteku ./linux.

Instaliranje binarne datoteke

Pošto korisnički način rada u Linuxu stvara običnu binarnu datoteku, možete je instalirati kao i bilo koji drugi uslužni program. Evo kako sam to uradio:

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

U to se takođe vredi uveriti ~/bin je u vašem $PATH:

export PATH=$PATH:$HOME/bin

Postavljanje sistema datoteka za goste

Kreirajte direktorij za sistem datoteka gostiju:

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

Otvorite alpinelinux.org i uđite preuzmi odjeljak pronađite stvarni link za preuzimanje MINI ROOT FILESYSTEM. U vrijeme pisanja ovo je bilo:

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

Preuzmite ovaj tarball koristeći 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

Sada uđite u direktorij sistema datoteka za goste i raspakirajte arhivu:

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

Opisane akcije će kreirati mali predložak sistema datoteka. Zbog prirode sistema, biće izuzetno teško instalirati pakete preko Alpine apk menadžera. Ali ovaj FS će biti dovoljan za procjenu opšte ideje.

Potreban nam je i alat tini za smanjenje potrošnje memorije zombi procesi naše gostujuće jezgro.

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

Kreiranje komandne linije kernela

Linux kernel, kao i većina drugih programa, ima argumente komandne linije kojima se može pristupiti navođenjem ključa --help.

On sam — u pomoć

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.

Ovaj panel naglašava glavne parametre lansiranja. Pokrenimo kernel sa minimalnim potrebnim skupom opcija:

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

Gornje linije govore našem kernelu sljedeće:

  • Pretpostavimo da je korijenski sistem datoteka pseudo uređaj /dev/root.
  • Odaberite hostfs kao drajver za root fajl sistem.
  • Montirajte gostujući fajl sistem koji smo kreirali na root uređaj.
  • I da, u načinu čitanja i pisanja.
  • Koristite samo 64 MB RAM-a (možete koristiti mnogo manje u zavisnosti od toga šta planirate da radite, ali čini se da je 64 MB optimalna količina).
  • Kernel se automatski pokreće /bin/sh kako init-proces.

Pokrenite ovu naredbu i trebali biste dobiti nešto poput sljedećeg:

Još jedan list

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
/ # 

Gore navedene manipulacije će nam dati sistem gostiju na minimum, bez stvari poput /proc ili dodijeljeno ime hosta. Na primjer, pokušajte sa sljedećim naredbama:

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

Da biste se odjavili iz gosta, otkucajte exit ili pritisnite Control-d. Ovo će ubiti ljusku praćeno panikom kernela:

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

Dobili smo ovu paniku kernela jer Linux kernel misli da proces inicijalizacije uvijek radi. Bez toga, sistem više ne može funkcionirati i pada. Ali pošto je ovo proces u korisničkom režimu, rezultujući izlaz se sam šalje SIGABRT, što rezultira izlazom.

Postavljanje mreže za goste

I tu stvari počinju da idu po zlu. Umrežavanje u korisničkom modu Linux je mjesto gdje cijeli koncept ograničenog "korisničkog načina" počinje da se raspada. Uostalom, obično na nivou sistema, mreža je ograničena privilegovan načini izvršenja iz svima nama razumljivih razloga.

Bilješka. per .: možete pročitati više o različitim opcijama za rad s mrežom u UML-u ovdje.

Putovanje u Slirp

Međutim, postoji drevni i gotovo nepodržani alat pod nazivom Slirp, s kojim User Mode Linux može komunicirati s mrežom. Radi slično kao TCP/IP stek na nivou korisnika i ne zahtijeva nikakve sistemske dozvole za pokretanje. Ovaj alat je bio objavljen 1995, a najnovije ažuriranje ima datum 2006. Slirp je veoma star. Tokom vremena bez podrške i ažuriranja, kompajleri su otišli toliko daleko da se sada ovaj alat može opisati samo kao code rot.

Dakle, hajde da preuzmemo Slirp iz Ubuntu repozitorijuma i pokušamo da ga pokrenemo:

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)

Oh boze. Hajde da instaliramo Slirpov debugger i vidimo da li možemo da shvatimo šta se ovde dešava:

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.

Greška tuče u nama ovu liniju. Pogledajmo stacktrace, možda nam tu nešto pomogne:

(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.

Ovdje vidimo da se pad događa tokom početka glavne petlje kada slirp pokuša provjeriti da li je došlo do isteka. U ovom trenutku, morao sam odustati od pokušaja otklanjanja grešaka. Ali hajde da vidimo da li Slirp napravljen od nekih vrsta radi. Ponovo sam skinuo arhivu direktno sa stranice Sourceforge, jer je prevlačenje nečega odatle kroz komandnu liniju muka:

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

Ovdje vidimo upozorenja o nedefiniranim ugrađenim funkcijama, odnosno o nemogućnosti povezivanja rezultirajuće binarne datoteke. Čini se da je između 2006. i ove tačke, gcc prestao proizvoditi simbole koji se koriste u ugrađenim funkcijama posredno kompajliranih datoteka. Pokušajmo zamijeniti ključnu riječ inline na prazan komentar i pogledajte rezultat:

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

Ne. Ni ovo ne radi. Još uvijek ne mogu pronaći simbole za ove funkcije.

U ovom trenutku sam odustao i počeo da tražim Github Heroku build paketi. Moja teorija je bila da bi neki Heroku build paket sadržavao binarne datoteke koje su mi potrebne. Na kraju me je potraga dovela ovdje. Skinuo sam i raspakovao uml.tar.gz i pronašao sljedeće:

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*

Ovo je slirp binarno! Da li radi?

./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 ...

Ne ruši se - tako da bi trebalo da radi! Ugradimo ovu binarnu datoteku ~/bin/slirp:

cp slirp ~/bin/slirp

U slučaju da ga kreator paketa ukloni, I napravila ogledalo.

Konfiguracija mreže

Sada postavimo mrežu na našem gostujućem kernelu. Ažurirajte opcije pokretanja:

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

Sada uključimo mrežu:

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

Prve dvije konfiguracijske naredbe /proc и /sys neophodna za rad ifconfig, koji postavlja mrežni interfejs za komunikaciju sa Slirp-om. Tim route postavlja tabelu rutiranja kernela da prisili sav promet da se pošalje kroz Slirp tunel. Provjerimo ovo DNS upitom:

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

Radi!

Napomena po .: Očigledno, originalni post je napisan na desktopu sa ožičenom mrežnom karticom, ili nekom drugom konfiguracijom koja nije zahtijevala dodatne drajvere. Na laptopu sa WiFi 8265 od Intel-a dolazi do greške prilikom podizanja mreže

/ # 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
/ #

Očigledno, kernel ne može komunicirati sa drajverom mrežne kartice. Pokušaj kompajliranja firmvera u kernel, nažalost, nije popravio situaciju. U trenutku objavljivanja nije bilo moguće pronaći rješenje u ovoj konfiguraciji. Na jednostavnijim konfiguracijama (na primjer, u Virtualboxu), sučelje se pravilno podiže.

Automatizirajmo preusmjeravanje sa sljedećom shell skriptom:

#!/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

I označite ga kao izvršno:

chmod +x init.sh

A onda ćemo napraviti promjene u komandnoj liniji kernela:

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

I da ponovimo:

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

Mreža je stabilna!

docker fajl

Da vam olakšam sve ovo da provjerite, prikupio sam dockerfile, koji automatizira većinu opisanih koraka i trebao bi vam dati radnu konfiguraciju. I ja imam unapred konfigurisan kernel, koji ima sve što je opisano u postu. Ali važno je shvatiti da sam ovdje naveo samo minimalnu postavku.

Nadam se da vam je ovaj post pomogao da shvatite kako da podignete jezgro za goste. Ispostavilo se da je to neko čudovište, ali publikacija je zamišljena kao sveobuhvatan vodič za izgradnju, instalaciju i konfiguraciju korisničkog moda u Linuxu pod modernim verzijama operativnih sistema ove porodice. Sljedeći koraci bi trebali uključivati ​​instalaciju usluga i drugog softvera koji je već unutar gostujućeg sistema. Budući da su slike Docker kontejnera samo objavljeni tarball-ovi, trebali biste moći izvući sliku putem docker export, a zatim odredite njegovu instalacijsku putanju u korijenu sistema datoteka gostujućeg kernela. Pa, onda izvedite shell skriptu.

Posebno hvala Rkeeneu iz #lobsters na Freenodeu. Bez njegove pomoći u otklanjanju grešaka u Slirpu, ne bih stigao ovako daleko. Nemam pojma kako njegov Slackware sistem radi ispravno sa slirpom, ali moji Ubuntu i Alpine sistemi nisu prihvatili slirp i binarni Rkeene mi je predložio. Ali meni je dovoljno da mi bar nešto radi.

izvor: www.habr.com

Dodajte komentar