Kernel Linux tùy chỉnh: Loại bỏ thành phần thừa để tăng tốc độ và bảo mật

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Tại sao nên tự biên dịch Kernel?

Các bản phân phối tiêu chuẩn như Ubuntu, RHEL, hay Debian thường đi kèm với một kernel “phù hợp cho tất cả mọi người”. Những bản build chung này được thiết kế để khởi động trên hầu hết mọi thiết bị, từ những chiếc ThinkPad cổ cho đến các máy chủ Threadripper 128 nhân. Để đạt được khả năng tương thích khổng lồ này, những người duy trì hệ thống phải đóng gói hàng nghìn driver và tính năng mà có lẽ bạn chẳng bao giờ dùng tới. Điều này tạo ra một file thực thi (binary) cồng kềnh với bề mặt tấn công lớn hơn và tiêu tốn bộ nhớ không cần thiết.

Hành trình tìm đến kernel tùy chỉnh của tôi bắt đầu khi tôi nhận thấy một dàn máy chủ rack đang tải driver cho ổ đĩa mềm và card Wi-Fi. Những cỗ máy này nằm trong một trung tâm dữ liệu được kiểm soát nhiệt độ nghiêm ngặt và sẽ chẳng bao giờ thấy một chiếc đĩa mềm hay tín hiệu không dây nào. Bằng cách loại bỏ những thành phần cũ kỹ này, bạn có thể tạo ra một môi trường gọn nhẹ hơn, nhanh hơn và bảo mật hơn đáng kể.

Sự đánh đổi: Kernel chung vs. Kernel tùy chỉnh

Việc lựa chọn giữa kernel mặc định và bản build thủ công là sự cân bằng giữa tính tiện dụng và khả năng kiểm soát. Hãy cùng xem chúng khác biệt thế nào trong môi trường production.

Kernel chung (Tiêu chuẩn của bản phân phối)

  • Phân phối dạng Binary: Bạn nhận được một file .deb hoặc .rpm đã được biên dịch sẵn và hoạt động ngay lập tức.
  • Khả năng tương thích cực cao: Bao gồm các module cho mọi thứ, từ bộ điều khiển SCSI thập niên 90 đến các ổ NVMe mới nhất.
  • Cập nhật tự động: Các bản vá bảo mật được gửi qua apt hoặc dnf mà không cần can thiệp thủ công.
  • Hiệu suất: Thường ở mức trung bình. Mã nguồn được tối ưu hóa cho khả năng tương thích rộng rãi thay vì tận dụng tập lệnh cụ thể của CPU bạn đang dùng.

Kernel tùy chỉnh (Cách tiếp cận “may đo”)

  • Ưu tiên mã nguồn: Bạn lấy mã nguồn thô trực tiếp từ kernel.org.
  • Đặc thù cho phần cứng: Bạn chỉ bao gồm driver cho NIC, bộ điều khiển lưu trữ và chipset cụ thể của mình.
  • Tối ưu hóa tập lệnh: Bạn có thể biên dịch riêng cho các kiến trúc như Zen 3 hoặc Ice Lake. Điều này cho phép trình biên dịch sử dụng các lệnh chuyên dụng (như AVX-512) hiệu quả hơn.
  • Thắt chặt bảo mật: Bạn có thể vô hiệu hóa vĩnh viễn các tính năng rủi ro cao như eBPF không đặc quyền hoặc các syscall cũ vốn thường là mục tiêu của các cuộc tấn công khai thác lỗi.

Thực tế của việc biên dịch thủ công

Biên dịch không phải là “viên đạn bạc” cho mọi tình huống. Nó đòi hỏi sự cam kết bảo trì liên tục.

Lợi ích

  • Dung lượng nhỏ hơn: Một kernel tối giản sẽ nằm trong bộ nhớ đệm (cache) của CPU hiệu quả hơn. Trên một instance cloud có 4GB RAM, tôi đã thấy kernel tùy chỉnh giảm mức chiếm dụng bộ nhớ cơ sở từ 120MB xuống còn khoảng 45MB. Điều này giải phóng tài nguyên quan trọng cho các ứng dụng web có độ truy cập đồng thời cao.
  • Bảo mật bằng cách lược bỏ: Nếu mã nguồn cho FireWire hoặc driver USB cũ không tồn tại, chúng sẽ không thể bị khai thác. Bạn loại bỏ hiệu quả toàn bộ các lớp lỗ hổng leo thang đặc quyền cục bộ.
  • Tính năng mới nhất: Bạn có thể triển khai các cải tiến lập lịch (scheduling) hoặc các bản vá hệ thống tập tin mới nhất vài tháng trước khi chúng xuất hiện trên kho lưu trữ chính thức của bản phân phối.

Nhược điểm

  • Tốn thời gian: Tùy thuộc vào phần cứng, việc biên dịch có thể mất 10 phút trên một máy trạm hiện đại hoặc hơn một giờ trên một VPS giá rẻ.
  • Vá lỗi thủ công: Giờ đây bạn chính là người tự duy trì hệ thống. Khi có thông báo CVE mới, bạn phải tự tải xuống, cấu hình và biên dịch lại.
  • Dễ gặp lỗi: Một sai sót nhỏ—như quên driver NVMe—sẽ dẫn đến lỗi “Kernel Panic” và hệ thống không thể khởi động.

Điều kiện tiên quyết để build

Luôn thực hiện những bản build đầu tiên trên máy chủ staging hoặc máy ảo (VM) cục bộ. Đừng bao giờ thử nghiệm trên một node production đang chạy. Trong ví dụ này, chúng ta sử dụng Ubuntu 22.04 LTS.

Bắt đầu bằng cách cài đặt bộ công cụ thiết yếu:

sudo apt update
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev dwarves zstd -y

Đảm bảo bạn có ít nhất 25GB dung lượng đĩa trống. Quá trình biên dịch tạo ra một lượng lớn các file đối tượng trung gian.

Triển khai từng bước

1. Tải mã nguồn

Truy cập kernel.org để tìm phiên bản ổn định mới nhất. Đối với môi trường production, tôi khuyên bạn nên chọn các nhánh Hỗ trợ dài hạn (LTS).

wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.15.tar.xz
tar -xf linux-6.6.15.tar.xz
cd linux-6.6.15

2. Cấu hình bản build

Đừng bắt đầu từ con số không. Hãy sao chép cấu hình hiện tại đang hoạt động để làm nền tảng. Điều này giúp bạn không bỏ lỡ các driver phần cứng thiết yếu.

cp /boot/config-$(uname -r) .config

Khởi chạy giao diện cấu hình:

make menuconfig

Điều hướng menu để áp dụng các tinh chỉnh cấp độ production sau:

  • Processor type: Thay đổi “Processor family” từ Generic sang model CPU cụ thể của bạn (ví dụ: “Core2/newer Xeon”).
  • Local version: Thêm một tag như -prod-optimized để giúp nhận diện kernel trong log.
  • Networking: Loại bỏ Bluetooth, Amateur Radio và IRDA nếu đó là máy chủ.
  • Security: Đảm bảo “Stack Protector buffer overflow detection” được thiết lập thành Strong.

3. Xử lý Trusted Keys

Kernel của Ubuntu và Debian được ký bằng các khóa riêng cụ thể. Bản build của bạn sẽ thất bại nếu nó cố gắng tham chiếu đến các khóa mà bạn không sở hữu. Chạy các lệnh sau để xóa yêu cầu này:

scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
scripts/config --set-str CONFIG_SYSTEM_TRUSTED_KEYS ""

4. Bắt đầu biên dịch

Sử dụng cờ -j để tận dụng tất cả các nhân CPU. Trên máy 8 nhân, -j8 sẽ giúp giảm đáng kể thời gian chờ đợi.

make -j$(nproc)

Hãy chú ý đến nhiệt độ hệ thống. Quá trình này sẽ đẩy mức sử dụng CPU lên 100% trong suốt thời gian build.

5. Cài đặt

Sau khi build xong, hãy cài đặt các module trước, sau đó mới đến chính kernel image.

sudo make modules_install
sudo make install

Script make install rất thông minh; nó tự động xử lý việc chuyển file vào /boot và cập nhật cấu hình GRUB cho bạn.

6. Xác minh

Khởi động lại hệ thống. Nếu mọi việc suôn sẻ, hãy kiểm tra kết quả:

uname -a

Kết quả trả về sẽ hiển thị chuỗi phiên bản tùy chỉnh của bạn.

Lời khuyên từ thực tế

Giá trị thực sự của một kernel tùy chỉnh không chỉ nằm ở việc tăng 2% điểm benchmark. Đó là sự an tâm đến từ một hệ thống được đơn giản hóa. Một kernel không có 500 driver không cần thiết đồng nghĩa với việc có ít hơn 500 thứ có thể bị lỗi trong quá trình cập nhật.

Luôn giữ một kernel mặc định của bản phân phối để dự phòng. Nếu bản build tùy chỉnh của bạn không thể mount phân vùng root, bạn chỉ cần nhấn ‘Esc’ khi khởi động, chọn kernel cũ và sửa lại cấu hình. Đối với những người quản lý nhiều máy chủ, hãy sử dụng make bindeb-pkg. Lệnh này tạo ra một file .deb tiêu chuẩn mà bạn có thể phân phối cho tất cả các node giống hệt nhau trong hệ thống mà không cần biên dịch lại trên từng máy.

Share: