Một chương trình nên dùng kết nối thường trong khi mọi thứ khác ở lại trong đường hầm, và máy khách không có công tắc cho việc đó. Cũng không có menu ẩn nào để tìm. Tuyến được chọn từ các trường bên trong gói, và gói mang địa chỉ và cổng chứ không phải danh tính của tiến trình đã tạo ra nó, nên việc loại trừ phải được biểu đạt trong một trường đó. Theo dõi một gói một lần và các lựa chọn sẵn có không còn bí ẩn nữa.

Vì sao máy khách không thể cung cấp

Định tuyến theo đích so sánh địa chỉ đích với các tiền tố và giữ mục khớp dài nhất. Ở thời điểm đó mọi gói trông giống nhau, bất kể cái gì đã tạo ra nó. Định tuyến theo chính sách nguồn mở rộng so sánh sang địa chỉ nguồn, và đó là cái móc mà mọi giải pháp thực tế dùng: đổi nguồn và một bảng khác trở nên hợp lệ.

Cổng không giúp được gì. Loại trừ theo cổng sẽ phải được đánh giá trước khi tra cứu đích, và cổng không có vai trò nào trong quyết định đó. Bất cứ điều gì được quảng cáo là loại trừ dựa trên cổng thực ra loại trừ theo một trường khác và mô tả điều đó một cách lỏng lẻo.

Định tuyến thật theo ứng dụng tồn tại ở nơi nền tảng đã thêm cơ chế cho nó, như các lệnh gọi bộ lọc trên Windows hay việc gắn dịch vụ VPN trên Android. Một bản OpenVPN trên máy tính để bàn không mang theo bất kỳ thứ nào trong số đó, và không cờ cấu hình nào bịa ra nó.

Linux: đánh dấu tiến trình, rồi định tuyến dấu

Cách tiếp cận sạch nhất gắn quyết định với tiến trình sở hữu socket. Việc khớp owner hoạt động cho lưu lượng tạo tại chỗ trong chuỗi OUTPUT, nên một dấu đặt ở đó có thể chọn một bảng riêng:

iptables -t mangle -A OUTPUT -m owner --uid-owner 1001 -j MARK --set-mark 0x1
ip rule add fwmark 0x1 table 200
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.0 table 200
ip route add default via 192.168.1.1 dev eth0 table 200

Các gói từ người dùng 1001 sau đó tham chiếu bảng 200 và ra ngoài qua cổng mặc định, trong khi bảng chính vẫn gửi mọi thứ khác vào đường hầm. Việc khớp owner chỉ áp dụng cho các gói được tạo tại chỗ, đúng là lưu lượng quan trọng ở đây, và nó không thể phân loại các gói được chuyển tiếp cho một máy khác. Hãy kiểm chứng bằng công cụ chứ không bằng ý định: ss -tnp cho thấy địa chỉ tại chỗ và tiến trình sở hữu của các kết nối đã thiết lập, và ip route get 1.1.1.1 mark 0x1 cho thấy dấu chọn bảng nào.

Không gian tên mạng là câu trả lời vững chắc hơn cho một chương trình tự chứa, vì mọi socket tạo bên trong đều bị ràng buộc với nó theo cấu trúc, nên các tiến trình phụ và kết nối con thừa hưởng hành vi mà không cần phân loại gì cả. Cái giá là hệ thống đường ống: một cặp veth, một địa chỉ ở mỗi đầu, và một tuyến mặc định bên trong không gian tên trỏ ngược về máy chủ.

ip netns add novpn
ip link add veth-host type veth peer name veth-ns
ip link set veth-ns netns novpn
ip addr add 10.200.0.1/24 dev veth-host
ip netns exec novpn ip addr add 10.200.0.2/24 dev veth-ns
ip netns exec novpn ip route add default via 10.200.0.1

Windows: đích vẫn quyết định

Windows chọn giao diện ra dựa trên đích, nên một chương trình muốn đường khác phải thay đổi thứ mà ngăn xếp hỏi trước khi lựa chọn đó được thực hiện. ForceBindIP bao phủ nửa đầu: nó khởi chạy chương trình với các socket đã gắn vào địa chỉ tại chỗ mà bạn nêu. Chỉ riêng điều đó không thay đổi giao diện mà gói đi ra, vì đích vẫn chọn tuyến. Hãy gắn một nguồn trên một laptop có tuyến mặc định trỏ vào đường hầm và gói vẫn đi vào đường hầm.

Triệu chứng có một hình dạng đọc được một khi bạn biết nó. Nó đúng với một địa chỉ LAN mà giao diện đã chọn đến trực tiếp và thất bại với mọi thứ trên internet có tuyến trỏ vào đường hầm. Nó cũng có vẻ hoạt động cho đến khi chương trình giao việc cho một trình phụ, vì một trình phụ tự mở socket của mình chưa bao giờ được cho biết về việc gắn.

Chuyển quyết định khi một tiến trình là đơn vị sai

Nếu yêu cầu thật là một thiết bị chứ không phải một chương trình, hãy đặt nó trên SSID hoặc VLAN riêng và để router quyết định: nguồn đó đi đường bình thường trong khi các nguồn khác dùng đường hầm. Một máy cổng chuyên dụng là thiết kế trung thực còn lại: nó giữ VPN và chỉ nhận những đích mà router gửi đến nó. Trên một VLAN, chính sách bao phủ mọi luồng mà thiết bị mở, kể cả các tiến trình phụ đã phá vỡ cách làm của Windows. Cái đánh đổi là phạm vi: hai chương trình trên thiết bị đó không còn được đối xử khác nhau nữa.

Cả hai đều là chính sách nguồn hoặc đích với một phạm vi có thể nói trong một câu. Không cái nào là theo ứng dụng, và một thiết kế tự bán mình là theo ứng dụng sẽ thất bại ngay lần đầu chương trình giao việc của nó cho một tiến trình thứ hai.

Bài viết liên quan