Root không phải là thứ cho phép ứng dụng VPN Android mang lưu lượng, chặn rò rỉ hay tồn tại sau khi khởi động lại. Người ta gộp tất cả thành „ứng dụng có quyền VPN“, điều này che giấu ba cơ chế riêng biệt: sự đồng ý do người dùng cấp, giao diện gói do hệ thống thiết lập và chính sách chặn của nền tảng mà ứng dụng không được định nghĩa. Đánh giá thiết kế VPN Android nghĩa là hỏi một tuyên bố thực sự dựa vào cái nào trong ba thứ đó, vì mỗi thứ có chủ sở hữu và kiểu hỏng khác nhau.

Sự đồng ý đến qua một hoạt động hệ thống

VpnService.prepare() không cấp gì cả. Nó trả về intent cho hoạt động đồng ý của hệ thống khi thiếu sự đồng ý, và ứng dụng mở hộp thoại đó để người dùng phê duyệt dịch vụ. Việc khởi động tiến trình riêng của ứng dụng, thêm quyền vào manifest hay hiển thị màn hình „bật VPN“ tùy chỉnh không tạo ra sự cấp quyền.

Sự cấp quyền cũng có phạm vi. Nó thuộc về một gói trong hồ sơ người dùng, nên bản sao cá nhân và bản sao công việc là hai quyết định riêng, và chủ thiết bị có thể chuẩn bị hồ sơ được quản lý khác với hồ sơ cá nhân. Nếu hộp thoại không bao giờ xuất hiện và prepare() trả về null, sự đồng ý đã tồn tại cho gói đó trong hồ sơ đó; đó không phải bằng chứng ứng dụng đáng tin, chỉ là quyền đã có.

Giao diện là yêu cầu mà hệ thống đáp ứng

Sau khi đồng ý, ứng dụng mô tả điều mình muốn bằng VpnService.Builder: địa chỉ, tuyến, máy chủ DNS, MTU và khi được hỗ trợ, các ứng dụng cần đưa vào hoặc loại trừ. establish() yêu cầu hệ thống tạo giao diện đường hầm và dẫn lưu lượng tương ứng vào đó. Hệ thống sở hữu quyết định định tuyến; ứng dụng nhận bộ mô tả tệp và sau đó phải làm điều gì đó hữu ích với các gói.

What you observeWho actually owns it
VPN consent dialogThe system, triggered by prepare()
Routes, DNS and app listsThe app requests them; the system applies them
One active VPN per profileThe platform; a new service replaces the old one
Always-on and block-without-VPNDevice policy enforced by the platform

Bảng đó là kiến trúc ở một chỗ. Ứng dụng tham gia xử lý gói; nó không sở hữu giao diện, bảng định tuyến hay số dịch vụ được phép chạy.

Socket của đường hầm phải thoát khỏi đường hầm của chính nó

Kết nối mang lưu lượng đã mã hóa bản thân là một socket. Nếu nó bị định tuyến trở lại giao diện mà ứng dụng vừa tạo, đường hầm phụ thuộc vào đường hầm và dừng lại. VpnService.protect() gắn socket đó với mạng bên dưới để nó bỏ qua việc bắt gói, và đó là lý do một ứng dụng khách đúng đắn bảo vệ socket ngoài của nó trước lần bắt tay đầu tiên.

adb shell dumpsys connectivity | grep -i -A5 vpn
adb shell settings get global always_on_vpn_app
adb shell settings get global always_on_vpn_lockdown

Các lệnh này hiển thị mạng VPN đã cài, gói luôn bật và liệu chế độ khóa đã được đặt chưa. Đây là những quan sát chỉ đọc: nếu giá trị không khớp với điều thiết kế tuyên bố, tuyên bố đó nói về giao diện của ứng dụng chứ không phải trạng thái của hệ thống.

Việc chặn có thể thuộc về nền tảng

Android ghi nhận một chính sách chặn các kết nối không dùng VPN. Việc thực thi đó là hợp đồng của nền tảng, không phải ứng dụng lặp lại việc thử kết nối trong vòng lặp. Công tắc nằm trong cài đặt VPN của thiết bị với tên Chặn kết nối không có VPN, và trên thiết bị được quản lý, chủ sở hữu có thể bật nó cho toàn bộ hồ sơ. Sự khác biệt này quan trọng khi đánh giá một tuyên bố tiếp thị: ứng dụng khách có thể hiển thị biểu tượng ổ khóa và kết nối lại mạnh mẽ trong khi lưu lượng trực tiếp vẫn khả thi, hoặc các ứng dụng được bao phủ có thể vẫn ngoại tuyến vì hệ thống đang thực thi khóa.

Biểu tượng ổ khóa do ứng dụng vẽ, nên nó chỉ chứng minh ứng dụng tin rằng mình đã kết nối. Việc một ứng dụng khác mất quyền truy cập mạng do nền tảng quyết định, nên kiểm tra hữu ích là xem ứng dụng đó thất bại khi đường hầm đang bật.

Nhãn „luôn bật“ từ cửa hàng ứng dụng cũng không thay thế hợp đồng đó. Luôn bật và khóa là cài đặt của thiết bị, thường do chủ sở hữu áp dụng, và hành vi của chúng với các ứng dụng bị loại trừ do nền tảng định nghĩa. Hãy đọc cài đặt, không phải huy hiệu.

Bốn câu hỏi cho việc đánh giá thiết kế

Thứ nhất, ai đã đồng ý: gói nào, hồ sơ nào, và đó là người dùng hay chính sách thiết bị được quản lý? Thứ hai, ứng dụng đã yêu cầu gì: những tuyến nào, những họ địa chỉ nào, những ứng dụng nào được đưa vào hay loại trừ? Thứ ba, điều gì xảy ra khi đường hầm không khả dụng: hệ thống chặn hay lưu lượng quay về mạng bên dưới? Thứ tư, ứng dụng làm gì với các gói nhận được?

Câu hỏi thứ tư là câu mà mô hình quyền không thể trả lời. Sự đồng ý và giao diện TUN chứng minh ứng dụng có thể nhận lưu lượng, không phải rằng nó mã hóa, xác thực đối tác hay phục hồi sạch sẽ. Đó là thuộc tính triển khai, và đó là nơi một đánh giá trung thực dành thời gian.

Một yêu cầu root không cần thiết không trở nên chính đáng chỉ vì gọi kết quả là công tắc tiêu diệt, và hộp thoại đồng ý không phải cuộc kiểm toán bảo mật. Hãy giữ ba quyền riêng biệt và mọi tuyên bố trở nên có thể kiểm chứng.

Bài viết liên quan