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

Uvod od prevoditelja: U pozadini masovnog ulaska raznih vrsta spremnika u naše živote, može biti vrlo zanimljivo i korisno saznati s kojim je tehnologijama sve počelo. Neki od njih mogu se korisno koristiti i danas, ali ne sjećaju se svi takvih metoda (ili znaju ako nisu uhvaćeni tijekom njihovog brzog razvoja). Jedna takva tehnologija je User Mode Linux. Autor originala dosta je kopao, otkrivajući koji od starih razvoja još uvijek rade, a koji ne, i sastavio je nešto poput korak-po-korak uputa o tome kako sebi nabaviti domaći UML u 2k19. I da, pozvali smo autora originalne objave na 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 zapravo je priključak Linux kernela za sebe. Ovaj način vam omogućuje pokretanje pune jezgre Linuxa kao korisničkog procesa i programeri ga obično koriste za testiranje upravljačkih programa. Ali ovaj je način također koristan kao opći alat za izolaciju, čiji je princip sličan radu virtualnih strojeva. Ovaj način rada pruža veću izolaciju od Dockera, ali manje od potpunog virtualnog stroja poput KVM-a ili Virtual Boxa.

Općenito, korisnički način rada može se činiti kao čudan i težak alat za korištenje, ali ipak ima svoje namjene. Uostalom, ovo je potpuni Linux kernel koji pokreće neprivilegirani korisnik. Ova značajka omogućuje pokretanje potencijalno nepouzdanog koda bez ikakve prijetnje glavnom računalu. A budući da je ovo punopravni kernel, njegovi su procesi izolirani od glavnog stroja, tj procesi koji se izvode unutar korisničkog načina rada neće biti vidljivi hostu. Ovo nije kao uobičajeni Docker spremnik, u kojem slučaju glavno računalo uvijek vidi procese unutar repozitorija. Pogledajte ovaj dio pstree-a s jednog od mojih poslužitelja:

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 usporedite ovo s pstreeom Linux kernela u korisničkom načinu rada:

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

Kada radim s Docker spremnicima, na hostu mogu vidjeti nazive procesa koji se izvode u gostu. Ovo nije moguće s Linux korisničkim načinom rada. Što to znači? To znači da alati za praćenje rade kroz podsustav revizije Linuxa ne vidim procesi koji se izvode u gostujućem sustavu. Ali u nekim situacijama ova značajka može postati dvosjekli mač.

Općenito, cijeli post ispod je zbirka istraživanja i grubih pokušaja postizanja željenog rezultata. Da bih to učinio, morao sam koristiti razne stare alate, čitati izvore kernela, intenzivno ispravljati pogreške koda napisanog u danima kad sam još bio u osnovnoj školi, a također petljati s Heroku verzijama koristeći posebnu binarnu datoteku kako bih pronašao alate koji su mi bili potrebni . Sav ovaj posao naveo je dečke na mom IRC-u da me nazovu čarobnim. Nadam se da će ovaj post poslužiti kao pouzdana dokumentacija za nekoga da pokuša istu stvar s novijim kernelima i verzijama OS-a.

podešavanje

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

  • instaliranje ovisnosti o hostu;
  • preuzimanje Linux kernela;
  • podešavanje izgradnje jezgre;
  • sklop jezgre;
  • binarna instalacija;
  • konfiguriranje gostujućeg datotečnog sustava;
  • odabir parametara pokretanja jezgre;
  • postavljanje mreže za goste;
  • pokretanje jezgre za goste.

Pretpostavljam da ćete, ako se odlučite na to sami, najvjerojatnije napraviti sve što je opisano u nekom sustavu sličnom Ubuntu ili Debianu. Pokušao sam implementirati sve gore navedeno u mojoj omiljenoj distribuciji - Alpine, ali ništa od toga, očito zbog činjenice da Linux kernel ima hard-binding glibc-isms za upravljačke programe u korisničkom načinu rada. Planiram ovo prijaviti upstreamu nakon što konačno shvatim problem.

Instaliranje ovisnosti o 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 sljedećom naredbom (kao root ili 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 postavljanje izbornika jezgre Linuxa zahtijevati instalaciju libncurses-dev. Provjerite je li instaliran sljedećom naredbom (kao root ili sudo):

apt-get -y install libncurses-dev

Preuzimanje kernela

Odlučite gdje ćete preuzeti i zatim izgradite kernel. Za ovu operaciju morat ćete dodijeliti oko 1,3 GB prostora na tvrdom disku, stoga provjerite imate li ga.

Zatim idite na kernel.org i dohvatite URL za preuzimanje najnovije stabilne verzije kernela. U vrijeme pisanja ovog posta: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Preuzmite ovu datoteku pomoću 'wget':

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

I izvadite ga s 'tar':

tar xJf linux-5.1.16.tar.xz

Sada ulazimo u direktorij stvoren prilikom raspakiranja tarballa:

cd linux-5.1.16

Postavljanje izgradnje kernela

Sustav izrade kernela je skup Makefiles с puno prilagođeni alati i skripte za automatizaciju procesa. Prvo otvorite interaktivni program za postavljanje:

make ARCH=um menuconfig

Djelomično će izgraditi i prikazati dijaloški okvir za vas. Kada '[Select]', moći ćete konfigurirati pomoću tipki Space ili Enter. Krećite se prozorom, kao i obično, sa strelicama tipkovnice "gore" i "dolje" i odaberite elemente - "lijevo" ili "desno".

Pokazivač pogleda —> znači da se nalazite u podizborniku kojemu pristupate tipkom Enter. Izlaz iz toga očito je kroz '[Exit]'.

Uključite sljedeće opcije u '[Select]' i provjerite imaju li '[*]' pokraj 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 provjerite jeste li na kraju upitani da spremite konfiguraciju i odaberete '[Yes]'.

Preporučujem da se poigrate s opcijama izgradnje kernela nakon što pročitate ovaj post. Kroz ove pokuse možete puno naučiti u smislu razumijevanja rada mehanike kernela niske razine i utjecaja raznih oznaka na njegovu montažu.

Izgradnja kernela

Linux kernel je veliki program koji radi puno stvari. Čak i uz ovu minimalnu konfiguraciju na starijem hardveru, sastavljanje može potrajati dosta dugo. Dakle, izgradite kernel pomoću sljedeće naredbe:

make ARCH=um -j$(nproc)

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

Nakon nekog vremena naš kernel će se kompajlirati u izvršnu datoteku ./linux.

Instaliranje binarne datoteke

Budući da korisnički način rada u Linuxu stvara obični binarni program, možete ga instalirati kao bilo koji drugi uslužni program. Evo kako sam ja to napravio:

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

Također je vrijedno osigurati da ~/bin je u vašem $PATH:

export PATH=$PATH:$HOME/bin

Postavljanje gostujućeg datotečnog sustava

Napravite direktorij za gostujući datotečni sustav:

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

Otvorite alpinelinux.org i uđite odjeljak za preuzimanje pronađite stvarnu vezu 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 gostujućeg datotečnog sustava i raspakirajte arhivu:

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

Opisane radnje stvorit će mali predložak datotečnog sustava. Zbog prirode sustava bit će izuzetno teško instalirati pakete putem Alpine apk managera. Ali ovaj FS će biti dovoljan za procjenu opće ideje.

Trebamo i alat kace za smanjenje potrošnje memorije zombi procese naš gostujući kernel.

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

Stvaranje naredbenog retka jezgre

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

On sam — 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.

Ova ploča ističe glavne parametre pokretanja. Pokrenimo kernel s minimalno potrebnim skupom opcija:

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

Gornji redovi govore našem kernelu sljedeće:

  • Pretpostavimo da je korijenski datotečni sustav pseudo uređaj /dev/root.
  • Odaberite hostfs kao upravljački program korijenskog datotečnog sustava.
  • Montirajte gostujući datotečni sustav koji smo stvorili na root uređaju.
  • I da, u načinu čitanja i pisanja.
  • Koristite samo 64 MB RAM-a (možete koristiti puno manje ovisno o tome što planirate raditi, ali 64 MB se čini kao optimalna količina).
  • Kernel se automatski pokreće /bin/sh kao init-postupak.

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

Gornje manipulacije će nam dati minimalni sustav za goste, bez stvari poput /proc ili dodijeljeno ime glavnog računala. Na primjer, pokušajte sljedeće naredbe:

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

Za odjavu iz sustava za goste unesite exit ili pritisnite control-d. Ovo će ubiti ljusku nakon čega slijedi panika 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 kernel paniku jer Linux kernel misli da se proces inicijalizacije uvijek izvodi. Bez njega sustav više ne može funkcionirati i ruši se. Ali budući da je ovo proces u korisničkom načinu rada, rezultirajući izlaz šalje se u SIGABRT, što rezultira izlazom.

Postavljanje mreže za goste

I tu stvari počinju ići po zlu. Umrežavanje u korisničkom načinu Linux je mjesto gdje se cijeli koncept ograničenog "korisničkog načina" počinje raspadati. Uostalom, obično je na razini sustava mreža ograničena privilegiran načini izvršenja iz svima nama razumljivih razloga.

Bilješka. po .: možete pročitati više o različitim opcijama za rad s mrežom u UML-u здесь.

Putovanje u Slirp

Međutim, postoji drevni i gotovo nepodržani alat tzv Skliznuti, s kojim korisnički način rada Linux može komunicirati s mrežom. Djeluje poput TCP/IP skupa na korisničkoj razini i ne zahtijeva nikakve sistemske dozvole za rad. Ovaj alat je bio izdana 1995, a najnovije ažuriranje je datirano 2006 godine. Slirp je jako star. Tijekom vremena bez podrške i ažuriranja, kompajleri su otišli toliko daleko da se sada ovaj alat može opisati samo kao kod truleži.

Dakle, preuzmimo Slirp iz Ubuntu repozitorija i pokušajmo ga pokrenuti:

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 bogovi. Instalirajmo Slirpov debugger i vidimo možemo li shvatiti što se ovdje događa:

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 kuca 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 rušenje događa tijekom pokretanja glavne petlje kada slirp pokušava provjeriti vrijeme čekanja. U ovom trenutku sam morao odustati od pokušaja otklanjanja pogrešaka. Ali da vidimo radi li Slirp izgrađen od vrsta. Ponovno sam preuzeo arhivu izravno sa stranice sourceforge, jer je muka povući nešto odatle kroz naredbeni redak:

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 dobivene binarne datoteke. Čini se da je između 2006. i ove točke, gcc prestao proizvoditi simbole koji se koriste u ugrađenim funkcijama međukompiliranih 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 ide. Još uvijek ne mogu pronaći simbole za ove funkcije.

U ovom trenutku sam odustao i počeo tražiti Github Heroku paketi za izradu. Moja je teorija bila da bi neki paket za izradu Herokua sadržavao binarne datoteke koje sam trebao. Na kraju me potraga dovela ovdje. Skinula sam i raspakirala 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 slips binarni! Radi li to?

./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 - znači trebalo bi raditi! Ugradimo ovu binarnu datoteku ~/bin/slirp:

cp slirp ~/bin/slirp

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

Konfiguracija mreže

Sada postavimo mrežu na našem gostujućem kernelu. Ažurirajmo parametre 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 potrebno za rad ifconfig, koji postavlja mrežno sučelje za komunikaciju sa Slipom. Tim route postavlja tablicu usmjeravanja kernela da prisili sav promet da se šalje kroz Slirp tunel. Provjerimo ovo pomoću DNS upita:

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

Djeluje!

Napomena prema .: Očigledno je izvorni post napisan na radnoj površini sa žičnom mrežnom karticom ili nekom drugom konfiguracijom koja ne zahtijeva dodatne upravljačke programe. Na prijenosnom računalu s WiFi 8265 od Intela dolazi do pogreš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
/ #

Čini se da kernel ne može komunicirati s upravljačkim programom mrežne kartice. Pokušaj kompajliranja firmvera u kernel, nažalost, nije popravio situaciju. U vrijeme objave nije bilo moguće pronaći rješenje u ovoj konfiguraciji. Na jednostavnijim konfiguracijama (na primjer, u Virtualboxu), sučelje se podiže ispravno.

Automatizirajmo preusmjeravanje pomoću sljedeće skripte ljuske:

#!/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 izvršnim:

chmod +x init.sh

Zatim ćemo promijeniti naredbeni redak jezgre:

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 datoteka

Da vam olakšam provjeru svega ovoga, prikupio sam dockerfile, koji automatizira većinu opisanih koraka i trebao bi vam dati radnu konfiguraciju. također imam unaprijed konfigurirana jezgra, koji ima sve što je opisano u postu. Ali važno je razumjeti da sam ovdje naveo samo minimalne postavke.

Nadam se da vam je ovaj post pomogao razumjeti kako podići gostujući kernel. Ispostavilo se da je to neka vrsta čudovišta, ali publikacija je zamišljena kao sveobuhvatan vodič o izgradnji, instaliranju i konfiguriranju korisničkog načina rada u Linuxu pod modernim verzijama operativnih sustava ove obitelji. Sljedeći koraci trebali bi uključivati ​​instaliranje usluga i drugog softvera koji se već nalazi unutar sustava za goste. Budući da su slike Docker spremnika samo objavljene arhive, trebali biste moći izdvojiti sliku putem docker export, a zatim odredite njegovu instalacijsku stazu u korijenu datotečnog sustava gostujućeg kernela. Pa, onda izvršite skriptu ljuske.

Posebna zahvala Rkeeneu iz #lobsters na Freenodeu. Bez njegove pomoći u otklanjanju pogrešaka u Slirpu, ne bih stigao ovako daleko. Nemam pojma kako njegov Slackware sustav radi ispravno sa slirpom, ali moj Ubuntu i Alpine sustavi 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