Dịch vụ khởi động, nhật ký phàn nàn rằng nó không mở được thiết bị tun, và các tuyến đường không bao giờ xuất hiện. Chạy capsh --print trong shell của bạn và cap_net_admin có ngay ở đó, khiến lỗi trông như không thể xảy ra. Điều khác biệt giữa shell của bạn và unit là quá trình chuyển đặc quyền, không phải việc nhân sẵn lòng cấp khả năng. Hãy đi qua bốn bước kiểm tra bên dưới theo thứ tự và dừng ở bước đầu tiên giải thích được khoảng cách.

Tách biệt khả năng bị thiếu với thiết bị bị ẩn

Hai lỗi trông giống nhau từ dòng nhật ký. Một tiến trình không có CAP_NET_ADMIN không thể tạo hoặc cấu hình giao diện đường hầm, và một tiến trình mà sandbox ẩn /dev/net/tun thì không thể mở nó ngay từ đầu. Thêm khả năng sẽ không sửa được trường hợp thứ hai.

Kiểm tra xem thiết bị có tồn tại bên trong không gian tên của dịch vụ trước khi bạn sửa bất cứ thứ gì. PrivateDevices=yes là một dòng tăng cường phổ biến loại bỏ hoàn toàn nút tun, và ProtectSystem hạn chế có thể làm cho đường dẫn cấu hình chỉ đọc theo cách đọc lên như một lỗi quyền. Cả hai đều tạo ra những dòng nhật ký nhắc đến đường hầm, đó là lý do các khả năng bị đổ lỗi. Trước tiên hãy xác nhận nút tồn tại và mở được, rồi mới đi tiếp.

Biết bạn đang nhìn vào bộ khả năng nào

Linux giữ các bộ được phép, hiệu lực, kế thừa, giới hạn và môi trường, và bộ môi trường là bộ sống sót qua exec của người dùng không phải root. Khả năng tệp trên tệp nhị phân có thể chuyển giao quyền được phép và hiệu lực khi exec, nhưng chỉ chừng nào không có gì trong chuỗi chặn việc chuyển giao đó.

Đây là chỗ sudo đánh lừa người ta. Một lệnh chạy qua sudo -u bắt đầu một quá trình chuyển đặc quyền mới và bộ môi trường biến mất, nên cùng một bước kiểm tra thành công khi là root lại thất bại ở đó. Trình quản lý dịch vụ lại là một lần chuyển nữa, và nó không cấp gì thuộc môi trường trừ khi unit nói vậy.

Cấp khả năng trong unit, không phải trong lớp bọc

Một phần dịch vụ tối thiểu cho đường hầm cần tạo thiết bị và cài đặt tuyến đường trông như sau.

[Unit]
Description=OpenVPN client, office profile
After=network-online.target

[Service]
Type=notify
User=openvpn
Group=openvpn
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_ADMIN
CapabilityBoundingSet=CAP_NET_ADMIN
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/office.conf

AmbientCapabilities đặt quyền vào bộ môi trường trước khi tiến trình khởi động, và CapabilityBoundingSet ngăn tiến trình giữ bất cứ thứ gì ngoài danh sách đó. NoNewPrivileges=yes chặn việc giành đặc quyền qua setuid hoặc khả năng tệp, trong khi khả năng mà unit cấp rõ ràng vẫn áp dụng. Chỉ thêm CAP_NET_BIND_SERVICE khi dịch vụ phải gắn một cổng thấp, và đừng bao giờ thêm CAP_SYS_ADMIN chỉ vì một chủ đề diễn đàn đã làm vậy.

Nếu unit bọc tệp nhị phân trong sudo, hãy bỏ lớp bọc. systemd đã áp dụng User=, và chính lớp thừa đó là lý do khả dĩ nhất khiến bộ môi trường trống.

Xác minh trên tiến trình đang chạy, không phải trên tệp unit

Đọc những gì trình quản lý thực sự đã áp dụng, rồi đọc tiến trình mà nó sinh ra.

unit=openvpn-client@office
systemctl show -p User -p AmbientCapabilities "$unit"
systemctl show -p MainPID --value "$unit" | xargs -r getpcaps
grep -E '^Cap(Eff|Amb)' /proc/$(systemctl show -p MainPID --value "$unit")/status

Nếu unit liệt kê khả năng mà CapEff vẫn chưa có, một drop-in nào đó đang ghi đè cài đặt hoặc một bước ExecStartPre đang thay đổi môi trường. Hãy tìm tên unit trong các thư mục drop-in trước khi cho rằng tệp chính là có thẩm quyền, vì một tệp đến sau sẽ thắng một cách lặng lẽ. Nếu cả unit và tiến trình đều hiển thị khả năng mà đường hầm vẫn hỏng, hãy quay lại các bước kiểm tra thiết bị và đường dẫn thay vì mở rộng bộ giới hạn. Mở rộng nó che giấu nguyên nhân thật và để dịch vụ có nhiều đặc quyền hơn trước.

Nên từ bỏ đặc quyền sau khi khởi động

OpenVPN có thể khởi động với đặc quyền rồi hạ xuống một tài khoản không đặc quyền thông qua các tùy chọn user và group của chính nó, với persist-key và persist-tun giữ cho đường hầm vẫn dùng được sau đó. Cách bố trí đó thu hẹp khoảng thời gian tiến trình nắm quyền, và nó thường phù hợp hơn việc khởi động toàn bộ daemon không đặc quyền với các khả năng thường trực.

Dù chọn mô hình nào, hãy khởi động lại unit và lặp lại các bước kiểm tra sau khi khởi động lại, vì một dịch vụ chạy được từ shell root tương tác mà hỏng khi khởi động thường là khác biệt về khả năng, thiết bị hoặc quyền tệp. Ghi lại cài đặt của unit bên cạnh đầu ra khả năng của tiến trình để người đánh giá tiếp theo thấy liệu một bản cập nhật gói hay một drop-in đã dịch chuyển ranh giới.

Bài viết liên quan