اگر بسته‌های AlmaLinux یا Rocky Linux را از یک سرور داخلی بگیریم، چه چیزی اصالت آن‌ها را ثابت می‌کند؟ آیا میرور باید RPMها را دوباره امضا کند؟ و اگر امضای بسته سالم باشد، هنوز امکان دست‌کاری فهرست نسخه‌ها وجود دارد؟

برای پاسخ، باید سه لایه را جدا ببینیم: انتخاب محل دانلود، اصالت خود RPM و اعتبار متادیتایی که مجموعهٔ نسخه‌ها را معرفی می‌کند. نمونه‌ها برای AlmaLinux ۹ و Rocky Linux ۹ با DNF 4 هستند؛ تنظیمات مخازن رسمی را از فایل‌های همان توزیع بخوانید.

مخزن، میرور، کش و انتشار مدیریت‌شده#

مدلمحتوامسئولیت
مخزن اصلیRPMها و متادیتای ناشرانتشار نسخه‌ها
میرورکپی محتوای بالادستهمگام‌سازی و ارائهٔ فایل
کش واسطپاسخ درخواست‌های قبلیکاهش دریافت تکراری
انتشار مدیریت‌شدهمجموعهٔ انتخاب‌شده و متادیتای خروجیکنترل ورود محتوا و ارتقای محیط‌ها

یک کش پرشده از دانلودهای قبلی الزاماً تمام وابستگی‌های نصب یک ماشین تازه را ندارد. میرور کامل هم الزاماً یک snapshot ثابت نیست؛ ممکن است در دریافت بعدی نسخه‌های قبلی حذف شوند. برای کنترل انتشار باید هویت مجموعه و زمان تأیید آن را مستقل ثبت کرد.

ابزار reposync در DNF برای دریافت مخازن است؛ createrepo_c متادیتا تولید می‌کند. هیچ‌کدام به‌تنهایی تمام چرخهٔ آزمایش، promotion و نگهداری snapshot را مدیریت نمی‌کنند. افزونهٔ reposync ، پروژهٔ createrepo_c

کلاینت ابتدا چه نشانی‌ای را پیدا می‌کند؟#

در فایل .repo، این گزینه‌ها نقش‌های متفاوتی دارند:

گزینهنقش
baseurlریشهٔ مستقیم مخزن قابل‌مصرف
mirrorlistنشانی سرویسی که فهرست میرورها می‌دهد
metalinkمعرفی میرورها همراه اطلاعاتی مانند هش متادیتای مرجع

mirrorlist و metalink خود ریشهٔ مخزن نیستند. با انتخاب یکی از میرورها، درخواست‌ها به‌طور مفهومی چنین می‌شوند:

Client --> mirror selection
       --> GET /repository/repodata/repomd.xml
       --> GET /repository/repodata/<checksum>-primary.xml.gz
       --> GET /repository/Packages/example.rpm

DNF مسیر فایل RPM را از متادیتا می‌خواند. وب‌سرور فایل می‌دهد؛ حل وابستگی‌ها روی کلاینت انجام می‌شود. Metalink می‌تواند برای تطبیق repomd.xml با مرجع نقش داشته باشد؛ این نقش را با امضای OpenPGP خود RPM یکی نگیرید. تعریف گزینه‌های مخزن در DNF

اعتماد معمول RPM با APT فرق دارد#

در APT معمول، امضای آرشیو از طریق هش‌ها به فایل deb وصل می‌شود. در RPM، امضای خود بسته یک سازوکار مستقل است:

Trusted RPM public key
          |
          v
Signature embedded in downloaded RPM
          |
          v
Package contents and metadata covered by signature

با gpgcheck=1، DNF امضای بسته را بررسی می‌کند. یک RPM رسمی که بدون تغییر کپی شده، امضای ناشر رسمی را نگه می‌دارد؛ میرور برای ارائهٔ آن به کلید خصوصی AlmaLinux یا Rocky نیاز ندارد.

برای یک فایل دانلودشده:

rpmkeys --checksig --verbose ./example.rpm

پیام مربوط به digest را از تأیید signature جدا بخوانید. هش سالم بدون کلید معتبر فقط سلامت بایت‌ها را نشان می‌دهد؛ اصالت ناشر را ثابت نمی‌کند. امضای بسته‌ها در راهنمای RPM

متادیتا چه زمانی امضا بررسی می‌شود؟#

در مخزنی که امضای متادیتا ارائه می‌کند، مسیر جداگانه‌ای داریم:

Trusted repository metadata key
          |
          v
repomd.xml.asc --> repomd.xml
                       |
                       v
             metadata index checksums
                       |
                       v
               RPM checksum in index

گزینهٔ repo_gpgcheck=1 بررسی این امضا را فعال می‌کند. مخزنی که repomd.xml.asc ندارد با فعال‌کردن این گزینه ناگهان امضاشده نمی‌شود؛ کلاینت خطا خواهد داد. بنابراین نمی‌توان یک تنظیم واحد را بدون بررسی به همهٔ مخازن رسمی تحمیل کرد.

حتی وقتی gpgcheck=1 فعال است، از آن نتیجه نگیرید فهرست نسخه‌ها نیز با امضای مخزن تأیید شده است. با امضای بسته می‌توان اصالت بستهٔ دریافت‌شده را سنجید؛ اما یک مجموعهٔ قدیمی یا ناقص می‌تواند همچنان فقط RPMهای معتبر داشته باشد. HTTPS، Metalink مورداعتماد و سیاست انتشار هرکدام در این لایه اهمیت دارند. تفاوت gpgcheck و repo_gpgcheck

کلیدهای رسمی ابتدا از کجا آمده‌اند؟#

در نصب معتبر، بسته‌های release و تنظیمات توزیع اطلاعات مخازن و مسیر کلیدهای رسمی را فراهم می‌کنند. معمولاً فایل کلید زیر /etc/pki/rpm-gpg/ معرفی می‌شود؛ برای انتشار خودتان مقدار واقعی gpgkey را بخوانید:

rg -n '^(\[|baseurl|mirrorlist|metalink|gpgkey|gpgcheck|repo_gpgcheck)' \
  /etc/yum.repos.d/*.repo
rpm -qa '*release*'

اگر rg نصب نیست، فایل‌ها را با less بخوانید. نقطهٔ شروع اعتماد، ISO یا ایمیج معتبر و فرایند نصب است؛ دریافت یک کلید از سرور ناشناس همراه با اثرانگشتی که همان سرور اعلام می‌کند، احراز مستقل هویت نیست.

برای کلید سازمانی، فایل را دریافت و اثرانگشت کامل را با مقدار کانال مورداعتماد مقایسه کنید:

curl --fail --show-error --location \
  https://rpm.example.org/keys/RPM-GPG-KEY-company \
  --output /tmp/RPM-GPG-KEY-company
gpg --show-keys --with-fingerprint /tmp/RPM-GPG-KEY-company

پس از مقایسه، واردکردن کلید تصمیم مدیر سیستم است. پاسخ خودکار yes به هر درخواست ورود کلید، جای این بررسی را نمی‌گیرد.

gpgkey معادل دقیق Signed-By نیست#

نمونهٔ زیر برای مخزن سازمانی است:

[company-tools]
name=Company tools
baseurl=https://rpm.example.org/el9/$basearch/releases/v1/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-company
includepkgs=company-*
sslverify=1

gpgkey محل یافتن کلیدهای قابل‌ورود را معرفی می‌کند. در بررسی امضای بسته‌ها با RPM/DNF 4، نباید آن را محدودسازی سخت امضاکننده به همان repo فرض کرد: کلیدهای واردشده در keyring عمومی RPM می‌توانند در اعتبارسنجی بسته‌ها دخیل باشند. کلیدهای بررسی متادیتا در DNF جدا و به تفکیک مخزن ذخیره می‌شوند. مدل کلیدها در تنظیم DNF

includepkgs=company-* انتخاب بسته از این repo را به الگو محدود می‌کند؛ مرز رمزنگاری نیست. اگر آن را تغییر دهید، دامنهٔ انتخاب هم عوض می‌شود. برای برنامهٔ نصب، نام نسخه و repo را بخوانید:

dnf list --showduplicates company-hello
sudo dnf --assumeno install company-hello

مخزن ثالثی که بستهٔ هم‌نام با بستهٔ رسمی دارد می‌تواند روی انتخاب نسخه اثر بگذارد. جداکردن کلید، سیاست انتخاب بسته و سیاست مبدأ سه مسئلهٔ مستقل‌اند.

میرور بدون تغییر و بازتولید متادیتا#

در کپی کامل، می‌توان RPM و متادیتای موجود را حفظ کرد. اگر امضای متادیتای بالادست ارائه شده، آن را نیز باید بدون تغییر منتقل کرد. اما اجرای createrepo_c متادیتای تازه می‌سازد؛ امضای قبلی repomd.xml دیگر برای آن معتبر نیست.

با بازتولید متادیتا، الزاماً نیازی به دوباره‌امضاکردن RPMهای رسمی نداریم:

Official RPMs -- official package signatures --> internal selected collection
                                                       |
                                                createrepo_c
                                                       |
Company key -- metadata signature --> internal repomd.xml

در این مدل، سازمان انتخاب مجموعه را با امضای متادیتا تأیید می‌کند؛ اصالت هر RPM رسمی همچنان با کلید ناشر آن بررسی می‌شود. بسته‌های ساخته‌شدهٔ سازمان باید امضای خودشان را داشته باشند. اگر مخزن رسمی و داخلی را مخلوط کردید، کلاینت ممکن است به چند کلید نیاز داشته باشد.

برای مجموعه‌های modular، فیلترکردن RPMها بدون توجه به module metadata می‌تواند نصب را خراب کند. همچنین updateinfo شامل اطلاعاتی است که از امضای بسته یا filename به‌تنهایی استخراج نمی‌شود. ملاحظات متادیتا در reposync

انتشار ناقص چگونه خطا ایجاد می‌کند؟#

فرض کنید repomd.xml تازه در دسترس است، اما یکی از فهرست‌های معرفی‌شده هنوز کپی نشده: دریافت متادیتا با 404 یا خطای checksum شکست می‌خورد. اگر فهرست جدید حاضر باشد ولی RPM مربوط وجود نداشته باشد، خطا هنگام دانلود بسته رخ می‌دهد.

راه عملی، دریافت در پوشهٔ staging، بررسی مجموعه و سپس ارائهٔ یک نسخهٔ کامل است. نگهداری فایل‌های نسخهٔ قبلی نیز لازم است؛ کلاینتی که قبلاً فهرست قدیمی گرفته ممکن است هنوز همان مسیرها را درخواست کند. تعویض اتمیک symlink، چند درخواست HTTP یک کلاینت را به یک تراکنش شبکه تبدیل نمی‌کند؛ URL ثابت هر snapshot این ابهام را کمتر می‌کند.

امضای معتبر تضمین تازگی نیست#

metadata_expire سیاست تازه‌کردن کش کلاینت است؛ معادل تضمین رمزنگاری برای جدیدترین محتوا نیست. timestamp و revision متادیتا را نیز بدون سیاست معتبر ناشر، تضمین عمومی ضدبازپخش فرض نکنید.

برای مخزن داخلی این اطلاعات را ثبت کنید: آخرین دریافت موفق، snapshot منتشرشده، نسخه‌های تأییدشده و فاصله با اصلاحیه‌های بالادست. اگر advisoryها حفظ شده‌اند، dnf updateinfo list --security مفید است؛ نبودن خروجی در مخزنی که updateinfo ندارد، سالم‌بودن امنیتی سیستم را ثابت نمی‌کند.

خطا را در لایهٔ خودش بررسی کنیم#

نشانهنخستین بررسی
خطای DNS یا TLSنام، شبکه، گواهی و CA
repomd.xml پیدا نمی‌شودریشهٔ baseurl و خروجی انتشار
خطای GPG برای RPMامضای فایل، کلید واردشده و سازگاری الگوریتم
خطای امضای متادیتاrepo_gpgcheck، فایل asc و کلید متادیتا
خطای checksumکش واسط و یکپارچگی همگام‌سازی
404 فایل RPMفهرست قدیمی یا انتشار ناقص
نسخهٔ غیرمنتظرهrepo مبدأ، excludeها، اولویت و stream فعال

غیرفعال‌کردن gpgcheck یا sslverify علت خطا را پیدا نمی‌کند. مخزن داخلی قابل‌اعتماد به تعریف روشن ناشر، حفاظت کلید، انتشار منسجم و فرایند رساندن اصلاحیه‌ها نیاز دارد؛ خصوصی‌بودن شبکه به‌تنهایی این مسئولیت‌ها را انجام نمی‌دهد.