Bạn đăng nhập vào router, dán một bộ quy tắc kill switch lấy từ bài đăng trên diễn đàn, và LAN ngừng duyệt web ngay khi tunnel sập. Hai ngày sau, router vẫn cập nhật bản ghi DNS động qua WAN thông thường, và laptop của khách vẫn truy cập được các trang IPv6. Cả hai hành vi đều bình thường, vì các quy tắc đã dán chỉ bao phủ một chuỗi và một họ địa chỉ, và không cái nào trong đó là toàn bộ router. Đi qua các đường đi của gói tin theo thứ tự sẽ cho thấy chính xác điều gì đã bị bỏ sót.

Bắt đầu từ router, không phải từ laptop

Chính sách ở cấp router hấp dẫn với một văn phòng nhỏ vì mọi thiết bị phía sau đều thừa hưởng cùng hành vi và không ai có thể quên bật một công tắc trên máy khách. Nó cũng cho bạn một nơi duy nhất để kiểm tra sau mỗi lần cập nhật firmware. Điều nó không cho là phạm vi tự động cho lưu lượng của chính router hoặc cho họ địa chỉ thứ hai, và đó là hai lỗ hổng đằng sau phần lớn các lần triển khai thất bại.

Trước khi sửa bất cứ thứ gì, hãy ghi ba dữ kiện ra giấy: tên giao diện WAN, tên cầu LAN, và địa chỉ cùng cổng của điểm cuối VPN. Bạn sẽ cần cả ba trong các quy tắc, và đoán tên giao diện là lý do phổ biến nhất khiến một bộ quy tắc trông đúng lại không làm gì cả.

Đi qua ba đường đi mà một gói tin có thể theo

Lưu lượng từ laptop ra internet được chuyển tiếp, nên nó đi qua chuỗi FORWARD. Lưu lượng do chính router tạo ra, như chuyển tiếp DNS, truy vấn NTP, cập nhật DDNS và kênh điều khiển VPN, đi qua OUTPUT. Lưu lượng quản trị hướng tới router đi vào qua INPUT.

Vì vậy một kill switch chỉ xây trong FORWARD bảo vệ máy khách và không gì khác. Bảng cho thấy vì sao sự rò rỉ trong cảnh mở đầu là có thể đoán trước chứ không hề bí ẩn.

Packet pathExampleChain that sees it
LAN client to WAN or tunnelBrowser requestFORWARD
Router-originatedDDNS update, NTPOUTPUT
Addressed to the routerSSH from the LANINPUT

Trong hầu hết thiết kế bạn không cần kill switch trên INPUT, nhưng bạn cần giữ quyền truy cập quản trị hoạt động khi tunnel đã tắt. Nếu không, lần đầu VPN hỏng bạn sẽ lái xe đến văn phòng với một cáp console.

Sắp xếp quy tắc để tunnel vẫn có thể khởi động

Một kill switch hoạt động là danh sách cho phép kết thúc bằng một lệnh từ chối, và thứ tự chính là thứ biến nó thành kill switch thay vì một viên gạch. Trước hết cho phép loopback, điểm cuối VPN, các phản hồi cho luồng đã thiết lập và giao diện tunnel; từ chối phần còn lại sau cùng.

iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d 198.51.100.7 -p udp --dport 51820 -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o wg0 -j ACCEPT
iptables -A OUTPUT -o eth0 -j REJECT

Điểm cuối ở bước này phải là một địa chỉ, không phải tên máy chủ. Khi lệnh từ chối cuối cùng chặn DNS, một quy tắc nêu tên máy chủ của nhà cung cấp không còn phân giải được nữa, và tunnel không bao giờ khởi động lại sau khi khởi động lại máy. Nếu nhà cung cấp thay đổi điểm cuối, hãy phân giải tên trước khi chính sách được áp dụng và làm mới quy tắc đó từ cùng một script.

Sao chép hình dạng đó trong FORWARD cho lưu lượng của máy khách, và đặt một quy tắc quản trị rõ ràng phía trên lệnh từ chối. Giữ quy tắc quản trị đó hẹp nhưng vẫn với tới được, và xác nhận nó bằng cách mở một phiên SSH thứ hai trước khi đóng phiên đầu tiên. Tự khóa mình ra ngoài trong lúc thay đổi kill switch đủ phổ biến để phải tính trước. Trên router chạy WireGuard, allowed-ips của peer quyết định thứ gì đi vào tunnel, trong khi các quy tắc này quyết định thứ gì được phép đi ra mà không có nó.

IPv6 cần cửa riêng

Mọi thứ ở trên là IPv4. Nếu LAN của bạn có IPv6 hoạt động và tunnel chỉ mang IPv4, mọi thiết bị được bao phủ vẫn có một đường trực tiếp ra internet mà các quy tắc mới của bạn không bao giờ thấy. Một laptop dual-stack sẽ vui vẻ ưu tiên nó, và kill switch chỉ trông hỏng với người đang kiểm tra bằng IPv4.

ip6tables -A FORWARD -i br-lan -j REJECT
ip6tables -A OUTPUT -o eth0 -j REJECT
ip6tables -A OUTPUT -o lo -j ACCEPT

Ở đây thứ tự cũng quan trọng: lệnh cho phép loopback phải đứng trước lệnh từ chối WAN, nếu không các dịch vụ cục bộ trên router bắt đầu hỏng theo những cách kỳ lạ. Nếu mạng hoàn toàn không dùng IPv6, tắt nó trên WAN và LAN thì đơn giản hơn và không để lại gì để quên.

Một số máy khách VPN chỉ cài một tuyến mặc định cho IPv4 và để nguyên tuyến mặc định IPv6 hiện có. Hãy kiểm tra bảng định tuyến sau khi tunnel kết nối thay vì cho rằng máy khách đã xử lý.

Chứng minh điều đó khi tunnel đã tắt

Dừng tunnel từ router và kiểm tra từ ba nơi theo thứ tự này:

# systemctl stop wg-quick@wg0
# ip route get 203.0.113.1
# curl -m 5 -sS http://example.com || echo blocked
# iptables -vnL OUTPUT | head
# ip6tables -vnL OUTPUT | head

Tra cứu tuyến cho bạn biết một gói tin sẽ đi đâu, và các bộ đếm cho bạn biết các quy tắc có bao giờ khớp hay không. Một quy tắc không có gói nào sau một lần kiểm tra thất bại thì không bảo vệ gì, và nguyên nhân thường gặp là tên giao diện khác với tên bạn đã nhập. Hãy kiểm tra rõ ràng lưu lượng do router tạo ra, vì một lần kiểm tra từ phía LAN không thể tác động tới OUTPUT.

Hãy quyết định chế độ hỏng trước khi bạn cần đến nó. Fail-closed giữ máy khách ngoại tuyến cho đến khi tunnel trở lại; fail-open khôi phục truy cập WAN thông thường và làm mất mục đích đối với lưu lượng mà bạn quan tâm. Một tuyến blackhole tới pool VPN với metric cao là lớp thứ hai hữu ích cho các thiết kế fail-closed, vì nó tồn tại khi tuyến tunnel biến mất thay vì rơi về tuyến mặc định.

Chỉ chấp nhận cấu hình khi một máy khách trong LAN, một yêu cầu do router tạo ra và một yêu cầu IPv6 đều thất bại khi tunnel tắt, và cả ba hoạt động lại khi tunnel bật.

Bài viết liên quan