NAT quyết định địa chỉ nguồn nào mà máy chủ VPN của bạn thực sự thấy
Địa chỉ laptop của bạn không bao giờ đến được máy chủ VPN. NAT viết lại nó ở chặng cuối, và IP của đường hầm được cấp sau đó. Cách so sánh hai đầu.
Bạn hình dung máy chủ VPN đọc địa chỉ laptop của bạn từ gói tin và ghi nó vào nhật ký. Thứ nó đọc là những gì chặng NAT cuối cùng đặt vào tiêu đề bên ngoài, và trên một điện thoại dùng làm điểm phát sóng thì đó thường là địa chỉ được chia sẻ với hàng trăm thuê bao khác. Địa chỉ của chính máy bạn 192.168.x.x không bao giờ đi qua internet trong tiêu đề đó, và địa chỉ đường hầm do máy chủ cấp sau khi kết nối đã được thiết lập. Vì vậy khi nhật ký máy chủ và ip addr trên laptop không khớp nhau, không cái nào sai; chúng mô tả các lớp khác nhau của cùng một phiên.
Ba địa chỉ, và chỉ một nằm trong nhật ký
Sự nhầm lẫn đến từ việc gộp ba địa chỉ thành một. Mỗi địa chỉ có chủ sở hữu khác nhau, sống trong một tiêu đề khác nhau và đến máy chủ bằng một đường khác nhau.
| Address | Who assigns it | Where it sits | Visible to the VPN server |
|---|---|---|---|
Device address, e.g. 192.168.1.24 | Your router via DHCP | Outer header, before translation | No, rewritten in place |
| Translated address and port | Router, ISP CGNAT, or both | Outer header, after translation | Yes, this is the tuple it logs |
Tunnel address, e.g. 10.8.0.6 | The VPN server itself | Inner header, after decapsulation | Yes, but it chose it |
Chỉ hàng giữa là chưa biết tại thời điểm kết nối. Máy chủ ghi nó vào bảng ngang hàng, tệp trạng thái hoặc nhật ký luồng tùy theo daemon: WireGuard gọi nó là điểm cuối, tệp trạng thái của OpenVPN gắn nhãn Real Address, và strongSwan báo cáo nó là máy chủ từ xa của IKE_SA. Giá trị đó được làm mới mỗi khi có gói tin đến từ một nguồn khác, nên nó thay đổi mà không ai khởi động lại thứ gì.
Hàng dưới cùng là thứ mọi người đọc nhầm thành một tuyên bố danh tính. Nó đánh dấu một vị trí trong cấu hình máy chủ, không phải một con người, vì máy chủ đã chọn nó từ nhóm của chính mình. Hai người dùng có thể nhận cùng một địa chỉ đường hầm vào những ngày khác nhau, và một người có thể giữ hai địa chỉ từ hai thiết bị.
Tại sao bộ phận tuple được ghi lại thay đổi trong khi đường hầm vẫn hoạt động
Dịch địa chỉ là một bảng có bộ đếm thời gian, không phải một ràng buộc vĩnh viễn. Router gia đình giữ ánh xạ UDP thêm một lúc sau gói cuối, cổng của nhà mạng tái sử dụng cổng theo lịch riêng, và một điện thoại chuyển từ Wi-Fi sang LTE quay lại với nguồn hoàn toàn khác. Ở đây các giá trị mặc định của conntrack trên Linux là một thước đo hữu ích: nf_conntrack_udp_timeout là 30 giây và biến thể phát trực tuyến là 120, nên một đường hầm im lặng có thể mất ánh xạ rất lâu trước khi người dùng nhận ra.
Đường hầm tồn tại vì giao thức xác thực ngang hàng, không phải địa chỉ. WireGuard không trạng thái sau bắt tay, nên mọi gói tin đã xác thực cập nhật điểm cuối đã lưu và việc gắn lại được chữa lành ở gói tiếp theo; đó là lý do tồn tại persistent-keepalive = 25, để giữ ánh xạ ấm trong lúc rảnh. Tham số --float của OpenVPN làm việc tương tự và cho phép một client đã xác thực tiếp tục từ địa chỉ và cổng mới. Trên các bản dựng 2.4 và 2.5 nơi float bị tắt mặc định, việc gắn lại đặt lại phiên và client kết nối lại.
IPsec đạt được điều đó với nhiều bộ phận chuyển động hơn. IKEv2 nhận ra việc dịch bằng cách so sánh hàm băm nguồn và đích trong tải trọng phát hiện NAT, chuyển sang đóng gói UDP 4500 và theo dõi keepalive đến tuple mới. Khi keepalive bị chặn, SA vẫn hoạt động trên giấy trong khi lưu lượng một chiều lặng lẽ dừng.
Máy chủ có thể quy kết điều gì, và không thể điều gì
Huyền thoại đáng bị giết là việc dịch địa chỉ che giấu bạn khỏi nhà mạng. Nó đổi nhãn, không đổi quan sát. Một cổng sau NAT của nhà mạng thấy không gian 100.64.0.0/10 hoặc một địa chỉ công cộng được nhiều thuê bao chia sẻ, và vẫn có thể gắn luồng với chủ thể chứng chỉ, khóa công khai WireGuard, địa chỉ đường hầm được cấp, bộ đếm byte và một cửa sổ thời gian. Không điều nào trong đó cần địa chỉ LAN của bạn.
Các giới hạn cũng đi theo chiều ngược lại. Một địa chỉ chia sẻ trong nhật ký chỉ vào cổng, không chỉ vào hộ gia đình; hai phiên từ cùng địa chỉ đã dịch trên các cổng khác nhau là hai thiết bị khác nhau; cùng một địa chỉ trong hai ngày khác nhau có thể là hai thuê bao không liên quan nếu cổng đã được tái sử dụng. Máy chủ chỉ ghi khóa ngang hàng không thể ánh xạ chúng tới khách hàng nếu không có cơ sở dữ liệu tài khoản, và máy chủ chỉ ghi địa chỉ không thể phân biệt laptop với điện thoại sau cùng một router.
So sánh hai đầu thay vì đoán
Để xác định điều gì đã xảy ra, hãy bắt cùng một kết nối ở cả hai đầu tại cùng một thời điểm và so sánh tuple, không phải địa chỉ. Trên client, trước mọi phép dịch:
ss -uapn 'dport = :51820'
ip -4 route get 203.0.113.10
wg show wg0 endpoints
Sau đó đọc mục dịch trên router hoặc cổng CGNAT, và những gì cuối cùng đến máy chủ:
conntrack -L -p udp --dport 51820
tcpdump -ni eth0 udp port 51820
Ba mẫu giải thích hầu hết các khác biệt. Cổng nguồn trên máy chủ khác cổng cục bộ trong khi đích khớp: dịch cổng thông thường. Địa chỉ nguồn trên máy chủ thuộc một khối ISP không phải của bạn: ít nhất một lớp NAT bổ sung. Gói tin dừng sau một khoảng rảnh và tiếp tục với cổng mới: ánh xạ đã hết hạn, không phải lỗi định tuyến. Nếu dấu thời gian cách nhau hơn một hoặc hai giây, bạn đang so sánh hai lần thử khác nhau.
Nơi sự khác biệt phá hỏng mọi thứ
Các gián đoạn trông như lỗi máy chủ thường bắt đầu từ đây. Một quy tắc truy cập ghim vào địa chỉ nhà của bạn thất bại sau khi hợp đồng thuê của ISP thay đổi. Một quy tắc fail2ban khớp với địa chỉ đã dịch sẽ chặn mọi thuê bao sau cổng đó cùng lúc. Một peer site-to-site với địa chỉ từ xa cố định ngừng gia hạn khóa sau khi liên kết di động thay đổi. Giao thức đường hầm vẫn ổn; giả định về tuple bên ngoài thì không.
Cùng sự nhầm lẫn xuất hiện ở phía máy chủ. Nếu bản thân hộp VPN nằm sau NAT, bạn cần chuyển tiếp cổng và một đường chuyển tiếp hoạt động; hướng dẫn chuyển tiếp của strongSwan bao trùm trường hợp đó cho IPsec. Một máy chủ chỉ truy cập được qua địa chỉ riêng không bao giờ thấy tuple đã dịch mà client của nó trình bày, và đó là vấn đề khác với việc client bị dịch.
Thực hiện bốn kiểm tra này theo thứ tự và dừng ở cái đầu tiên thất bại:
- Bắt ở cả hai đầu cùng lúc; xác nhận cổng nguồn, cổng đích và dấu thời gian khớp nhau.
- Đọc danh sách ngang hàng của máy chủ cho địa chỉ nó đang giữ, không phải địa chỉ bạn mong đợi.
- Kiểm tra bảng conntrack hoặc NAT cho mục và thời gian sống còn lại của nó.
- Xác nhận địa chỉ giao diện đường hầm trên client khớp với địa chỉ máy chủ đã cấp, không phải địa chỉ LAN.
Nếu cả hai bản bắt đều đồng ý về tuple và đường hầm vẫn thất bại, thì việc dịch không phải vấn đề của bạn; hãy chuyển sang bắt tay và bảng định tuyến bên trong đường hầm.