Kiel Komenci Uzi Uzantan Reĝimon en Linukso

Enkonduko de la tradukisto: Kontraŭ la fono de la amasa eniro de diversaj specoj de ujoj en niajn vivojn, povas esti sufiĉe interese kaj utile ekscii per kiaj teknologioj ĉi tio iam komenciĝis. Kelkaj el ili povas esti utile uzataj ĝis hodiaŭ, sed ne ĉiuj memoras tiajn metodojn (aŭ scias, ĉu ili ne estis kaptitaj dum ilia rapida disvolviĝo). Unu tia teknologio estas Uzanta Reĝimo Linukso. La aŭtoro de la originalo faris sufiĉe da fosado, eltrovante, kiu el la malnovaj evoluoj ankoraŭ funkcias kaj kiuj ne, kaj kunmetis ion similan al paŝo post paŝo instrukcioj pri kiel krei memfaritan UML en vi mem. 2k19. Kaj jes, ni invitis la aŭtoron de la originala afiŝo al Habr Cadey, do se vi havas demandojn, demandu angle en la komentoj.

Kiel Komenci Uzi Uzantan Reĝimon en Linukso

Uzanta Reĝimo en Linukso estas, fakte, haveno de la Linukso-kerno al si mem. Ĉi tiu reĝimo permesas al vi ruli plenan Linuksan kernon kiel uzantprocezon kaj estas ofte uzata de programistoj por testi ŝoforojn. Sed ĉi tiu reĝimo ankaŭ estas utila kiel ilo por ĝenerala izolado, kies principo estas simila al la funkciado de virtualaj maŝinoj. Ĉi tiu reĝimo disponigas pli da izoliteco ol Docker, sed malpli ol plentaŭga virtuala maŝino kiel KVM aŭ Virtual Box.

Ĝenerale, Uzanta Reĝimo povas ŝajni stranga kaj malfacila ilo por uzi, sed ĝi havas siajn uzojn. Post ĉio, ĉi tio estas plentaŭga Linukso-kerno funkcianta kiel senprivilegia uzanto. Ĉi tiu funkcio permesas eble nefiditan kodon funkcii sen ajna minaco al la gastiga maŝino. Kaj ĉar ĉi tio estas plentaŭga kerno, ĝiaj procezoj estas izolitaj de la gastiga maŝino, tio estas procezoj kurantaj en Uzanta Reĝimo ne estos videblaj por la gastiganto. Ĉi tio ne similas al tradicia Docker-ujo, en kiu la gastiga maŝino ĉiam vidas la procezojn ene de la stokado. Rigardu ĉi tiun pecon de pstree de unu el miaj serviloj:

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

Kaj komparu ĉi tion kun la pstree de la Linukso-kerno en Uzanta Reĝimo:

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

Kiam mi laboras kun Docker-ujoj, mi povas vidi de la gastiganto la nomojn de la procezoj, kiuj funkcias en la gasto. Ĉi tio ne eblas kun Linukso-Uzantreĝimo. Kion ĝi signifas? Ĉi tio signifas, ke monitoraj iloj funkcias tra la revizia subsistemo de Linukso ne vidas procezoj kurantaj en la gastsistemo. Sed en iuj situacioj ĉi tiu funkcio povas esti dutranĉa glavo.

Ĝenerale, la tuta afiŝo sube estas kolekto de esploroj kaj malglataj provoj atingi la deziratan rezulton. Por fari tion, mi devis uzi diversajn antikvajn ilojn, legi kernajn fontojn, okupiĝi pri intensa senararigado de kodo skribita kiam mi estis ankoraŭ en la bazlernejo, kaj ankaŭ tuŝi Heroku-konstruaĵojn uzante specialan binaron serĉante la ilojn, kiujn mi bezonis. Ĉio ĉi tiu laboro kondukis al la uloj sur mia IRC nomis min magiisto. Mi esperas, ke ĉi tiu afiŝo servos kiel fidinda dokumentaro por ke iu faru la samon, sed kun pli novaj kernoj kaj OS-versioj.

alĝustigo

Agordi Linuksan Uzantan Reĝimon implikas plurajn paŝojn:

  • instali dependecojn sur la gastiganto;
  • elŝuti la Linukso-kernon;
  • agordo de kerno;
  • kerno asembleo;
  • instali la binaron;
  • starigi la gastdosiersistemon;
  • elekto de kernaj lanĉaj parametroj;
  • starigi gastan reton;
  • lanĉante la gastkernon.

Mi supozas, ke se vi decidas fari ĉion ĉi mem, plej verŝajne vi faros ĉion priskribitan en iu Ubuntu aŭ Debian-simila sistemo. Mi provis efektivigi ĉion supre en mia plej ŝatata distribuo - Alpine, sed nenio funkciis, ŝajne ĉar la Linukso-kerno estas forte ligita al glibc-ismoj por ŝoforoj en Uzanta Reĝimo. Mi planas raporti tion al kontraŭfluo post kiam mi finfine eltrovas la problemon.

Instalado de dependecoj sur la gastiganto

Ubuntu postulas almenaŭ la sekvajn pakaĵojn por konstrui la Linuksan kernon (supozante puran instalon):

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

Vi povas instali ilin per la sekva komando (kiel radiko aŭ per sudo):

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

Bonvolu noti, ke ruli la menuan personigoprogramon por la Linukso-kerno postulos instaladon libncurses-dev. Bonvolu certigi, ke ĝi estas instalita per la sekva komando (kiel radiko aŭ uzante sudo):

apt-get -y install libncurses-dev

Elŝutante la kernon

Determini kie elŝuti kaj poste konstrui la kernon. Vi devos asigni proksimume 1,3 GB da malmola disko spaco por ĉi tiu operacio, do certigu, ke vi havas ĝin.

Tiam iru al kernel.org kaj ricevu la URL por elŝuti la plej novan stabilan kernan version. Al la horo de skribi ĉi tiun afiŝon: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Elŝutu ĉi tiun dosieron uzante 'wget':

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

Kaj ĉerpi ĝin per 'tar':

tar xJf linux-5.1.16.tar.xz

Nun ni eniras la dosierujon kreitan kiam malpakigas la tarball:

cd linux-5.1.16

Agordante kernan konstruon

La kerna konstrusistemo estas aro Faru dosierojn с multaj kutimaj iloj kaj skriptoj por aŭtomatigi la procezon. Por komenci, malfermu la interretan agordan programon:

make ARCH=um menuconfig

Ĝi parte kompletigos la asembleon kaj montros dialogujon por vi. Kiam la lumo aperas ĉe la fundo de la fenestro[Select]', vi povas agordi la agordojn per la Spacbreto aŭ Enigu klavojn. Navigado ĉirkaŭ la fenestro estas kiel kutime uzante la klavarajn sagojn "supren" kaj "malsupren", kaj elektado de elementoj estas "maldekstre" aŭ "dekstre".

La vido-indikilo -> signifas, ke vi estas en submenuo, kiun oni povas aliri per la Enigu klavon. La elirejo estas evidente tra '[Exit]'.

Enmetu la jenajn opciojn en '[Select]' kaj certigu, ke estas simbolo '[*]' apud ili:

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

Jen ĝi, vi povas eliri ĉi tiun fenestron sinsekve elektante '[Exit]'. Nur certigu, ke ĉe la fino oni petas vin konservi la agordon kaj elektu '[Yes]'.

Mi rekomendas vin ludi kun la kernaj konstruopcioj post legi ĉi tiun afiŝon. El ĉi tiuj eksperimentoj vi povas lerni multon pri kiel funkcias malaltnivelaj kernaj mekanikoj kaj kiel malsamaj flagoj influas kiel la kerno estas konstruita.

Konstruante la kernon

La Linukso-kerno estas granda programo kiu faras multajn aferojn. Eĉ kun ĉi tiu minimuma agordo sur pli malnova aparataro, muntado povas preni sufiĉe da tempo. Do konstruu la kernon uzante la jenan komandon:

make ARCH=um -j$(nproc)

Por kio? Ĉi tiu komando diros al nia konstruanto uzi ĉiujn disponeblajn CPU-kernojn kaj fadenojn dum la konstruprocezo. Teamo $(nproc) ĉe la fino de Konstruo enigas la eligon de la komando nproc, kiu estas parto coreutils en la norma Ubuntu-konstruaĵo.

Post iom da tempo, nia kerno estos kompilita en plenumeblan dosieron ./linux.

Instalante la binaron

Ĉar Uzanta Reĝimo en Linukso kreas regulan binaron, vi povas instali ĝin kiel ajnan alian ilon. Jen kiel mi faris ĝin:

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

Ankaŭ indas certigi tion ~/bin estas en via $PATH:

export PATH=$PATH:$HOME/bin

Agordante la Gastan Dosiersistemon

Kreu dosierujon por la gastdosiersistemo:

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

Malfermu alpinelinux.org kaj en elŝuta sekcio trovi la nunan elŝutan ligon MINI ROOT FILESYSTEM. Dum la skribado ĉi tio estis:

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

Elŝutu ĉi tiun tarball uzante 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

Nun enigu la gastdosiersisteman dosierujon kaj malpaku la arkivon:

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

La priskribitaj paŝoj kreos malgrandan dosiersisteman ŝablonon. Pro la maniero kiel la sistemo funkcias, instali pakaĵojn per la Alpine apk-administranto estos ege malfacila. Sed ĉi tiu FS sufiĉos por taksi la ĝeneralan ideon.

Ni ankaŭ bezonas ilon tini ĉesigi memorkonsumon zombiaj procezoj nia gastkerno.

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

Kreante Kernel-Komandlinion

La Linukso-kerno, kiel plej multaj aliaj programoj, havas komandliniajn argumentojn alireblajn specifante la ŝlosilon. --help.

Li mem — helpu

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.

Ĉi tiu panelo elstarigas la ĉefajn lanĉajn parametrojn. Ni rulu la kernon kun la minimuma bezonata aro de opcioj:

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

La supraj linioj rakontas al nia kerno la jenon:

  • Ni supozu, ke la radika dosiersistemo estas pseŭda aparato /dev/root.
  • Elektu gastigantoj kiel radika dosiersistema pelilo.
  • Muntu la gastdosiersistemon, kiun ni kreis sur la radika aparato.
  • Kaj jes, en lego-skriba reĝimo.
  • Uzu nur 64 megabajtojn da RAM (vi povas uzi multe malpli depende de tio, kion vi planas fari, sed 64 MB ŝajnas esti la optimuma kvanto).
  • La kerno aŭtomate komenciĝas /bin/sh kiom init-procezo.

Rulu ĉi tiun komandon kaj vi devus ricevi ion kiel la jenan:

Alia folio

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

La supraj manipuladoj donos al ni minimuma gastsistemo, sen aferoj kiel /proc aŭ asignita gastnomo. Ekzemple, provu la jenajn komandojn:

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

Por elsaluti el la gastsistemo, enigu exit aŭ premu kontrolo-d. Ĉi tio pafos la ŝelon sekvitan de kerna paniko:

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

Ni ricevis ĉi tiun kernan panikon ĉar la Linukso-kerno opinias, ke la komenca procezo ĉiam funkcias. Sen ĝi, la sistemo ne plu povas funkcii kaj malŝaltas. Sed ĉar ĉi tio estas uzantreĝima procezo, la rezulta rezulto sendas sin al SIGABRT, kiu kondukas al la elirejo.

Starigante gastan reton

Sed ĉi tie la aferoj komencas malbone por ni. Retigado en Uzantreĝimo Linukso estas kie la tuta koncepto de limigita "uzantreĝimo" komencas disfali. Post ĉio, la reto estas kutime limigita je la sistemnivelo privilegiita ekzekutreĝimoj pro evidentaj kialoj al ni ĉiuj.

Notu per.: Vi povas legi pli pri malsamaj ebloj por labori kun reto en UML tie.

Vojaĝo al slirp

Tamen, ekzistas antikva kaj preskaŭ nesubtenata ilo nomata Slirp, kun kiu Uzanta Reĝimo Linukso povas interagi kun la reto. Ĝi funkcias proksimume kiel uzantnivela TCP/IP-stako kaj ne postulas iujn ajn sistemajn permesojn por funkcii. Ĉi tiu ilo estis liberigita en 1995, kaj la lasta ĝisdatigo estas datita 2006. Slirp estas tre maljuna. Dum la tempo sen subteno kaj ĝisdatigoj, kompililoj venis tiom longe, ke nun ĉi tiu ilo povas esti priskribita nur kiel "kodputro".

Do, ni elŝutu Slirp el la Ubuntu-deponejoj kaj provu ruli ĝin:

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)

Ho miaj dioj. Ni instalu la erarserĉilon Slirp kaj vidu ĉu ni povas ekscii, kio okazas ĉi tie:

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.

La eraro batas nin ĉi tiu linio. Ni rigardu la stakspuron, eble io helpos nin tie:

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

Ĉi tie ni vidas, ke la kraŝo okazas dum la ekfunkciigo de la ĉefa buklo, kiam slirp provas kontroli la tempodaŭrojn. Ĝuste en ĉi tiu momento mi devis rezigni provi sencimigi. Sed ni vidu ĉu Slirp, konstruita el specoj, funkcias. Mi reelŝutis la arkivon rekte de la retejo Fonto, ĉar treni ion de tie per la komandlinio estas doloro:

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

Ĉi tie ni vidas atentigojn pri nedifinitaj enkonstruitaj funkcioj, tio estas, pri la neebleco ligi la rezultan binaran dosieron. Ŝajnas, ke inter 2006 kaj nun gcc ĉesis krei simbolojn uzatajn en konstruitaj mezaj funkcioj. Ni provu anstataŭigi la ŝlosilvorton inline al malplena komento kaj rigardu la rezulton:

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

Ne. Ĉi tio ankaŭ ne funkcias. Ankoraŭ ne povas trovi simbolojn por ĉi tiuj funkcioj.

Je ĉi tiu punkto mi rezignis kaj komencis serĉi sur Github Heroku konstrui pakaĵojn. Mia teorio estis, ke iu Heroku-konstrupakaĵo enhavus la binarojn, kiujn mi bezonis. Fine mia serĉado kondukis min ĉi tie. Mi elŝutis kaj malpakis uml.tar.gz kaj trovis la jenon:

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*

Ĉi tio estas slirp duuma! Ĉu ĝi funkcias?

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

Ĝi ne falas - do ĝi devus funkcii! Ni plantu ĉi tiun binaron en ~/bin/slirp:

cp slirp ~/bin/slirp

Se la kreinto de la pakaĵo forigas ĝin, mi faris spegulon.

Reta agordo

Nun ni agordu la reton sur nia gastkerno. Ni ĝisdatigu la lanĉajn parametrojn:

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

Nun ni ebligu la reton:

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

La unuaj du agordaj komandoj /proc и /sys necesa por laboro ifconfig, kiu starigas retan interfacon por komuniki kun Slirp. Teamo route starigas la kernan vojigtabelon por devigi la tutan trafikon esti sendita tra la Slirp-tunelo. Ni kontrolu ĉi tion per DNS-demando:

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

Ĝi funkcias!

Noto per.: Ŝajne, la originala afiŝo estis skribita sur labortablo kun kablita retkarto, aŭ iu alia agordo kiu ne postulas pliajn ŝoforojn. Sur tekkomputilo kun WiFi 8265 de Intel, eraro okazas kiam oni altigas la reton

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

Ŝajne, la kerno ne povas komuniki kun la reta stirado. Provo kompili la firmvaro en la kernon, bedaŭrinde, ne korektis la situacion. En la momento de la publikigo, neniu solvo estis ankoraŭ trovita en ĉi tiu aparta agordo. Ĉe pli simplaj agordoj (ekzemple, en Virtualbox), la interfaco estas levita ĝuste.

Ni aŭtomatigu la alidirekton uzante la sekvan ŝelan skripton:

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

Kaj marku ĝin kiel plenumebla:

chmod +x init.sh

Kaj tiam ni faru ŝanĝojn al la komandlinio de la kerno:

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

Kaj ni ripetu:

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

La reto estas stabila!

docker dosiero

Por faciligi al vi kontroli ĉion ĉi, mi kolektis dockerfile, kiu aŭtomatigas la plej multajn el la priskribitaj paŝoj kaj devus provizi al vi funkciantan agordon. Mi ankaŭ havas preta kerna agordo, kiu enhavas ĉion priskribitan en la afiŝo. Sed gravas kompreni, ke ĉi tie mi skizis nur la minimumajn agordojn.

Mi esperas, ke ĉi tiu afiŝo helpis vin kompreni kiel alporti gastan kernon. Ĝi montriĝis esti ia monstro, sed la publikigo estis intencita esti ampleksa gvidilo pri la temo kunmeti, instali kaj agordi Uzantan Reĝimon en Linukso sub modernaj versioj de operaciumoj de ĉi tiu familio. Postaj paŝoj devus inkluzivi instali servojn kaj aliajn programojn jam ene de la gastsistemo. Ĉar Docker-ujo-bildoj estas nur reklamitaj tarballs, vi devus povi ĉerpi la bildon per docker export, kaj poste determinu la vojon por instali ĝin en la radiko de la gastkerna dosiersistemo. Nu, tiam rulu la ŝelan skripton.

Specialan dankon al Rkeene de #lobsters sur Freenode. Sen lia helpo en senararigado de Slirp, mi ne estus atinginta ĉi tien. Mi tute ne scias kiel lia Slackware-sistemo funkcias ĝuste kun slirp, sed miaj Ubuntu kaj Alpaj sistemoj ne akceptis slirp kaj la binara Rkeene sugestis al mi. Sed sufiĉas por mi, ke almenaŭ io funkcias por mi.

fonto: www.habr.com

Aldoni komenton