Máy chủ duyệt web qua đường hầm còn container bên cạnh thì không tới được gì. Xuất bản một cổng từ container chạy ứng dụng VPN riêng còn tệ hơn: yêu cầu đến mà phản hồi không bao giờ ra. Cả hai đều là quyết định định tuyến trên máy chủ, và Docker chỉ là người đưa tin.

Ba câu hỏi xác định bạn đang gặp trường hợp nào trong hai trường hợp, và mất khoảng một phút.

Hai sự cố trông giống nhau

Thứ nhất là vấn đề đường quay về. Cổng được xuất bản được dịch vào container, yêu cầu đến, và phản hồi được định tuyến theo tuyến mặc định của máy chủ, tuyến mà ứng dụng khách OpenVPN đã trỏ vào tun0. Phản hồi đi ra từ một địa chỉ mà đầu xa không mong đợi, và bị loại bỏ. Thứ hai là xung đột tiền tố: cầu mặc định của Docker sở hữu 172.17.0.0/16 và một đường hầm doanh nghiệp đẩy đúng dải đó vào.

Một cái được sửa bằng bảng định tuyến, cái kia bằng cách đánh số lại một cầu. Chỉnh sửa trước khi biết cái nào là cái nào chính là cách làm hỏng một container đang chạy tốt.

Quyết định bằng ba câu hỏi

Câu hỏi một: sự cố có biến mất khi bạn dừng VPN không? Nếu mọi thứ chạy được khi đường hầm tắt, hãy nghi đường quay về. Câu hỏi hai: ip route show table all có liệt kê cùng một tiền tố hai lần, một lần trên cầu và một lần trên tun0 không? Đó chính là xung đột. Câu hỏi ba: địa chỉ bị ảnh hưởng là container, khách NAT hay khách cầu nối?

Câu hỏi thứ ba quan trọng vì mỗi loại có cách khắc phục đúng khác nhau, và áp cách khắc phục của container cho một khách libvirt sẽ làm mất cả buổi tối.

ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'

Đường quay về: một bảng cho một địa chỉ nguồn

Khi lưu lượng của container phải đi ra qua giao diện vật lý trong khi bản thân máy chủ dùng đường hầm, định tuyến dựa trên nguồn là thay đổi nhỏ nhất. Thêm một quy tắc khớp với địa chỉ của container và gửi nó vào một bảng riêng. Không gì khác trên máy chủ phải di chuyển.

ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10

Mọi gói mà nguồn là địa chỉ đó trước tiên tra bảng 10, và bảng 10 gửi nó tới cổng của cầu thay vì đường hầm.

Xác nhận bằng ip route get 1.1.1.1 from 172.22.0.3. Câu trả lời phải nêu giao diện của cầu, không phải tun0. Các quy tắc thêm theo cách này sẽ mất khi khởi động lại, nên hãy đặt chúng trong unit hoặc móc mạng sở hữu container.

Cùng mẫu đó cũng đúng cho container WireGuard, nơi đường phản hồi cũng cần một quy tắc rõ ràng.

Xung đột tiền tố: đánh số lại cầu

Một bảng định tuyến gửi một tiền tố tới một nơi. Nếu VPN đẩy 172.17.0.0/16 vào trong khi cầu của Docker đã ở đó, metric thấp hơn sẽ thắng: Docker cài tuyến kết nối của nó ở metric 0, và tuyến bị đẩy vào đến với 50. Khi đó đường hầm trông như hỏng trong khi Docker vẫn chạy, hoặc ngược lại, tùy thứ tự cài đặt. Hãy đánh số lại cầu thay vì đánh nhau với metric.

{
  "bip": "10.200.0.1/24",
  "default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}

Khởi động lại Docker sau thay đổi và tạo lại các mạng được dựng bằng pool cũ. Đổi metric chỉ chuyển xung đột sang lần khởi động tiếp theo.

Máy ảo lại cần một câu trả lời khác

Một khách libvirt trên mạng NAT mặc định thừa hưởng định tuyến của máy chủ và ngừng ra ngoài khi đường hầm của máy chủ giữ tuyến mặc định. Chuyển khách sang thiết bị cầu nối hoặc macvtap cho nó đường riêng trên mạng vật lý. Trong virt-manager, thêm phần cứng, chọn Network, đặt nguồn là thiết bị máy chủ macvtap, giữ virtio làm kiểu, rồi tắt giao diện NAT cũ.

Khách macvtap thường không tới được chính máy chủ của nó. Đó là hành vi mong đợi chứ không phải lỗi, và nó thuộc về ghi chú bạn để lại.

Với khách chỉ cần LAN của máy chủ, ứng dụng khách của nhà cung cấp có thể có công tắc còn thiếu: với Mullvad, mullvad lan set allow khôi phục khả năng truy cập cục bộ mà không chạm vào libvirt. Và khi một container chỉ được truy cập qua đường hầm, hãy buộc cổng đã xuất bản vào địa chỉ đường hầm, -p 10.8.0.5:8080:8080, thay vì xuất bản trên mọi địa chỉ.

Bài viết liên quan