Hai bản ghi A, một địa chỉ, một daemon: dù người dùng gõ tên nào, gói tin đến vẫn giống hệt nhau, và tiến trình gắn với cổng 1194 không có gì để phân biệt hai cái đó. Đây không phải là cấu hình sai đang chờ sửa; đây là giới hạn của những gì một lần tra tên có thể diễn đạt. Bất cứ thứ gì chọn giữa hai thực thể OpenVPN đều phải là một giá trị mà máy khách đặt vào kết nối và phần đầu có thể đọc lại, còn máy khách OpenVPN tiêu chuẩn không đặt giá trị như vậy một cách công khai. Phần tiếp theo cho thấy điều đó để bạn ở đâu, và những cách bố trí nào thực sự tách luồng dữ liệu.

Bắt đầu từ những gì trình phân giải trả về

Máy khách hỏi vpn-a.example và nhận một địa chỉ; địa chỉ đó cộng một cổng là toàn bộ thứ nó kết nối tới. Tên được tiêu thụ cục bộ, trong lúc tra cứu, và không bao giờ trở thành một trường trên đường truyền, nên trình lắng nghe ở đầu bên kia không thể thấy nhãn nào đã được dùng. Trỏ vpn-a.example và vpn-b.example vào cùng một máy chủ và cả hai lần tra đều cho cùng đích, đó là lý do daemon hấp thụ cả hai kết nối vào một thực thể mà không ghi nhận khác biệt. Các hồ sơ dựa trên địa chỉ cũng hành xử y hệt như hồ sơ dựa trên tên, vì cùng lý do đó.

Điều này cũng đóng lại một họ giải pháp vòng tránh hấp dẫn: thêm bí danh, chọn chứng chỉ cho từng tên trên một socket, hoặc một quy tắc tường lửa gắn với tên được hỏi. Không cái nào có thể hành động trên thông tin đã bị bỏ đi trước khi gói tin đầu tiên rời máy khách. Nếu hai máy chủ phải tiếp tục tách biệt, sự tách biệt phải đi cùng chính kết nối, nghĩa là một địa chỉ, một cổng, hoặc một trường tải trọng mà giao thức định nghĩa.

Bộ chọn duy nhất được tính đi bên trong gói tin

HTTP xử lý điều này bằng tiêu đề Host, còn TLS bằng phần mở rộng tên máy chủ trong ClientHello, và nhờ vậy một địa chỉ phục vụ nhiều trang sau một trình lắng nghe. Cả hai đều hoạt động vì giao thức trên đường truyền mang một yêu cầu cho một dịch vụ cụ thể. Sự thật liên quan về OpenVPN là không trường nào trong hai trường đó hiện diện ở tầng mà một hộp trung gian kiểm tra.

Trong một cách bố trí tiêu chuẩn, bắt tay TLS bảo vệ kênh điều khiển diễn ra sau khi phiên bên ngoài được thiết lập và được mang bên trong nó, nên một trình lắng nghe chưa kết thúc phiên đó chỉ thấy một dòng chảy mờ đục. Nó vẫn có thể nói đây là OpenVPN, vì mã thao tác và cách đóng khung trong các byte mở đầu là nhận ra được, nhưng tên máy chủ, nếu có, nằm trong phần đã mã hóa. Một thiết kế mong đọc máy chủ ảo từ gói bên ngoài đang đọc một trường mà giao thức không bao giờ ghi ở đó. Điều đó đến từ cách đường hầm được dựng nên, không phải từ một lỗ hổng mà một cách khớp mẫu khéo hơn có thể bịt lại.

Nơi bộ tách giao thức dừng lại

Một bộ ghép kênh kiểu mà dự án sslh ghi lại sẽ lắng nghe trên một cổng, kiểm tra các byte mở đầu và chuyển kết nối cho backend nào nói giao thức mà nó nhận ra. Đó là giá trị thực khi một cổng phải phục vụ SSH, HTTPS và OpenVPN cùng lúc.

sslh giữ một đầu dò riêng cho mỗi giao thức, và đầu dò TLS của nó có thể lấy ra một tên máy chủ hoặc một giá trị ALPN từ một ClientHello thật. Nhận ra OpenVPN gốc là một cách phân loại khác với đọc phần mở rộng TLS, và hai thứ đó không kết hợp được, vì một máy khách không bao giờ gửi ClientHello tới socket lắng nghe sẽ để lại đầu dò mà không có gì để đọc. Vì thế một quy tắc khớp với OpenVPN trả lời “đây là máy khách OpenVPN” và không đi xa hơn. Hai backend OpenVPN sau quy tắc đó không thể phân biệt, phần đầu không có cơ sở để chọn, và mọi phiên đều hạ cánh ở cùng một chỗ. Ghép kênh chia sẻ một cổng giữa các dịch vụ khác nhau; nó không làm lưu trữ ảo bên trong một dịch vụ.

Những cách bố trí thực sự tách hai máy chủ

Cách tách trung thực rẻ nhất là một địa chỉ công cộng thứ hai, mỗi thực thể một cái, và các hồ sơ hiện có đã mang những gì cần thiết vì chúng trỏ đến các địa chỉ khác nhau. Tiếp theo là một cổng khác trên cùng địa chỉ, không tốn gì ngoài một con số trong mỗi hồ sơ. TCP và UDP giữ bảng cổng riêng, nên 1194/tcp và 1194/udp là hai socket không liên quan và mỗi loại một cái có thể cùng tồn tại trên một máy chủ; đó là tách theo tầng vận chuyển chứ không phải định tuyến theo tên, và thường bị nhầm với nó. Cả hai lựa chọn đều qua được rà soát tường lửa, vì quy tắc khớp với một thứ mà gói tin thực sự chứa.

Nếu ranh giới bạn cần chạy giữa các nhóm người dùng thay vì giữa hai cách hiện thực, một thực thể với các cấu hình máy khách khác nhau, tự xử lý chứng chỉ và một chính sách truy cập rõ ràng có thể bao phủ điều đó. Thứ mua được là chính sách bên trong một máy chủ, không phải cô lập giữa các máy chủ, và hai điều đó là những yêu cầu khác nhau. Sự cô lập phải trụ vững khi bị xâm phạm vẫn cần đến địa chỉ hoặc mép tường lửa.

Một bộ kết thúc TLS đặt trước OpenVPN có thể phơi ra một tên máy chủ thật cho phần đầu có năng lực, nhưng chỉ khi phía máy khách cũng được cấu hình cho tầng thêm đó. Các hồ sơ hiện có không có được hành vi đó chỉ nhờ được trỏ đến cùng địa chỉ.

Chứng minh bộ chọn trước khi xây

Gọi tên trường sẽ nhận diện một backend, rồi xác nhận rằng máy khách thực sự gửi nó; nếu câu trả lời là một địa chỉ thì kế hoạch đứng vững, còn nếu đó là một tên máy chủ bên trong một lần bắt tay không bao giờ đến được trình lắng nghe, thì không lượng công việc DNS nào cứu được. Ba lệnh giải quyết nhanh phía lắng nghe.

ss -lntup | grep -E ':443|:1194'
openssl s_client -connect vpn-a.example:443 -servername vpn-a.example </dev/null | head -n 20
journalctl -u openvpn-server@server-a -n 20 --no-pager

Dòng openssl chỉ cho chứng chỉ ở nơi có gì đó trên địa chỉ đó kết thúc TLS; với một trình lắng nghe OpenVPN gốc, nó sẽ khựng lại hoặc thất bại, và đó tự nó là câu trả lời về những gì tầng ngoài phơi ra. Dòng journal, đọc trên từng backend, cho thấy thực thể nào đã chấp nhận phiên. Nhật ký phần đầu ghi lại cái đã được phân loại và không bao giờ ghi cái đã định, nên backend vẫn là thẩm quyền duy nhất về nơi người dùng đã hạ cánh.

Kết thúc bằng hai hồ sơ nhằm đến các máy chủ khác nhau, nối chúng lần lượt và ghi lại nhật ký backend cho từng cái. Nếu cả hai phiên đều xuất hiện trong cùng một journal, bộ chọn bị thiếu chứ không phải bị cấu hình sai, và cách sửa là một địa chỉ hoặc một cổng mà máy khách có thể nhắm tới. Sửa quy tắc định tuyến sẽ không giúp gì, vì quy tắc chưa bao giờ được giao thứ gì để định tuyến. Khi sự tách biệt là thật, hãy viết nó bên cạnh các hồ sơ để người tiếp theo không thêm một bí danh thứ hai và mong nó làm nốt công việc.

Bài viết liên quan