Docker Rootless: Đừng để một lỗ hổng ứng dụng ‘bay màu’ cả Server

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Cú điện thoại lúc 2 giờ sáng và cái giá của đặc quyền root

Màn hình điện thoại sáng rực lúc 2 giờ sáng với hàng loạt cảnh báo đỏ rực từ hệ thống giám sát. Một container trong cụm staging bị chiếm quyền điều khiển (compromised). Kẻ tấn công đã khai thác thành công lỗ hổng RCE từ một thư viện cũ mà team chưa kịp cập nhật.

Nguy hiểm nằm ở chỗ Docker daemon mặc định chạy với quyền root. Khi kẻ tấn công thực hiện container breakout (thoát khỏi container), chúng sẽ có ngay quyền tối cao trên máy chủ vật lý. Việc này chẳng khác nào bạn khóa cửa nhà cực kỹ nhưng lại để chìa khóa vạn năng ngay dưới thảm chùi chân.

Sau sự cố đó, mình đã chuyển 100% các service sang Rootless Mode. Đây là cách áp dụng triệt để Nguyên tắc đặc quyền tối thiểu (Least Privilege). Khi daemon Docker không có quyền root, kẻ tấn công dù thoát ra được cũng chỉ là một user vô danh, không thể phá hoại hệ thống cốt lõi.

Cài đặt Docker Rootless trong 5 phút

Thay vì ngồi chờ lỗ hổng xuất hiện, hãy chủ động bảo mật server ngay. Trên Ubuntu hoặc Debian, bạn có thể thiết lập xong chỉ với vài thao tác đơn giản.

Bước 1: Chuẩn bị môi trường

Rootless Docker cần newuidmapnewgidmap để ánh xạ ID người dùng. Hãy cài đặt các package bổ trợ này bằng lệnh:

sudo apt-get update
sudo apt-get install -y dbus-user-session uidmap slirp4netns fuse-overlayfs

Bước 2: Chạy script cài đặt (Không dùng sudo)

Docker cung cấp script cài đặt tự động rất gọn nhẹ. Bạn hãy thực hiện lệnh này với tư cách user thường. Tuyệt đối không thêm sudo vào trước lệnh này:

curl -fsSL https://get.docker.com/rootless | sh

Bước 3: Khai báo biến môi trường

Khi script chạy xong, hệ thống sẽ yêu cầu bạn thêm một vài dòng cấu hình. Hãy copy chúng vào file .bashrc hoặc .zshrc để Docker tự kích hoạt mỗi khi bạn login:

export PATH=/home/$USER/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

Kích hoạt cấu hình mới bằng lệnh: source ~/.bashrc.

Bước 4: Kiểm tra kết nối

Thử khởi chạy một container để xác nhận mọi thứ đã ổn định:

docker run -d hello-world

Nếu thấy dòng chữ “Hello from Docker!” xuất hiện mà không cần dùng sudo, hệ thống của bạn đã an toàn hơn 90% các server mặc định ngoài kia.

Cơ chế bảo mật của Rootless Mode có gì đặc biệt?

Ở chế độ thông thường, tiến trình dockerd nắm quyền root. Mọi container bạn tạo ra đều được quản lý bởi một thực thể có quyền tối thượng trên host. Ngược lại, Rootless Mode tận dụng User Namespaces của Kernel Linux.

Tính năng này ánh xạ UID (User ID) bên trong container thành một UID khác trên máy host. Chẳng hạn, user root (UID 0) trong container thực tế chỉ tương đương user thanh_it (UID 1001) ở bên ngoài.

Mình từng xử lý một vụ bot đào coin thâm nhập qua lỗ hổng Memcached. Ở chế độ Rootful, con bot này đẩy CPU lên 400%, làm latency API vọt từ 50ms lên 10s khiến hệ thống tê liệt. Với Rootless, chúng ta có thể giới hạn tài nguyên chặt chẽ ở mức user. Kẻ tấn công cũng không thể can thiệp sâu vào kernel để che giấu tiến trình độc hại.

3 rào cản thường gặp khi chạy Rootless

Chuyển sang Rootless không hoàn toàn là “màu hồng”. Bạn sẽ gặp một số hạn chế về hạ tầng cần xử lý khéo léo.

1. Chặn port dưới 1024

Linux mặc định chỉ cho phép root bind các port từ 1 đến 1023. Nếu bạn chạy Nginx trên port 80, Docker sẽ báo lỗi Permission denied ngay lập tức.

Giải pháp: Hãy chạy container ở port cao như 8080 hoặc 8443. Sau đó, sử dụng Reverse Proxy hoặc Cloudflare Tunnel để điều hướng traffic. Nếu bắt buộc phải dùng port thấp, hãy chạy lệnh sau để mở quyền cho user thường:

sudo sysctl net.ipv4.ip_unprivileged_port_start=80

2. Lỗi lệnh Ping

Đừng quá bất ngờ nếu bạn không thể ping google.com từ bên trong container. Nguyên nhân do cơ chế networking slirp4netns không có quyền tạo raw sockets theo mặc định.

Giải pháp: Cấu hình lại dải port cho phép của kernel bằng lệnh:

sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"

3. Giới hạn tài nguyên (Cgroup v2)

Các distro cũ như CentOS 7 sẽ khiến bạn mệt mỏi khi muốn giới hạn RAM/CPU cho Rootless container. Để mọi thứ vận hành trơn tru nhất, mình khuyên bạn nên dùng Ubuntu 22.04 hoặc Debian 11 trở lên vì chúng hỗ trợ sẵn Cgroup v2.

Mẹo vận hành Rootless trên Production

Sau nhiều lần “trầy da tróc vảy”, đây là 3 kinh nghiệm xương máu giúp bạn quản lý hệ thống ổn định hơn:

  • Duy trì service khi logout: Vì Docker chạy dưới quyền user, nó sẽ tắt khi bạn thoát session SSH. Hãy bật tính năng lingering để daemon chạy ngầm vĩnh viễn: sudo loginctl enable-linger $USER.
  • Quản lý dung lượng: Dữ liệu Docker mặc định nằm tại ~/.local/share/docker. Hãy kiểm tra kỹ dung lượng phân vùng /home. Nếu cần, hãy dùng symlink để chuyển thư mục này sang ổ đĩa dữ liệu riêng.
  • Cẩn thận khi Backup: Tránh dùng sudo cp để sao lưu volume. Việc này làm sai lệch quyền sở hữu file (UID mapping), khiến bạn không thể khởi động lại container sau khi restore.

Thay đổi thói quen dùng sudo ban đầu có thể gây chút phiền toái. Tuy nhiên, bỏ ra 30 phút cấu hình Rootless là khoản đầu tư rẻ nhất cho sự an tâm của bạn. Đừng đợi đến khi hệ thống bị xâm nhập mới bắt đầu đi vá víu.

Share: