Một tuyến đường được thêm vào bảng main trên Android trông đúng trong mọi danh sách và vẫn không mang lưu lượng. Lý do là bảng main chỉ là một lựa chọn trong số nhiều lựa chọn, và nó không được hỏi đến trước. Dịch vụ mạng của Android xây dựng các quy tắc chính sách chọn bảng định tuyến bằng thông tin mà địa chỉ đích không chứa — uid của ứng dụng, dấu trên gói tin, giao diện mà nó đến — và việc tra cứu đích diễn ra sau đó, bên trong bảng mà các quy tắc ấy đã chọn.

Ba quyết định theo một thứ tự cố định

Một gói tin đi ra thực hiện ba quyết định riêng biệt. Thứ nhất, một quy tắc chính sách quyết định bảng định tuyến nào được áp dụng. Thứ hai, một tuyến trong bảng đó quyết định chặng kế tiếp và giao diện ra. Thứ ba, các móc netfilter quyết định gói tin sống sót, bị sửa đổi hay bị chuyển hướng.

Thứ tự quan trọng vì mỗi giai đoạn chỉ có thể trả lời câu hỏi của chính nó. Một quy tắc tường lửa chấp nhận gói tin không chọn bảng, và một tuyến được thêm vào bảng mà không quy tắc nào chọn thì vô hiệu. Phần lớn sự nhầm lẫn quanh VPN trên Android đến từ việc sửa một trong ba rồi không thấy thay đổi, vì lỗi nằm ở một cái khác.

StageSelectorWhat it cannot decide
Policy ruleuid range, mark, incoming interfaceWhich route exists inside the table
Route lookupDestination prefix, longest matchWhether the packet is allowed out
Netfilter hookChain position, match conditionsWhich table was selected

Dấu là một trường được đóng gói, không phải nhãn bạn sở hữu

Android đóng gói nhiều sự thật vào cùng một giá trị dấu: mạng nào được chọn, ứng dụng có chọn mạng một cách rõ ràng hay không, socket có được bảo vệ khỏi VPN hay không, và các bit liên quan đến quyền. Tiêu đề fwmark của AOSP định nghĩa cách bố trí đó cho cây hiện tại, và cách bố trí là chi tiết nội bộ của nền tảng thay đổi giữa các bản phát hành.

Đó là lý do trên Android việc ghi toàn bộ giá trị dấu bằng iptables -j MARK --set-mark là nguy hiểm. Nó không thêm thẻ; nó thay thế lựa chọn mạng mà hệ thống đã thực hiện. Gói tin sau đó khớp với các quy tắc khác, điều này có thể trông như VPN bắt đầu hoạt động, hoặc như một ứng dụng không liên quan mất kết nối, tùy thuộc vào các bit bị ghi đè.

Nếu buộc phải chạm vào dấu, hãy đọc giá trị hiện tại trước và dùng mặt nạ để chỉ những bit bạn hiểu được thay đổi:

ip rule show
ip route show table all | head -40
ip route get 10.20.4.11

Dấu kết nối là một đối tượng riêng so với dấu gói tin, và không cái nào là tuyến đường. Khôi phục dấu trên gói tin trả lời là một bước riêng so với việc chọn bảng khi đi ra, vì thế các bản sửa một chiều tạo ra những kết nối mở ra rồi bị treo.

Ai sở hữu các quy tắc và bảng

Dịch vụ mạng của Android, netd, tạo ra các quy tắc và bảng theo từng mạng. AOSP RouteController là nơi các quy tắc đó được lắp ghép cho VPN, mạng vật lý và dải uid, và vòng đời của nó gắn với các sự kiện mạng chứ không phải một tệp cấu hình.

Hai hệ quả đi kèm. Thứ nhất, mức ưu tiên và số bảng mà bạn tìm thấy trên một thiết bị là chi tiết nội bộ của bản dựng, không phải giao diện: những con số trông giống nhau trên phiên bản Android khác có thể mang ý nghĩa hoàn toàn khác. Thứ hai, trạng thái được dựng lại khi mạng thay đổi, nên một quy tắc chèn hôm nay từ shell root có thể biến mất sau lần chuyển Wi-Fi tiếp theo.

Sự biến mất đó thường được báo cáo như hệ thống phớt lờ một tuyến đường. Điều thực sự xảy ra là quy tắc chọn bảng không còn tồn tại, và tuyến trong bảng giờ không thể đến được từ góc nhìn của gói tin. Hãy kiểm tra danh sách quy tắc, không phải danh sách tuyến đường, khi một cấu hình đang chạy ngừng chạy sau khi kết nối lại.

Câu hỏi về thứ tự các móc không có câu trả lời phổ quát

Câu hỏi iptables có chạy trước định tuyến VPN hay không không thể trả lời mà không nêu rõ đường đi của gói tin. Một gói tin được tạo cục bộ đi qua móc output, nơi thay đổi dấu kích hoạt việc kiểm tra định tuyến lại — một lần tra cứu thứ hai, không phải chỉnh sửa hồi tố lần đầu. Một gói tin đến từ máy khách qua tether đi theo đường prerouting và được chuyển tiếp thay vào đó, và các chuỗi nhìn thấy nó là khác.

Vì vậy cùng một quy tắc có thể hiệu quả với lưu lượng của một ứng dụng và vô hình với lưu lượng qua tether, và một bộ đếm đứng ở số không cho bạn biết gói tin đã đi đường nào, không phải quy tắc có sai hay không. Hãy dùng bộ đếm để xác lập đường đi trước khi thay đổi bất kỳ điều kiện khớp nào.

Đây cũng là giai đoạn mà một lỗi định tuyến theo chính sách trở nên khó thấy. Định tuyến tới một bảng tồn tại nhưng không chứa đích tạo ra mạng không thể đến, trông giống như tường lửa loại bỏ, trong khi tường lửa loại bỏ tạo ra hết thời gian chờ trông giống như hố đen định tuyến.

Chẩn đoán bên trong hệ thống, hoặc để yên

Đối với một cuộc rà soát được phép, hãy xác lập bốn sự thật trước khi chạm vào bất cứ thứ gì: uid và hồ sơ của ứng dụng, mạng mà Android đã chọn cho nó, liệu VPN có bao gồm ứng dụng đó hay không, và liệu vấn đề có tồn tại ở cả hai họ địa chỉ hay không. Việc loại trừ theo từng ứng dụng giải thích rất nhiều báo cáo VPN không hoạt động mà không có lỗi định tuyến nào.

Sau đó đọc các quy tắc, mặt nạ và bảng thực sự có hiệu lực, và giữ một lần chuyển mạng trong cửa sổ quan sát. Nếu hành vi thay đổi qua một lần kết nối lại, bạn đang nhìn vào một vòng đời được quản lý, không phải một tuyến bị thiếu.

Đối với các nhu cầu thông thường, hãy dùng các điều khiển được hỗ trợ: bao gồm và loại trừ theo từng ứng dụng trong ứng dụng VPN, và việc chọn mạng của chính nền tảng cho mọi thứ cần một đường đi cụ thể. Nếu một tích hợp đặc quyền thực sự phải phối hợp với bộ máy định tuyến, hãy nhắm tới việc triển khai đúng phiên bản Android mà bạn hỗ trợ và duy trì vòng đời của nó qua thành phần sở hữu nó. Việc xóa chuỗi của nền tảng hoặc chèn một quy tắc ưu tiên cao biến một chẩn đoán thành trình quản lý mạng thứ hai, và điện thoại sẽ hành xử tương ứng.

Bài viết liên quan