كيفية بدء استخدام وضع المستخدم في Linux

مقدمة من المترجم: على خلفية الدخول المكثف لأنواع مختلفة من الحاويات إلى حياتنا ، قد يكون من الممتع والمفيد للغاية معرفة التقنيات التي بدأها كل شيء مرة واحدة. يمكن استخدام بعضها بشكل مفيد حتى يومنا هذا ، ولكن لا يتذكر الجميع مثل هذه الأساليب (أو يعرف ما إذا لم يتم القبض عليهم أثناء تطورهم السريع). إحدى هذه التقنيات هي User Mode Linux. قام مؤلف النسخة الأصلية بالكثير من البحث ، واكتشف أيًا من التطورات القديمة لا يزال يعمل وأيها لا يعمل ، وقام بتجميع شيء مثل التعليمات خطوة بخطوة حول كيفية الحصول على البيرة المحلية UML في 2k19. ونعم ، قمنا بدعوة مؤلف المنشور الأصلي إلى هبر كادي، لذلك إذا كان لديك أي أسئلة - اسأل باللغة الإنجليزية في التعليقات.

كيفية بدء استخدام وضع المستخدم في Linux

يعد وضع المستخدم في Linux ، في الواقع ، منفذًا لنواة Linux نفسها. يتيح لك هذا الوضع تشغيل نواة Linux كاملة كعملية مستخدم ويستخدمها المطورون بشكل شائع لاختبار برامج التشغيل. لكن هذا الوضع مفيد أيضًا كأداة عزل عامة ، يشبه مبدأه تشغيل الأجهزة الافتراضية. يوفر هذا الوضع عزلاً أكثر من Docker ، ولكنه أقل من جهاز افتراضي كامل مثل KVM أو Virtual Box.

بشكل عام ، قد يبدو وضع المستخدم كأداة غريبة وصعبة الاستخدام ، ولكن لا يزال لها استخدامات. بعد كل شيء ، هذه نواة Linux كاملة تعمل من مستخدم غير متميز. تسمح هذه الميزة بتشغيل التعليمات البرمجية التي يُحتمل أن تكون غير موثوق بها دون أي تهديد للجهاز المضيف. وبما أن هذه نواة كاملة ، فإن عملياتها معزولة عن الجهاز المضيف ، أي لن تكون العمليات التي تعمل داخل وضع المستخدم مرئية للمضيف. هذا ليس مثل حاوية Docker المعتادة ، وفي هذه الحالة يرى الجهاز المضيف دائمًا العمليات داخل المستودع. انظر إلى هذه القطعة من pstree من أحد خوادمي:

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

وقارن هذا مع pstree من Linux kernel في وضع المستخدم:

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

عند العمل مع حاويات Docker ، يمكنني أن أرى من المضيف أسماء العمليات التي تعمل في الضيف. مع وضع مستخدم Linux ، هذا غير ممكن. ماذا يعني ذلك؟ هذا يعني أن أدوات المراقبة التي تعمل من خلال نظام Linux الفرعي للتدقيق لا أرى العمليات التي تعمل في نظام الضيف. لكن في بعض الحالات ، يمكن أن تصبح هذه الميزة سيفًا ذا حدين.

بشكل عام ، المنشور بأكمله أدناه عبارة عن مجموعة من الأبحاث والمحاولات التقريبية لتحقيق النتيجة المرجوة. للقيام بذلك ، كان علي استخدام العديد من الأدوات القديمة ، وقراءة مصادر النواة ، وإجراء تصحيح مكثف للرمز المكتوب في الأيام التي كنت لا أزال فيها في المدرسة الابتدائية ، وكذلك العبث ببنيات Heroku باستخدام ثنائي خاص للعثور على الأدوات التي أحتاجها . قاد كل هذا العمل الرجال في IRC إلى مناداتي بالسحر. آمل أن يكون هذا المنشور بمثابة توثيق موثوق به لشخص ما لتجربة نفس الشيء مع إصدارات أحدث من أنظمة التشغيل وأنظمة التشغيل.

تعديل

يتم إعداد وضع مستخدم Linux بعدة خطوات:

  • تثبيت التبعيات على المضيف ؛
  • تنزيل Linux kernel ؛
  • تكوين بناء النواة ؛
  • تجميع النواة
  • التثبيت الثنائي
  • تكوين نظام ملفات الضيف ؛
  • اختيار معلمات إطلاق النواة ؛
  • إنشاء شبكة ضيف ؛
  • بدء نواة الضيف.

أفترض أنك إذا قررت أن تفعل ذلك بنفسك ، فمن المرجح أنك ستفعل كل ما هو موصوف في بعض أنظمة Ubuntu أو Debian. حاولت تطبيق كل ما سبق في توزيعة المفضلة - Alpine ، لكن لم يحدث شيء ، على ما يبدو بسبب حقيقة أن Linux kernel يحتوي على glibc-isms للسائقين في وضع المستخدم. أخطط لإبلاغ المنبع بهذا الأمر بعد أن فهمت المشكلة أخيرًا.

تثبيت التبعيات على المضيف

يتطلب Ubuntu الحزم التالية على الأقل لبناء نواة Linux (بافتراض تثبيت نظيف):

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

يمكنك تثبيتها بالأمر التالي (كجذر أو sudo):

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

لاحظ أن تشغيل برنامج إعداد قائمة Linux kernel سيتطلب تثبيت libncurses-dev. يرجى التأكد من تثبيته بالأمر التالي (كجذر أو مع sudo):

apt-get -y install libncurses-dev

تنزيل Kernel

حدد مكان التنزيل ثم قم ببناء النواة. لهذه العملية ، ستحتاج إلى تخصيص حوالي 1,3 جيجابايت من مساحة القرص الثابت ، لذا تأكد من توفرها لديك.

بعد الذهاب إلى kernel.org واحصل على عنوان URL لتنزيل أحدث نواة مستقرة. في وقت كتابة هذا التقرير: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

قم بتنزيل هذا الملف باستخدام 'wget':

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

واستخرجها مع 'tar':

tar xJf linux-5.1.16.tar.xz

الآن ندخل إلى الدليل الذي تم إنشاؤه عند تفريغ tarball:

cd linux-5.1.16

إعداد بناء النواة

نظام بناء النواة عبارة عن مجموعة ميكيفيلز с الكثير أدوات ونصوص مخصصة لأتمتة العملية. أولاً ، افتح برنامج الإعداد التفاعلي:

make ARCH=um menuconfig

سيتم إنشاء مربع حوار وعرضه جزئيًا لك. متى '[Select]'، ستتمكن من التهيئة باستخدام مفتاحي Space أو Enter. تنقل عبر النافذة ، كالعادة ، باستخدام سهمي لوحة المفاتيح "لأعلى" و "لأسفل" ، وحدد العناصر - "يسار" أو "يمين".

مؤشر العرض -> يعني أنك في قائمة فرعية ، يمكن الوصول إليها عن طريق الضغط على مفتاح Enter. من الواضح أن طريقة الخروج منه هي من خلال "[Exit]".

قم بتضمين الخيارات التالية في "[Select]وتأكد من وجود "[*]" بجوارهم:

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

هذا كل شيء ، يمكنك الخروج من هذه النافذة عن طريق تحديد "[Exit]". فقط تأكد من مطالبتك بحفظ التكوين في النهاية وتحديد "[Yes]".

أوصي بأن تتلاعب بخيارات بناء النواة بعد قراءة هذا المنشور. من خلال هذه التجارب ، يمكنك تعلم الكثير من حيث فهم عمل ميكانيكا النواة منخفضة المستوى وتأثير الأعلام المختلفة على تجميعها.

بناء النواة

نواة Linux هي برنامج كبير يقوم بالعديد من الأشياء. حتى مع وجود مثل هذا الحد الأدنى من التكوين على الأجهزة القديمة ، يمكن أن يستغرق البناء بعض الوقت. لذلك قم ببناء النواة بالأمر التالي:

make ARCH=um -j$(nproc)

لماذا؟ سيخبر هذا الأمر الباني الخاص بنا باستخدام جميع النوى والخيوط المتوفرة في وحدة المعالجة المركزية في عملية الإنشاء. فريق $(nproc) في نهاية Build يستبدل إخراج الأمر nproc، وهو جزء من coreutils في بناء Ubuntu قياسي.

بعد مرور بعض الوقت ، سيتم تجميع النواة الخاصة بنا في ملف قابل للتنفيذ ./linux.

تثبيت الثنائي

نظرًا لأن User Mode في Linux ينشئ ثنائيًا عاديًا ، يمكنك تثبيته مثل أي أداة مساعدة أخرى. إليك كيف فعلت ذلك:

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

من الجدير أيضًا التأكد من ذلك ~/bin هو في الخاص بك $PATH:

export PATH=$PATH:$HOME/bin

إعداد نظام ملفات الضيف

قم بإنشاء دليل لنظام ملفات الضيف:

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

افتح alpinelinux.org وفي قسم التحميل ابحث عن رابط التنزيل الفعلي MINI ROOT FILESYSTEM. في وقت كتابة هذا التقرير كان:

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

قم بتنزيل Tarball باستخدام 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

أدخل الآن دليل نظام ملفات الضيف واستخرج الأرشيف:

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

ستؤدي الإجراءات الموصوفة إلى إنشاء قالب نظام ملفات صغير. نظرًا لطبيعة النظام ، سيكون من الصعب للغاية تثبيت الحزم من خلال Alpine apk manager. لكن هذا العرض التقديمي سيكون كافياً لتقييم الفكرة العامة.

نحتاج أيضًا إلى أداة تيني للحد من استهلاك الذاكرة عمليات الزومبي نواة ضيفنا.

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

إنشاء سطر أوامر kernel

تحتوي نواة Linux ، مثل معظم البرامج الأخرى ، على وسيطات سطر أوامر يمكن الوصول إليها عن طريق تحديد المفتاح --help.

نفسه - مساعدة

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.

تسلط هذه اللوحة الضوء على المعالم الرئيسية لعملية الإطلاق. لنقم بتشغيل النواة مع الحد الأدنى المطلوب من مجموعة الخيارات:

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

تخبر الأسطر أعلاه نواةنا بما يلي:

  • افترض أن نظام ملفات الجذر هو جهاز زائف /dev/root.
  • أختر هوستفس كسائق نظام ملفات جذر.
  • قم بتركيب نظام ملفات الضيف الذي أنشأناه على جهاز الجذر.
  • ونعم ، في وضع القراءة والكتابة.
  • استخدم 64 ميجابايت فقط من ذاكرة الوصول العشوائي (يمكنك استخدام أقل بكثير اعتمادًا على ما تخطط للقيام به ، ولكن يبدو أن سعة 64 ميجابايت هي المقدار الأمثل).
  • يبدأ النواة تلقائيًا /bin/sh كيف init-عملية.

قم بتشغيل هذا الأمر ويجب أن تحصل على شيء مثل ما يلي:

ورقة أخرى

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

التلاعب أعلاه سوف يعطينا نظام الضيف كحد أدنى، بدون أشياء مثل /proc أو اسم مضيف معين. على سبيل المثال ، جرب الأوامر التالية:

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

لتسجيل الخروج من الضيف ، اكتب exit أو اضغط على control-d. هذا سيقتل القشرة متبوعًا بذعر النواة:

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

لقد شعرنا بذعر النواة هذا لأن Linux kernel يعتقد أن عملية التهيئة تعمل دائمًا. بدونها ، لا يمكن للنظام أن يعمل ويتعطل. ولكن نظرًا لأن هذه عملية في وضع المستخدم ، فإن المخرجات الناتجة ترسل نفسها إلى SIGABRT، مما ينتج عنه إخراج.

إعداد شبكة الضيف

وهذا هو المكان الذي تبدأ فيه الأمور في السوء. الشبكات في وضع المستخدم Linux هو المكان الذي يبدأ فيه المفهوم الكامل لـ "وضع المستخدم" المحدود في الانهيار. بعد كل شيء ، عادة على مستوى النظام ، تكون الشبكة محدودة ذو امتياز أوضاع التنفيذ لأسباب مفهومة لنا جميعًا.

ملحوظة. لكل.: يمكنك قراءة المزيد حول الخيارات المختلفة للعمل مع شبكة في UML هنا.

رحلة إلى Slirp

ومع ذلك ، هناك أداة قديمة وغير مدعومة تقريبًا تسمى زلق، التي يمكن أن يتفاعل معها وضع المستخدم Linux مع الشبكة. إنه يشبه إلى حد كبير مكدس TCP / IP على مستوى المستخدم ولا يتطلب أي أذونات نظام للتشغيل. كانت هذه الأداة صدر في عام 1995، وآخر تحديث مؤرخ سنة 2006. Slirp قديم جدًا. خلال الوقت الذي لم يكن فيه الدعم والتحديثات ، ذهب المترجمون إلى حد أنه لا يمكن وصف هذه الأداة الآن إلا على أنها تعفن رمز.

لنقم بتنزيل Slirp من مستودعات Ubuntu ونحاول تشغيله:

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)

يا آلهة. دعنا نثبِّت مصحح أخطاء Slirp ونرى ما إذا كان بإمكاننا اكتشاف ما يحدث هنا:

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.

الخطأ يدق فينا هذا الخط. لنلقِ نظرة على تتبع المكدس ، ربما سيساعدنا شيء ما هناك:

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

هنا نرى أن الانهيار يحدث أثناء بدء الحلقة الرئيسية عندما يحاول slirp التحقق من المهلات. في هذه المرحلة ، كان علي التخلي عن محاولة التصحيح. ولكن دعونا نرى ما إذا كان Slirp المبني من نوع ما يعمل. أعدت تنزيل الأرشيف مباشرة من الموقع سورس، لأن سحب شيء ما من هناك عبر سطر الأوامر يمثل ألمًا:

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

نرى هنا تنبيهات حول الوظائف المضمنة غير المحددة ، أي حول عدم القدرة على ربط الملف الثنائي الناتج. يبدو أنه بين عام 2006 وحتى هذه المرحلة ، توقف مجلس التعاون الخليجي عن إنتاج الرموز المستخدمة في الوظائف المدمجة للملفات المترجمة الوسيطة. دعنا نحاول استبدال الكلمة الأساسية inline على تعليق فارغ وانظر إلى النتيجة:

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

لا. هذا لا يعمل أيضا. لا يزال يتعذر العثور على رموز لهذه الوظائف.

في هذه المرحلة ، استسلمت وبدأت أبحث عن جيثب حزم بناء Heroku. كانت نظريتي أن بعض حزم بناء Heroku ستحتوي على الثنائيات التي أحتاجها. في النهاية ، قادني البحث هنا. لقد قمت بتنزيلها وتفكيكها uml.tar.gz ووجدت ما يلي:

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*

هذا هو ثنائي Slirp! هل يعمل؟

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

لا تتعطل - لذا يجب أن تعمل! دعونا نزرع هذا الثنائي في ~/bin/slirp:

cp slirp ~/bin/slirp

في حالة قيام منشئ الحزمة بإزالتها ، أنا صنع مرآة.

تكوين شبكة

لنقم الآن بإعداد الشبكة على نواة الضيف. تحديث خيارات التشغيل:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/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

أول أمرين تكوين /proc и /sys ضروري للعمل ifconfig، والذي يحدد واجهة الشبكة للتواصل مع Slirp. فريق route يضبط جدول توجيه kernel لإجبار كل حركة المرور على الإرسال عبر نفق Slirp. دعنا نتحقق من ذلك باستخدام استعلام 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

Работает!

ملاحظة لكل: على ما يبدو ، تمت كتابة المنشور الأصلي على سطح مكتب باستخدام بطاقة شبكة سلكية ، أو بعض التكوينات الأخرى التي لا تتطلب برامج تشغيل إضافية. على جهاز كمبيوتر محمول مزود بشبكة WiFi 8265 من Intel ، يحدث خطأ عند رفع الشبكة

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

على ما يبدو ، لا يمكن لـ kernel الاتصال ببرنامج تشغيل بطاقة الشبكة. محاولة تجميع البرامج الثابتة في النواة ، للأسف ، لم تصلح الموقف. في وقت النشر ، لم يكن من الممكن إيجاد حل في هذا التكوين. في التكوينات الأبسط (على سبيل المثال ، في Virtualbox) ، ترتفع الواجهة بشكل صحيح.

لنقم بأتمتة عملية إعادة التوجيه باستخدام برنامج شل النصي التالي:

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

ووضع علامة عليه قابل للتنفيذ:

chmod +x init.sh

وبعد ذلك سنقوم بإجراء تغييرات على سطر أوامر kernel:

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

ودعونا نكرر:

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

الشبكة مستقرة!

ملف عامل ميناء

لتسهيل التحقق من كل هذا ، فقد جمعت Dockerfile، والذي يقوم بأتمتة معظم الخطوات الموضحة ويجب أن يوفر لك تكوينًا عمليًا. لدي أيضا نواة مسبقة التكوين، والتي تحتوي على كل ما تم وصفه في المنشور. لكن من المهم أن نفهم أنني هنا أوجزت فقط الحد الأدنى من الإعداد.

آمل أن يكون هذا المنشور قد ساعدك في فهم كيفية رفع نواة الضيف. اتضح أنه نوع من الوحش ، ولكن تم تصميم المنشور كدليل شامل حول إنشاء وتثبيت وتكوين وضع المستخدم في Linux في ظل الإصدارات الحديثة من أنظمة التشغيل لهذه العائلة. يجب أن تتضمن الخطوات التالية تثبيت الخدمات والبرامج الأخرى الموجودة بالفعل داخل نظام الضيف. نظرًا لأن صور حاوية Docker هي مجرد كرات قطران معلنة ، يجب أن تكون قادرًا على استخراج الصورة عبر docker export، ثم حدد مسار التثبيت في جذر نظام ملفات الضيف kernel. حسنًا ، قم بتنفيذ البرنامج النصي shell.

شكر خاص لـ Rkeene من #lobsters على Freenode. بدون مساعدته في تصحيح أخطاء Slirp ، لم أكن لأصل إلى هذا الحد. ليس لدي أي فكرة عن كيفية عمل نظام Slackware الخاص به بشكل صحيح مع slirp ، لكن أنظمة Ubuntu و Alpine الخاصة بي لم تقبل Slirp واقترحني Rkeene الثنائي. لكن يكفي بالنسبة لي أن شيئًا ما يناسبني على الأقل.

المصدر: www.habr.com

إضافة تعليق