Hai cổng ra VPN khỏe mạnh, một lần tải lên dài đã chạy, và yêu cầu rằng kết nối tiếp theo dùng đường hầm kia. Có hai cách đáp ứng điều đó, và chỉ một cách an toàn trên một cổng kết nối đang hoạt động. Đổi tuyến mặc định di chuyển mọi gói, kể cả những gói thuộc lần tải lên. Một lần xả có kế hoạch thay đổi lựa chọn cho các kết nối mới và để các luồng được theo dõi ở trên đường mà chúng đã bắt đầu.

Hai cách để đổi cổng ra

Đổi tuyến là một lệnh và có thể hoàn tác trong vài giây, đó là lý do nó được dùng khi có sự cố. Nó cũng không phân biệt: các gói của lần tải lên hiện có đột nhiên đi ra qua một đường hầm khác, với một địa chỉ nguồn công khai khác và trạng thái dịch riêng.

Nếu đầu xa theo dõi luồng theo địa chỉ nguồn, lần tải lên có thể chỉ đơn giản là không còn được nhận ra. Việc xả tránh điều đó bằng cách ra quyết định một lần cho mỗi kết nối và lưu lại, nhờ vậy lần tải lên cũ giữ cổng ra của nó cho đến khi xong. Đó là toàn bộ giá trị của bài tập: đầu xa không thấy thay đổi nào mà nó phải diễn giải. Nó tiếp tục nhận các gói khớp với kết nối mà nó đã biết.

Cái giá là sự phức tạp: hai bảng định tuyến, một bộ phân loại chạy ở đúng điểm móc, và các dấu phải được phối hợp với mọi thứ khác trên máy dùng chúng.

Cho mỗi cổng ra bảng riêng của nó

Dành một bảng định tuyến cho mỗi cổng ra và các giá trị dấu hoặc bit riêng cho hai lựa chọn. Mỗi bảng cần các tuyến phù hợp với vai trò của nó, không chỉ một cái tên, và cần một kết quả thất bại có chủ đích cho trường hợp thiếu. Một bảng trống âm thầm rơi vào bảng chính — đó là cách lưu lượng đi ra qua một cổng mà không ai chọn.

ip rule add fwmark 0x10/0x10 table 101
ip rule add fwmark 0x20/0x20 table 102
ip route add default via 192.0.2.1 dev wg-a table 101
ip route add default via 198.51.100.1 dev wg-b table 102

Thêm một tuyến blackhole ở cuối mỗi bảng để một lần tra cứu không khớp sẽ thất bại ồn ào thay vì trốn sang một mặc định bạn không chọn.

Chọn một lần, ở gói đầu tiên

Phân loại sau khi đã có theo dõi kết nối và trước lần tra tuyến quan trọng. Với một kết nối LAN mới, chưa phân loại, hãy chọn cổng ra và lưu vào trạng thái kết nối. Ở các gói sau, khôi phục giá trị đã lưu vào dấu gói mà định tuyến theo chính sách đọc.

Phần tinh tế là ý nghĩa của từ mới. Conntrack vẫn có thể báo NEW cho các gói sớm và truyền lại trước khi thấy phản hồi, nên một bộ phân loại chỉ dựa vào trạng thái đó có thể ghi đè lựa chọn đã thực hiện. Trước khi gán, hãy kiểm tra rằng chưa lưu cổng ra nào cho kết nối.

nftables giữ dấu gói và dấu kết nối tách biệt, và hướng dẫn về siêu dữ liệu ghi lại việc sao chép tường minh giữa chúng. Một dấu kết nối không tự nó trở thành dấu gói mà quy tắc của bạn khớp, và đó là lý do phổ biến nhất khiến một bộ phân loại được viết cẩn thận không có tác dụng.

Giới hạn việc khôi phục ở hướng và lưu lượng bạn định. Áp một dấu cổng ra internet lên các gói quay về có thể gửi phản hồi về phía cổng ra thay vì LAN, và triệu chứng là một kết nối một chiều trông như sự cố tường lửa. Hãy đọc đường phản hồi trước khi chạm vào một quy tắc tường lửa, vì gói đang được định tuyến, chỉ là không quay về người gửi.

Bốn giai đoạn của một lần xả

  1. Chuẩn bị B mà không chạm vào A: định tuyến, chuyển tiếp, ủy quyền, NAT và đường về. Cài bảng và chính sách chọn của nó thông qua chủ sở hữu cấu hình hiện có của cổng.

  2. Chuyển bộ phân loại để các kết nối mới, chưa phân loại chọn B, giữ nguyên các lựa chọn đã lưu. Một giao dịch nftables nguyên tử tránh khoảng thời gian phải xóa trạng thái cũ.

  3. Để A chạy trong khi các luồng của nó kết thúc. Giao diện, bảng, cổng ra xa và các ánh xạ NAT của nó vẫn là một phần của các luồng đó, và việc sửa một quy tắc NAT không dựng lại các ràng buộc đã tồn tại.

  4. Cho A nghỉ khi điều kiện xả được thỏa, được đánh giá từ trạng thái kết nối và hành vi ứng dụng chứ không phải một khoảng lặng.

Điều một lần xả không thể hứa

Một yêu cầu của trình duyệt không phải là kết nối vận chuyển mới; việc gộp vẫn gửi yêu cầu qua kết nối cũ. Ngược lại, một luồng UDP có thể già đi khỏi conntrack và một gói sau đó được phân loại lại. Việc xả đi theo các luồng được theo dõi, không theo ý niệm của ứng dụng về một phiên.

Nếu A hỏng trước khi các luồng của nó kết thúc, dấu đã lưu không cứu chúng. Chúng kết nối lại qua B, hoặc không kết nối lại nữa. Một lần xả có kế hoạch mua sự liên tục khi đường ban đầu khỏe mạnh; nó không phải là sao chép trạng thái giữa các cổng ra độc lập.

Xác minh cả hai nửa

Bắt đầu một kết nối được phép dài hạn trước thay đổi và một kết nối thật sự mới sau đó. Xác nhận mỗi kết nối dùng đường hầm nào và đầu xa thấy địa chỉ nguồn công khai nào, rồi kiểm tra rằng lưu lượng quay về có trở lại.

Đừng xóa bảng conntrack để lựa chọn mới xuất hiện. Điều đó phá hủy đúng trạng thái mà việc xả phải giữ gìn, và biến một cuộc di chuyển có kiểm soát thành sự cố với một bài kiểm tra trông sạch sẽ.

Bài viết liên quan