Một tuyến ra khỏi máy trạm này là proxy SOCKS, và OpenVPN phía sau nó báo hết thời gian kết nối mà không kèm thông tin hữu ích nào. Trình duyệt trên cùng máy chạy được qua proxy đó, thông tin đăng nhập đúng, và cổng có phản hồi. Ba thứ khác nhau đủ thường để kiểm tra trước: phiên bản SOCKS mà proxy nói, giao vận mà ứng dụng khách chọn, và nơi diễn ra phân giải tên. Xác nhận từng thứ trước khi kết luận tường lửa là thủ phạm.

Khớp phiên bản SOCKS trước tường lửa

OpenVPN cộng đồng nói SOCKS5 cho socks-proxy. Trỏ nó vào proxy chỉ cung cấp SOCKS4 thì kết nối TCP mở ra rồi đứng, vì ứng dụng khách chờ phản hồi cho lời chào mà đầu kia không bao giờ phân tích. Từ bên ngoài, việc đứng đó trông đúng như một cổng bị lọc, nên câu hỏi phiên bản đứng trước mọi quy tắc tường lửa. Một lần truy xuất biết SOCKS giải quyết điều này bằng một lệnh.

curl --socks5-hostname 127.0.0.1:9050 gw.lab.example

Một yêu cầu hoàn tất chứng minh hai điều cùng lúc: proxy chấp nhận yêu cầu SOCKS và nó đã phân giải tên. Không cần lược đồ URL, vì curl coi máy chủ trần là HTTP, đủ cho phép thử này.

Lần truy xuất đó cũng loại trừ lỗi mà nhật ký ứng dụng khách che giấu. Proxy có thể cho phép trình duyệt mà vẫn từ chối đích VPN, khi đó việc từ chối xảy ra ở CONNECT, trước mọi xác thực VPN. OpenVPN chỉ báo hết thời gian, nên chính câu trả lời của proxy là bằng chứng bạn cần.

Giao vận phải là TCP ở cả hai phía

SOCKS5 mang một luồng TCP ở đây, nên bản thân đường hầm cần proto tcp-client. Một hồ sơ vẫn đặt UDP sẽ không chạy qua đường này, vì ứng dụng khách không dùng chế độ liên kết UDP của giao thức. Lật hồ sơ là thay đổi thật chứ không phải hình thức: đầu xa phải lắng nghe TCP trên cùng cổng. Sau đó tải tin thành TCP trong TCP, nơi phân đoạn mất được gửi lại hai lần và nhịp độ giảm, điều mà phiên tương tác cảm nhận nhiều hơn hẳn các lần truyền lớn.

proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050

Chỉ thị này nhận máy chủ proxy, cổng tùy chọn và tệp thông tin đăng nhập tùy chọn. Đặt chúng ngay trong hồ sơ để một bản sao ở nơi khác cư xử giống hệt.

Gói cả chuỗi vào một container

Làm chuỗi trên máy chủ nghĩa là chiếm tuyến mặc định của nó và để bộ phân giải ở trạng thái sau này không ai giải thích được. Namespace hoặc container giới hạn nó thay vào đó, nên máy chủ giữ tuyến riêng trong khi chặng SOCKS và đường hầm sống cùng nhau. Không gì dựng lên bên trong mà thiếu thiết bị đường hầm, quyền cấu hình thiết bị đó và một proxy tiếp cận được. Một dịch vụ Compose có được điều đó với cap_add: NET_ADMIN và /dev/net/tun được gắn bind.

cap_add:
  - NET_ADMIN
devices:
  - /dev/net/tun:/dev/net/tun

Cặp này hẹp hơn việc chạy container ở chế độ privileged, và đó là toàn bộ quyền truy cập thiết bị cần thiết. Một ứng dụng khách Tor hoặc container proxy riêng có thể cung cấp bộ lắng nghe. Cả hai trường hợp hãy gắn nó vào loopback, và tiếp cận từ namespace qua máy chủ thay vì phơi proxy ra mạng.

Phân giải tên là nơi cách ly thất bại

Một đường hầm mang gói tin mà vẫn hỏi bộ phân giải của máy chủ thì chưa cách ly gì cả. Hai điều làm cách ly thành thật: namespace có bộ phân giải riêng, và các truy vấn của nó đi qua proxy hoặc đường hầm, không bao giờ qua giao diện vật lý. Dùng hai tên cho phép thử: một tên chỉ tồn tại sau đường hầm, và một tên công cộng đáng lẽ đi cùng đường đó.

docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example

Nếu tên phía xa phân giải được còn tên công cộng thì không, chuỗi là chọn lọc chứ không hỏng, và khác biệt cho bạn biết mỗi truy vấn đi đường nào. Nếu cả hai phân giải được từ máy chủ nhưng không cái nào phân giải được trong container, container vẫn đang mượn bộ phân giải của máy chủ. Ghi lại tệp bộ phân giải bạn tìm thấy, vì đó là thiết lập phải thay đổi.

Chứng minh từng chặng theo thứ tự

Danh sách ngắn. Một yêu cầu SOCKS5 có câu trả lời, đường hầm tới được bộ lắng nghe qua proxy, và các gói rời namespace mang địa chỉ mà phía xa mong đợi. Xác nhận từng cái một thay vì chồng thêm cấu hình. Khi ứng dụng khách báo đã kết nối mà không gì nhúc nhích, chỗ đứt gần như luôn ở điều thứ hai hoặc thứ ba.

curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example

Ghi lại tổ hợp đã chạy được: phiên bản SOCKS, giao vận, bộ phân giải và thiết lập namespace. Giải lại chuỗi này lần hai từ trí nhớ tốn hơn ghi chú. Giữ bốn dữ kiện đó trong phiếu chứ không trong luồng trò chuyện.

Một chuỗi báo đã kết nối mà không truyền gì thường đã hỏng ở chặng bạn chưa chứng minh. Kiểm tra chặng đó trước khi thêm lớp nữa.

Bài viết liên quan