WireGuard lồng nhau: chặng giữa không thể trả lời cổng của chính nó
Khi chặng giữa gửi mọi thứ vào một đường hầm, các phản hồi cho dịch vụ đến của nó đi ra theo đường sai. Một quy tắc cổng nguồn trên giao diện khắc phục điều đó.
Ba chặng WireGuard đi tới một mạng không có địa chỉ công cộng, rồi máy ở giữa ngừng trả lời trên cổng mà nó đáng lẽ phải lắng nghe. Đường hầm phía trước vẫn hoạt động, máy chủ ở xa vẫn phản hồi, và chỉ có máy chủ ở giữa là im lặng từ bên ngoài. Sự kết hợp đó gây bối rối chính vì nó do chính nó tạo ra: chặng giữa tuân theo bảng định tuyến của chính nó, và bảng đó gửi các phản hồi của nó đi sai hướng.
Một chuỗi hoạt động cho tới khi bạn nói chuyện với chiếc hộp ở giữa
Lấy một chuỗi minh họa: máy khách A tới máy chủ B qua UDP 500, và B đi tiếp tới máy chủ C qua UDP 500. C chỉ chấp nhận lưu lượng từ địa chỉ của đối tác duy nhất của nó, điều này khiến nó thành một chiếc lá và giữ cho hành vi của nó đơn giản. B không phải là lá, và mọi điều thú vị về sự cố này đều xảy ra ở đó.
Sự phân biệt này quan trọng vì vai trò lá và vai trò giữa kéo về hai hướng ngược nhau. Một lá có thể gửi mọi thứ vào một đường hầm mà không để lại hậu quả, vì không có gì khác phụ thuộc vào nó. Một chặng giữa đồng thời là điểm cuối cho máy khách và là máy khách về phía xa, và hai công việc đó muốn cách định tuyến khác nhau.
Vì sao phản hồi đi ra qua đường hầm
Trên B, giao diện hướng về C mang AllowedIPs = 0.0.0.0/0 cùng với tuyến mặc định tương ứng. Vì vậy mọi gói mà B tạo ra đều đi vào đường hầm đó, trừ khi có thứ gì cụ thể hơn được ưu tiên.
Một gói từ A gửi tới B đến và được chấp nhận, vì B là đích và việc chuyển phát cục bộ diễn ra trước. Phản hồi là một gói hoàn toàn mới được tạo cục bộ và hướng tới địa chỉ công cộng của A, và đích đó khớp với tuyến mặc định vào đường hầm. C nhận được nó, không sở hữu địa chỉ đó và loại bỏ nó.
Triệu chứng đọc như một vấn đề tường lửa hoặc khóa không khớp, và ở đây không cái nào đúng. Một bản bắt gói trên đường hầm về phía C cho thấy các phản hồi đang đi sai hướng. Chỉ một quan sát đó tiết kiệm nhiều thời gian hơn bất kỳ lượng đọc cấu hình nào, nên hãy ghi lại trước khi bắt đầu đổi khóa. Bất kỳ ai chưa thấy bản bắt gói sẽ cho rằng chính đường hầm bị hỏng.
Bản sửa hẹp: các quy tắc chính sách khớp với cổng nguồn
Các phản hồi từ ổ cắm lắng nghe của B đi ra với cổng nguồn 500. Một quy tắc chính sách có thể khớp với điều đó và đưa các gói ấy trở lại bảng thông thường:
ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101
Các quy tắc chính sách được tra theo thứ tự ưu tiên, và bảng chính nằm ở 32766, nên một quy tắc ở 100 được hỏi trước khi tuyến mặc định của đường hầm có tiếng nói. Thêm một mục cho mỗi cổng phải tiếp tục truy cập được từ bên ngoài và không gì hơn, để lưu lượng được chuyển tiếp tiếp tục dùng đường hầm mà nó được tạo cho.
Hãy biết giới hạn của mẹo này. Bộ chọn sport khớp với các gói được tạo cục bộ, điều này bao trùm chính xác trường hợp phản hồi và cố ý không bao trùm lưu lượng mà B chỉ chuyển tiếp cho người khác. Một dịch vụ được lưu trữ sau B vẫn cần phản hồi riêng, và giả vờ điều ngược lại tạo ra một bản sửa hoạt động cho dịch vụ thứ nhất và thất bại cho dịch vụ thứ hai.
Trao cho quy tắc một chủ sở hữu
Một quy tắc gõ ở dấu nhắc sẽ biến mất vào lần tiếp theo giao diện được dựng lại. Trong một thiết lập WireGuard, hãy đặt nó ở nơi giao diện được tạo và gỡ bỏ:
PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100
Nếu NetworkManager, một móc phân phối hoặc điểm vào của vùng chứa sở hữu giao diện, cặp lệnh thuộc về chủ sở hữu đó chứ không phải một tệp được sửa bằng tay. Hãy kiểm tra các quy tắc hiệu lực sau khi kết nối lại, không chỉ sau lần khởi động đầu tiên, vì lần khởi động đầu tiên là trường hợp luôn hoạt động.
So sánh các lựa chọn thay thế một cách trung thực
Quy tắc cổng nguồn là một trong bốn lối ra, và là lối hẹp nhất trong số đó. Nó có lợi thế là hoàn toàn không chạm vào chính sách đường hầm, đó là lý do nó thường sống sót qua các thay đổi sau này. Các bản sửa hẹp cũng thất bại ồn ào khi hết áp dụng, trong khi một ngoại lệ rộng tiếp tục hoạt động âm thầm rất lâu sau khi lý do biến mất. Sự khác biệt đó quan trọng hơn sự thanh lịch khi hai năm sau người khác sở hữu chiếc hộp.
| Approach | What it costs | Where it breaks |
|---|---|---|
| Source-port policy rule | One rule per exposed port | Anything B forwards rather than originates |
| Destination exception route | A route pinned to specific client addresses | Clients whose address changes |
| Stop full-tunnelling on B | Loses the catch-all path toward C | Designs that depend on it |
| Split into two tunnels | More interfaces and more policy | Nothing, at the cost of complexity |
Xác minh từ cả hai đầu sau khi đã chọn. Từ A, bắt đầu một kết nối tới cổng của B và giữ nó bận một lúc. Trên B, buộc nhân chứng minh đường phản hồi bằng thứ gì đó như ip route get <address-of-A> sport 500, và xác nhận rằng nó nêu giao diện WAN chứ không phải đường hầm. Sau đó, kiểm tra rằng thứ gì đó sau C vẫn trả lời qua chuỗi, điều này chứng minh ngoại lệ vẫn hẹp thay vì trở thành đường vòng. Cuối cùng, ghi các cổng vào ghi chú thiết kế, nếu không người vận hành tiếp theo sẽ phát hiện lại điều này trên một dịch vụ khác.