Đặt một máy khách VPN vào vùng chứa và bạn có một không gian tên với một đường hầm bên trong, không phải một máy chủ định tuyến toàn bộ lưu lượng của nó qua VPN. Đây là những dự án riêng biệt, và việc coi chúng là một chính là cách các vùng chứa vô tình trở nên đặc quyền. Hướng dẫn này chỉ đề cập trường hợp đầu tiên: một image đã được duyệt, một profile được bảo vệ và một tiến trình máy khách bị giới hạn trong không gian tên mạng của riêng nó.

Bắt đầu từ một artifact mà ai đó đã phê duyệt. Các bước dưới đây giả định một image chứa tệp thực thi openvpn và một profile máy khách đầy đủ với chứng chỉ và vật liệu khóa đã được giải quyết bên trong mount. Chúng không xây dựng phần mềm, không phát hành thông tin xác thực và không bao gồm môi trường chạy không có root hay vùng chứa Windows gốc, mỗi thứ đều thay đổi câu trả lời.

Vùng chứa nhận được gì và không nhận được gì

Giữ profile và mọi thứ nó tham chiếu trong một thư mục cục bộ với quyền hạn chế, được mount chỉ đọc. Các đường dẫn tương đối bên trong profile phải được giải quyết trong mount đó; đây là chi tiết mà mọi người bỏ sót khi chứng chỉ nằm một thư mục phía trên profile và vùng chứa không bao giờ nhìn thấy nó.

services:
  vpn:
    image: ${VPN_CLIENT_IMAGE:?set the reviewed image reference}
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    volumes:
      - ./vpn:/vpn:ro
    working_dir: /vpn
    entrypoint: ["openvpn"]
    command: ["--config", "/vpn/client.ovpn"]

Tệp đó cung cấp ba thứ và không yêu cầu gì khác. Tham chiếu image nên được ghim bằng digest nếu chính sách triển khai của bạn nói vậy, và profile phải là bản đã được duyệt, không phải một bản sao mà ai đó đã sửa ngay trên máy chủ.

Chỉ đọc ở đây có nghĩa là vùng chứa không thể sửa đổi các tệp của bạn trên máy chủ; nó không có nghĩa là vùng chứa không thể đọc khóa riêng mà bạn đã mount. Đó là toàn bộ mục đích của mount, và cũng là lý do quyền tệp, quyền sở hữu và cách bí mật đến được máy chủ vẫn quan trọng. Không bao giờ truyền mật khẩu trên dòng lệnh và không nướng nó vào một lớp image, vì cả hai đều tồn tại ở những nơi bạn không thể dọn dẹp sau này.

Khả năng, entrypoint và cái bẫy giữa chúng

Cần hai cài đặt và chúng làm những việc không liên quan. NET_ADMIN cho phép thao tác giao diện và tuyến bên trong không gian tên của vùng chứa. Mục thiết bị /dev/net/tun cho phép tiến trình mở thiết bị đường hầm ngay cả khi đó. Cấp một mà không cấp cái kia tạo ra một lỗi rõ ràng, điều này thuận tiện: thiết bị TUN thiếu sẽ thất bại khi mở, trong khi khả năng thiếu sẽ thất bại khi máy khách cố cấu hình giao diện.

Không cái nào trong hai cái đó biện minh cho privileged: true. Một vùng chứa đặc quyền nhận mọi khả năng cộng với quyền truy cập thiết bị, và đó là một sự cấp phép lớn hơn nhiều so với nhu cầu của khối lượng công việc này. tài liệu tham khảo về đặc quyền và khả năng của môi trường chạy giải thích sự cấp phép đó đi xa đến đâu. Nếu một chart hoặc bài blog yêu cầu điều đó, trước tiên hãy kiểm tra xem yêu cầu có thực sự là một đường dẫn thiết bị bị thiếu hay một khả năng bị thiếu không.

Ghi đè entrypoint là phần cắn người. Gọi trực tiếp openvpn là đúng với một image thông thường và sai với bất kỳ image sản phẩm nào mà script khởi động chuẩn bị quy tắc tường lửa, tệp phân giải hoặc thông tin xác thực trước khi chạy daemon. Ghi đè script đó bỏ qua việc chuẩn bị và để bạn gỡ lỗi một đường hầm khởi động trong không gian tên được cấu hình nửa vời.

Chạy máy khách ở tiền cảnh và để nó là tiến trình chính của vùng chứa. Một tiến trình trở thành daemon sẽ thoát ngay lập tức, vùng chứa khởi động lại trong vòng lặp, và các log bạn cần bị phân tán qua những lần khởi động lại trông giống hệt nhau.

Xác minh từ bên trong không gian tên, không phải từ máy chủ

Dựng stack lên, xác nhận trong log rằng máy khách đã đạt trạng thái kết nối, sau đó kiểm tra không gian tên thực sự giữ đường hầm.

docker compose up -d
docker compose logs --tail 40 vpn
docker compose exec vpn ip -br addr
docker compose exec vpn ip route

Danh sách địa chỉ phải hiển thị một giao diện đường hầm với địa chỉ từ pool, và bảng tuyến phải hiển thị các đích được đẩy trỏ vào nó. Nếu giao diện thiếu, máy khách chưa bao giờ đến bước tạo nó. Nếu nó tồn tại nhưng không tuyến nào dùng nó, nơi cần xem là push hoặc các tùy chọn tuyến.

Sau đó kiểm tra đích bạn quan tâm, từ không gian tên lẽ ra phải dùng đường hầm, bằng ứng dụng chứ không chỉ bằng ping. Phân giải tên là một lỗi riêng đáng được kiểm tra rõ ràng: một địa chỉ DNS được đẩy không tự cập nhật bộ phân giải của vùng chứa, và một máy khách độc lập bỏ qua push sẽ phân giải tên qua những gì image đã cấu hình.

Trạng thái ngắt kết nối là một phần của hợp đồng

Hành vi kết nối lại cần kiểm tra riêng, vì chính sách khởi động lại chứng minh tiến trình khởi động lại và không nói gì về việc lưu lượng làm gì ở giữa. Dừng đường hầm, thử đích dự định và quan sát xem kết nối bị từ chối, bị treo hay âm thầm thành công qua tuyến thông thường của vùng chứa. Kết quả cuối cùng là kết quả quan trọng, và nó vô hình trong một log khỏe mạnh.

Nếu khối lượng công việc không bao giờ được dùng đường thông thường, hãy thiết kế điều đó một cách rõ ràng bằng quy tắc tường lửa và tín hiệu sẵn sàng bên trong không gian tên. Kill switch là một chính sách bạn viết và kiểm tra, không phải thuộc tính bạn thừa hưởng từ việc chạy máy khách trong vùng chứa.

Cuối cùng, hãy nhớ ranh giới: các tuyến này sống trong không gian tên của vùng chứa và không thay thế bảng định tuyến của máy chủ. Các quy tắc chuyển tiếp, biên dịch và tường lửa của Docker vẫn là một phần của đường đi bên ngoài, và một cổng được công bố không phải là giao diện VPN.

Bài viết liên quan