Cách chạy một tiến trình Linux bên ngoài đường hầm WireGuard
Cung cấp cho một chương trình ngữ cảnh mạng riêng để nó rời khỏi máy chủ WireGuard có đường hầm đầy đủ, sau đó sửa các quy tắc chuyển tiếp và đánh dấu đang chặn nó.
Bạn không thể miễn trừ một chương trình khỏi máy chủ WireGuard có đường hầm đầy đủ bằng cách sửa tuyến đường. Tuyến đường chọn đường đi theo đích đến, còn thứ bạn muốn miễn trừ là một tiến trình, nên nhân không có gì để so khớp. Cách khả thi là cung cấp cho tiến trình đó ngữ cảnh mạng riêng: một không gian tên với giao diện, địa chỉ và tuyến mặc định của riêng nó, nối với máy chủ bằng một cặp veth. Tôi đã chạy trên Ubuntu 24.04 với wireguard-tools 1.0.20210914, và không gian tên chưa bao giờ là vấn đề — chính sách chuyển tiếp của máy chủ và các quy tắc đánh dấu của đường hầm mới là vấn đề.
Trước tiên hãy chọn loại ngữ cảnh bạn cần
Trong thực tế có hai dạng. Nếu máy chủ chạy đường hầm đầy đủ và một chương trình phải đi ra theo đường ISP, bạn dựng không gian tên thứ hai, nối nó với máy chủ và để máy chủ chuyển tiếp và dịch lưu lượng cho nó. Nếu không gian tên đã mang giao diện VPN và bạn chỉ cần một lệnh khởi chạy bên trong, đó là trường hợp thông thường của ip netns exec và phần lớn công việc định tuyến đã xong.
Không dạng nào cho bạn một quy tắc giới hạn ở một ID tiến trình. Netfilter so khớp địa chỉ, cổng, dấu và giao diện; không có bảng định tuyến theo từng tiến trình. Đánh dấu có thể định hướng lưu lượng, nhưng dấu phải được đặt trên các gói bạn đã nhận diện, và đó là cùng vấn đề ở một tầng thấp hơn. Không gian tên tách toàn bộ ngăn xếp cho cây tiến trình đó, và đó là lý do nó là câu trả lời thông thường.
Nếu yêu cầu thực sự là không có gì ra khỏi đường hầm, hãy dừng đường hầm thay vì vậy. Không gian tên tồn tại cho trường hợp hỗn hợp: một chương trình ra ngoài, mọi thứ khác vào trong, trên cùng một máy, cùng lúc.
Dựng ngữ cảnh thứ hai và nối nó với máy chủ
Một bố cục minh họa: máy chủ có giao diện WireGuard mang tuyến mặc định, và một không gian tên mạng tên là clearnet nối với máy chủ bằng một cặp veth. Các địa chỉ bên dưới là ví dụ.
ip netns add clearnet
ip link add veth-clear-out type veth peer name veth-clear-in
ip addr add 192.168.100.1/24 dev veth-clear-out
ip link set veth-clear-out up
ip link set veth-clear-in netns clearnet
ip netns exec clearnet ip addr add 192.168.100.2/24 dev veth-clear-in
ip netns exec clearnet ip link set veth-clear-in up
ip netns exec clearnet ip route add default via 192.168.100.1
Không gian tên đó giờ có thể đến được máy chủ và không gì khác. Máy chủ phải chuyển tiếp lưu lượng và viết lại địa chỉ nguồn, vì 192.168.100.0/24 là riêng tư và bộ định tuyến phía trên không có tuyến quay lại vào nó:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE
Xác nhận phía không gian tên trước khi đi tiếp.ip netns exec clearnet ip route sẽ hiển thị tuyến veth và tuyến mặc định qua 192.168.100.1, và ping tới địa chỉ đó sẽ trả lời. Nếu ping tới địa chỉ máy chủ thất bại, địa chỉ hoặc trạng thái liên kết sai và không quy tắc tường lửa nào giúp được.
Khi tên phân giải được nhưng không có gì quay lại, hãy đọc FORWARD
Lỗi kinh điển trông như một lỗi định tuyến: không gian tên phân giải một tên, gói tin ra ngoài và không bao giờ có phản hồi. Trên các máy chủ có chính sách FORWARD là DROP — một số bản phân phối và hầu hết ảnh được gia cố làm vậy — gói tin bị bỏ trên đường, và lỗi mà ứng dụng in ra không nói gì về việc lọc.
Đọc chuỗi trước khi thêm bất cứ gì:
iptables -S FORWARD
nft list chain inet filter forward
Sau đó cho lưu lượng đi qua cả hai hướng, kèm bộ đếm, để biết quy tắc có từng khớp hay chưa:
iptables -A FORWARD -i veth-clear-out -o <wan-interface> -j ACCEPT
iptables -A FORWARD -i <wan-interface> -o veth-clear-out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
watch -n1 'iptables -L FORWARD -v -n'
Một quy tắc có bộ đếm gói bằng không thì không nằm trên đường. Hoặc tên giao diện khác với điều bạn giả định, hoặc một quy tắc trước đó trong chuỗi đã chấp nhận, bỏ hay trả gói tin trước. Sửa thứ tự, không sửa văn bản quy tắc.
Lưu lượng trả lời là nửa mà người ta quên. Quy tắc quay lại cần cùng tên veth cộng với khớp trạng thái kết nối, hoặc chấp nhận giao diện đơn giản nếu bạn giữ chính sách mở. Chỉ thêm quy tắc đi ra và triệu chứng ban đầu quay lại, trong khi quy tắc mới đứng đó và trông có vẻ đúng.
Giữ các quy tắc đánh dấu của đường hầm tránh xa đường mới
Bước này biến một không gian tên đang hoạt động thành một không gian tên bị rò. Các thiết lập WireGuard thường cài một chính sách dấu tường lửa cùng với quy tắc định tuyến của riêng chúng và một bảng riêng, nên các gói không có dấu rơi về bảng chính trong khi các gói có dấu dùng bảng của đường hầm. Lưu lượng được chuyển tiếp từ không gian tên được đánh giá theo định tuyến chính sách khi ra ngoài, và tùy vào cách các quy tắc đó được viết, nó có thể rơi vào bảng của đường hầm.
Hai phần bổ sung tách các đường. Quay lại sớm trong chuỗi mangle cho subnet của không gian tên, và thêm một quy tắc dựa trên nguồn đặt subnet đó vào bảng chính:
iptables -t mangle -I PREROUTING -s 192.168.100.0/24 -j RETURN
ip rule add from 192.168.100.0/24 lookup main priority 100
Mức ưu tiên 100 xếp trước các quy tắc của đường hầm trên máy của tôi, nên với nguồn đó bảng thường quyết định. Đừng sao chép con số một cách mù quáng: các mức ưu tiên mà wg-quick cài đặt khác nhau giữa các phiên bản và giữa thiết lập IPv4 với IPv6, nên hãy chạy ip rule show và chọn một mức ưu tiên rơi trước các quy tắc của đường hầm trên máy bạn.
Xác minh bằng tra cứu riêng theo nguồn thay vì tin vào danh sách quy tắc:
ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1
Nếu lệnh đầu báo giao diện WireGuard, quy tắc mới chưa nằm trước chính sách của đường hầm. Nếu nó báo giao diện WAN trong khi lệnh thứ hai vẫn hiển thị tuyến mặc định veth, máy chủ và không gian tên không đồng ý và bạn nên đọc lại cả hai bảng định tuyến.
Khởi chạy tiến trình mở kết nối
Khởi chạy lệnh là một dòng, nhưng hãy khởi chạy tiến trình thực sự tạo socket.ip netns exec clearnet curl -s https://ifconfig.me là bài kiểm tra trung thực nhỏ nhất: nó cho thấy địa chỉ mà không gian tên trình bày với thế giới, không phải địa chỉ máy chủ sẽ dùng.
Với một dịch vụ, hãy gắn không gian tên theo đường dẫn để tiến trình ở trong đó suốt đời:
[Service]
NetworkNamespacePath=/run/netns/clearnet
Ứng dụng đồ họa là nơi cách một dòng âm thầm thất bại. Trình duyệt khởi chạy từ menu thường giao yêu cầu cho một phiên bản đã chạy ngoài không gian tên, nên cửa sổ mới xuất hiện và lưu lượng vẫn ra qua đường hầm. Cung cấp cho nó một hồ sơ riêng để một phiên bản mới thực sự được tạo, rồi kiểm tra ngữ cảnh tiến trình thay vì đoán:
readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet
Hai kết quả phải khớp nhau. Cùng phép kiểm tra đó hiệu quả cho bất kỳ chương trình chạy lâu nào, và đáng làm một lần cho mỗi ứng dụng thay vì cho rằng trình khởi chạy đã làm điều bạn định.
Phân giải tên cần quyết định riêng. Tạo không gian tên không cấp cho nó cấu hình bộ phân giải; các tệp cho từng không gian tên được hỗ trợ qua /etc/netns/<name>/resolv.conf và không có nó bạn thừa hưởng hành vi dễ đọc sai. IPv6 cần cách xử lý tương tự: nếu không gian tên không có tuyến mặc định v6 trong khi ứng dụng ưu tiên v6, các yêu cầu có thể treo trước khi lùi lại, trông như một đường hầm hỏng.
Kiểm tra khung, không chỉ địa chỉ ra ngoài
Một địa chỉ công khai hoạt động chứng minh tuyến, không phải toàn bộ yêu cầu. Đi qua phần còn lại theo thứ tự này:
ip netns exec clearnet ip route get 1.1.1.1hiển thị tuyến mặc định veth, không phải giao diện WireGuard.- Bộ đếm FORWARD trên cả hai quy tắc tăng khi một yêu cầu đang chạy.
- Tiến trình ứng dụng báo inode không gian tên mà bạn mong đợi.
- Sau khi khởi động lại, không gian tên tồn tại trước khi dịch vụ bắt đầu; unit chạy sớm hơn sẽ thất bại hoặc, tệ hơn, chạy ngoài không gian tên.
Sau đó quyết định điều gì phải xảy ra khi đường hầm sập. Không gian tên tiếp tục hoạt động, đó là mục đích của bài tập và cũng là rủi ro: chương trình được miễn trừ vẫn kết nối trong khi mọi thứ khác dừng lại. Ghi điều đó như một lựa chọn chính sách và nói rõ điều mà miễn trừ không bao phủ — danh tính tài khoản, trạng thái trình duyệt đã lưu và nhà cung cấp DNS của bạn đều nằm ngoài phạm vi của một không gian tên mạng, và coi miễn trừ là ẩn danh chính là lỗi sống lâu hơn cấu hình.