SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-09-08

ما الذي يتغير في sudoers مع sudo-rs على Ubuntu 26.04؟

تجعل Ubuntu 26.04 sudo-rs الافتراضي: قواعد wildcard لوسائط الأوامر لا تعود متطابقة. تعرّف على الصيغة البديلة وما الذي يحدث عند الترقية.

ما الذي يتغير مع sudo-rs على Ubuntu

تأتي Ubuntu 26.04 LTS مع sudo-rs بوصفه sudo الافتراضي، لذلك ينفّذ الأمر sudo على خادم جديد إعادةَ التنفيذ المكتوبة بلغة Rust بدلاً من البرنامج الأصلي المكتوب بلغة C. تستمر معظم ملفات sudoers في العمل كما كانت تماماً. والقاعدة التي تتعطل هي التي تحتوي على حرف بدل wildcard ضمن وسائط أمر، لأن sudo-rs لا يطابق أنماط glob مع نص الوسائط.

أجرت Ubuntu 25.10 التغيير أولاً، ثم أبقت عليه 26.04 LTS. ولا تتأثر Ubuntu 24.04 LTS، لأنها ما زالت تختار sudo الأصلي ما لم تثبّت sudo-rs يدوياً. تظهر أهمية ذلك عند الترقية من Ubuntu 24.04 إلى 26.04، أو عند إعداد خادم جديد على الإصدار الأحدث. وإذا كنت تشغّل أيضاً الإصدارات المرحلية، يوضح اختلاف إصدارات Ubuntu LTS والإصدارات المرحلية على الخادم أي جهاز يطبّق تغييراً كهذا أولاً.

تحقّق من sudo الذي يشغّله خادمك فعلياً

لا تستنتج ذلك من رقم الإصدار. اسأل الجهاز مباشرة.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

اعتمد على sudo --version في جهازك بدلاً من أي جدول إصدارات على الإنترنت، بما في ذلك هذه الصفحة. ويشكّل update-alternatives --config sudo النصف الآخر من الإجابة: فهو يسرد كل مزوّد مثبت لـ /usr/bin/sudo ويحدّد المزوّد المحدد. لا يعني تثبيت حزمة أنها محددة للاستخدام، لذلك اقرأ التحديد لا قائمة الحزم.

يُحزَّم التطبيقان خلال الفترة الانتقالية. التطبيق المكتوب بلغة Rust هو sudo-rs، وكان إصداره 0.2.13 في 26.04 اعتباراً من August 2026. أما التطبيق الأصلي، الذي يصونه Todd C. Miller، فما زال ضمن حزمة sudo؛ والتغيير هو أن برامجه تحمل لاحقة .ws، بحيث يمكن تثبيت التطبيقين معاً: /usr/bin/sudo.ws و/usr/bin/visudo.ws، إلى جانب cvtsudoers.ws وsudoreplay.ws. تم التحقق من أرشيف 26.04 في September 2026: يسرد dpkg -L sudo الملفات التنفيذية ذات اللاحقة، بينما توفّر sudo-rs الملف /usr/bin/sudo-rs إلى جانبها.

لماذا انتقلت Ubuntu إلى sudo-rs

يعمل sudo بامتياز setuid إلى root. ويمكن لأي مستخدم على الجهاز تشغيله، ويبدأ التنفيذ بامتيازات كاملة. لذلك، فإن وجود خلل في الذاكرة داخله قد يتيح للمستخدم المحلي استغلالاً للحصول على root. كان CVE-2021-3156 من هذا النوع تحديداً: تجاوز سعة في المخزن المؤقت للكومة، ويمكن لأي مستخدم محلي الوصول إليه. وقد ظل هذا الخلل في إصدار مُطلق لنحو عشر سنوات. تكتشف Rust هذا النوع من الأخطاء وقت الترجمة، وهذا هو السبب الرئيسي لإعادة كتابة البرنامج.

السبب الثاني هو نطاق الوظائف، وهو السبب الذي يؤثر في إعداداتك. أضاف sudo الأصلي مجموعة كبيرة من الوظائف على مدى ثلاثة عقود، وكل وظيفة تعني مزيداً من التعليمات البرمجية التي تعمل بامتيازات root. يطبّق sudo-rs مجموعة فرعية من هذه الوظائف عن قصد. وقد استُبعدت أي وظيفة اعتبرها المؤلفون متخصصة أو ضارة فعلياً. لذلك، قد يكون أحد تراكيب sudoers التي عملت لسنوات غير متاح ببساطة. وقاعدة wildcard لديك واحدة من هذه الحالات.

تزيل سلامة الذاكرة فئة واحدة من الأخطاء. لكنها لا تجعل البرنامج خالياً من الأخطاء. وقد أُطلقت إصلاحات أمنية خاصة بـ sudo-rs منذ أن أصبح الإعداد الافتراضي. ثبّت تحديثاته كما تفعل مع أي برنامج آخر.

قواعد sudoers التي لا تزال تعمل

الملف هو الملف نفسه. يقرأ sudo-rs الملف /etc/sudoers وملفات الإسقاط في /etc/sudoers.d/، كما يدعم الصيغ المعتادة التي يكتبها مشغّلو الخوادم:

  • deploy ALL=(ALL:ALL) ALL، وصيغ المجموعات مثل %sudo ALL=(ALL:ALL) ALL
  • وسمَي NOPASSWD: وPASSWD:
  • User_Alias وRunas_Alias وHost_Alias وCmnd_Alias
  • أمر مع قائمة وسائط مطابقة تماماً، مثل /usr/bin/systemctl restart app-api
  • أمر يتبعه ""، ما يسمح بتشغيل الأمر من دون أي وسائط فقط
  • أمر يتبعه * كوسيط نهائي، ما يسمح بأي وسائط لاحقة
  • مسار دليل ينتهي بـ /، ما يسمح بأي أمر داخل ذلك الدليل
  • ! لطرح أمر من قائمة
  • مجموعة مفيدة من Defaults، تشمل secure_path وenv_keep وenv_check وtimestamp_timeout وpasswd_tries وeditor وumask وtargetpw وrootpw وuse_pty

يتصرف إعدادان افتراضيان بشكل مختلف وقد يسببان الالتباس. لا يمكن تعطيل env_reset في sudo-rs؛ فهو مفعّل دائماً. أما use_pty فهو مفعّل افتراضياً، ولذلك يعمل الأمر في pseudo-terminal خاص به.

لماذا توقفت قاعدة sudoers التي تستخدم wildcard عن المطابقة

لا يزال استخدام wildcard مسموحاً في موضع واحد: اسم ملف الأمر. تظل قاعدة من الشكل %ops ALL = /sbin/fsck* تسمح بتنفيذ sudo fsck وsudo fsck_exfat، لأن * جزء من المسار الذي تجري مطابقته مع نظام الملفات.

داخل قائمة الوسائط، يقبل sudo-rs شكلين خاصين فقط، ولا يمثّل أيٌّ منهما نمطاً. يعني "" عدم وجود وسائط. ويعني * في النهاية قبول أي وسائط لاحقة. وتُقارَن كل وسيلة أخرى كنص حرفي. لذلك تكون %ops ALL = /sbin/service ntp * صحيحة، لأن ntp حرفي و* في النهاية. أما قاعدة مثل التالية فلا تمنحك أي صلاحية مما قصدته:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

تُعد app-* نمطاً في منتصف وسيطة. لا يوسّعها sudo-rs، لذلك لا تغطي القاعدة systemctl restart app-api ويرفض sudo الأمر. يخبرك أمران بحقيقة أي قاعدة على خادمك: يطبع sudo -l -U deploy، عند تشغيله بصفة root، ما يمكن لهذا الحساب تشغيله فعلياً، بينما يبيّن sudo visudo -c ما إذا كان الملف قابلاً للتحليل أصلاً. شغّلهما قبل أن تبدأ التعديل عشوائياً.

كانت قاعدة أحرف البدل ثغرة دائماً

في sudo الأصلي، تُضمّ الوسائط التي تكتبها في سلسلة واحدة، ثم تُطابق مع سلسلة وسائط القاعدة باستخدام glob. يطابق glob المسافات البيضاء أيضاً. وهذه هي النقطة التي يغفل عنها معظم الناس.

تقدّم وثائق sudo-rs أوضح مثال على ذلك. تسمح قاعدة /bin/rm *.txt أيضاً بـ sudo rm -rf /home .txt، لأن * الواحدة تبتلع -rf /home ، وتظل السلسلة المضمومة منتهية بـ .txt. تُفهم القاعدة على أنها «ملفات نصية فقط». لكنها تعني فعلياً «أي وسائط، ما دام السطر ينتهي بـ .txt».

وينطبق الأمر نفسه على مثال systemctl. بما أن الوسائط تُقارن كسلسلة واحدة مضمومة، فإن النمط الموجود في النهاية يطابق أيضاً أي شيء تضيفه بعده. لذلك تغطي restart app-* التعبير restart app-api، إضافة إلى أي وسائط أخرى يضيفها المستدعي. يكشف وجود نمط داخل إحدى الوسائط الوسائط المحيطة به، والوسائط هي التي تحدد صلاحيات الأمر. يرفض sudo-rs هذا التركيب بدلاً من محاولة جعله آمناً، لأنه لا توجد صيغة عامة آمنة له.

استبدل القاعدة العامة بقائمة أوامر صريحة

توجد معظم القواعد العامة لأن شخصاً ما لم يرد كتابة أربعة أسطر. اكتب الأسطر الأربعة.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

استخدم المسار الصحيح. لا تطابق قاعدة تسمّي /bin/systemctl على نظام يوجد فيه الملف التنفيذي في /usr/bin/systemctl، ويبدو الفشل مطابقاً لمشكلة صلاحيات. تحقّق باستخدام command -v systemctl والصق الناتج الذي يعرضه.

ضع القاعدة في ملف drop-in مستقل بدلاً من وضعها في /etc/sudoers، حتى لا يتعارض تحديث الحزمة مع تعديلاتك:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

سمِّ الملف من دون نقطة ومن دون علامة tilde في النهاية. يتجاهل sudo الأصلي الملفات الموجودة في sudoers.d إذا احتوت أسماؤها على نقطة، لذلك يُعد 90-deploy.conf حالة شائعة لا ينتج عنها أي إجراء بصمت، ولا يكلّفك الالتزام بهذا النمط شيئاً.

استخدم غلافاً مملوكاً لـroot عندما تطول القائمة

عندما تصبح مجموعة الأوامر المسموح بها كبيرة جداً بحيث يتعذر إدراجها، انقل قرار السماح خارج sudoers إلى برنامج صغير يملكه root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

يكتفي جانب sudoers بعد ذلك بتحديد أمر واحد:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

تُعدّ علامة * اللاحقة مقبولة هنا لأن البرنامج النصي، وليس sudo، هو الذي يحدد ما هو مسموح به. وينطبق ذلك فقط ما دام البرنامج النصي مملوكاً لـroot وغير قابل للكتابة من أي حساب آخر. إذا كان deploy يستطيع الكتابة إلى الملف، فيمكن لـdeploy استبدال محتواه وتشغيل أي شيء بصلاحيات root، وهذا أسوأ من قاعدة wildcard التي أزلتها. افحص الوضع باستخدام ls -l، وإذا لم يكن الناتج واضحاً لك، فإن قراءة سلسلة الصلاحيات drwxr-xr-x تستغرق خمس دقائق لتعلّمها. وتنطبق القاعدة نفسها على الدليل: يجب ألا يكون /usr/local/sbin قابلاً للكتابة من الحساب أيضاً، لأن الدليل القابل للكتابة يعني إمكانية استبدال الملف بالكامل.

امنح المهمة حساباً مخصصاً بدلاً من قاعدة sudo

غالباً ما يكون السؤال الأفضل هو: لماذا يحتاج الأمر إلى root أصلاً؟ يمكن إدارة الخدمة التي تعمل باسم مستخدم خاص بها بواسطة ذلك المستخدم، من دون إضافة سطر إلى sudoers. بالنسبة إلى وحدات النظام، يفوّض systemd هذا القرار إلى polkit مسبقاً، لذلك يمكن لقاعدة أن تحدد وحدة واحدة ومشغلاً واحداً:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

احفظ ذلك باسم /etc/polkit-1/rules.d/50-app-api.rules، ويمكن لـdeploy تشغيل systemctl restart app-api من دون sudo إطلاقاً. اختبره من السياق الفعلي الذي سيستخدمه، لأن القاعدة التي تعمل في جلسة SSH الخاصة بك ينبغي التحقق منها أيضاً من cron قبل الاعتماد عليها. في جميع الحالات، يجب أن يكون الحساب الذي ينفّذ المهمة مخصصاً لهذه المهمة وحدها. وهذا هو المبدأ نفسه الذي تقوم عليه حسابات المستخدمين ذات أقل صلاحيات على VPS.

ما الذي لا يوفّره sudo-rs أيضاً

sudo -E غير مطبّق. سمِّ المتغيرات التي تحتاج إليها باستخدام Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" بدلاً منه. تذكّر أن env_reset مفعّل دائماً، ولذلك تُمسح كل القيم التي لم تُحفَظ.

لم يعد تخزين sudoers المركزي في LDAP متاحاً. sudoers.ldap وcvtsudoers غير مطبّقين، وأُزيلت الحزمة sudo-ldap في 26.04. تظل مصادقة LDAP عبر PAM أو SSSD تعمل. الجزء غير المدعوم هو تخزين السياسات في دليل.

INTERCEPT، الذي كان يحاول منع الخروج إلى shell من أمر مسموح به، غير مطبّق. ولم يكن يصمد أمام مستخدم مصمم على تجاوزه في أي حال. إذا سمحت قاعدة لشخص بتشغيل محرر أو مفسّر بصلاحيات root، فسيملك صلاحيات root، ولا يغيّر أي خيار في sudo ذلك.

تسجيل الجلسات غير مطبّق، لذلك لا يوجد سجل I/O ولا sudoreplay. يُرسل التسجيل إلى syslog فقط، ولا يتوفر خيار logfile لإعادة توجيهه إلى مكان آخر. لذلك تصل رسائل sudo إلى المكان الذي يرسل إليه نظامك رسائل syslog بالفعل.

هل ينبغي الرجوع إلى sudo.ws؟

يمكنك ذلك، وخلال دورة 26.04 سيبقى الإصدار الأصلي مضمّناً لهذا السبب تحديداً.

sudo apt install sudo
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

انسخ المسارات كما تظهر تماماً في خرج --config، وليس من هذه الصفحة، لأن تلك هي القائمة التي سيقبلها نظامك أنت. وعند العودة إلى sudo-rs لاحقاً، اضبط البديل على مسار ملف sudo-rs التنفيذي من القائمة نفسها.

أبقِ جلسة SSH ثانية مفتوحة، وسجّل الدخول إليها واتركها خاملة، قبل إجراء أي تغيير يؤثر في sudo. قد يؤدي تعذر تحليل ملف sudoers، أو توجيه البديل إلى ملف تنفيذي غير مثبّت، إلى فقدان قدرتك على التحول إلى root على خادم بعيد. أدرج هذه العادة ضمن كل ما تفعله في الدقائق العشر الأولى على VPS جديد.

تعامل مع الرجوع باعتباره مهلة نهائية، لا إصلاحاً. فهو يمنحك أسبوعاً لإعادة كتابة القواعد بطريقة صحيحة. وتستحق إعادة الكتابة التنفيذ بحد ذاتها، لأن كل قاعدة wildcard تحذفها كانت تمنح صلاحيات أوسع مما قصده كاتبها عند قراءتها.

FAQ

لماذا توقفت قاعدة wildcard في sudoers عن العمل على Ubuntu 26.04؟

لأن Ubuntu 26.04 LTS يختار sudo-rs كأداة sudo الافتراضية، ولأن sudo-rs لا يطابق أنماط wildcard داخل وسائط الأمر. يسمح باستخدام wildcard في اسم ملف الأمر، و"" للدلالة على عدم وجود وسائط، و* واحداً بوصفه الوسيط الأخير. تضع قاعدة مثل /usr/bin/systemctl restart app-* نمطاً في منتصف وسيط، ولذلك لا تمنح أي صلاحية ويُرفض الأمر. شغّل sudo -l -U deploy بصلاحية root لمعرفة الصلاحيات الفعلية للحساب، ثم استبدل القاعدة بالأوامر المحددة أو ببرنامج wrapper مملوك لـroot.

كيف أعود إلى sudo الأصلي على Ubuntu 26.04؟

يوجد sudo الأصلي في الحزمة sudo، وتحمل ملفاته الثنائية اللاحقة .ws. ثبّته باستخدام sudo apt install sudo، ثم وجّه البديل إليه باستخدام sudo update-alternatives --set sudo /usr/bin/sudo.ws. شغّل update-alternatives --config sudo أولاً لعرض المسارات الدقيقة التي يوفّرها نظامك، وأبقِ جلسة SSH ثانية مفتوحة أثناء تغيير الإعداد. لا يعيد ذلك sudo-ldap، إذ أُزيل من 26.04 بغض النظر عن التطبيق الذي تختاره.

هل يقرأ sudo-rs ملف /etc/sudoers نفسه؟

نعم. يقرأ sudo-rs الملف /etc/sudoers وملفات الإضافة ضمن /etc/sudoers.d/، مع استخدام الصياغة نفسها للمستخدمين والمجموعات والأسماء المستعارة ومواصفات run-as والعلامة NOPASSWD. يطبّق مجموعة فرعية من لغة sudoers، ولذلك تظهر الاختلافات في شكل بنى غير متوفرة، لا بنى تعمل بطريقة مختلفة. حرّر الملف باستخدام sudo visudo، ثم تحقّق باستخدام sudo visudo -c قبل إغلاق جلستك.

ما البديل عن sudo -E في sudo-rs؟

لا تُطبّق sudo -E، كما لم يكن استخدامها مستحسناً في sudo الأصلي، لأن تمرير بيئة يتحكم فيها المستخدم إلى عملية تعمل بصلاحية root طريقة معروفة لتغيير سلوك تلك العملية. حدّد المتغيرات التي تحتاج إليها فعلياً في sudoers بدلاً من ذلك، باستخدام سطر مثل Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". تكون env_reset مفعّلة دائماً في sudo-rs ولا يمكن تعطيلها، ولذلك يُحذف كل متغير لا تُبقي عليه.

#sudo#sudo-rs#ubuntu#sudoers#permissions