Vì sao nc -uz không thể chứng minh rằng máy chủ OpenVPN đã sẵn sàng
Một phép thử UDP bằng netcat báo thành công kể cả khi không có gì lắng nghe, nên nó không thể chứng minh rằng máy chủ OpenVPN đã sẵn sàng. Hãy kiểm tra tiến trình, nhật ký, bộ lắng nghe và một ứng dụng khách thật.
Chạy nc -uz nhắm vào một OpenVPN máy chủ gần như không đo được gì, và hướng dẫn của OpenBSD nói điều đó trong phần lưu ý: các lần quét UDP ở chế độ ấy báo thành công bất kể có thứ gì đang lắng nghe hay không. Trạng thái thoát phản ánh việc gửi cục bộ, không phải trạng thái từ xa, nên một giám sát viên tin vào nó sẽ giữ một máy chủ đã chết được đánh dấu là khỏe mạnh chừng nào bảng tiến trình còn trông hợp lý. Việc thay thế bắt đầu bằng quyết định phép kiểm tra phải trả lời câu hỏi nào, vì tiến trình, bộ lắng nghe, xác thực và khả năng tiếp cận của ứng dụng là bốn quan sát khác nhau. Một phép thử nêu tên một trong số đó thì hữu ích; một phép thử ngụ ý cả bốn thì là gánh nặng.
Phép thử UDP có thể và không thể quan sát điều gì
nc -uz gửi một gói dữ liệu rồi thoát, và trạng thái nó trả về mô tả việc gửi cục bộ. Một cổng đã đóng có thể trả lời bằng ICMP port unreachable, nhưng hành vi được ghi nhận của chế độ quét này không biến điều đó thành thất bại, và một cổng bị lọc hoàn toàn không trả lời. Vì thế im lặng và thành công mang cùng một nghĩa với bên gọi.
Điều đó khiến phép thử trở thành phép thử ngăn xếp cục bộ, không phải máy chủ. Nó không xác lập rằng máy chủ có thể tiếp cận, cổng đã được gắn, tiến trình OpenVPN đang chạy hay một ứng dụng khách có thể xác thực. Phép thử kết nối TCP mạnh hơn vì bắt tay cho câu trả lời dứt khoát, nhưng chỉ khi việc triển khai thực sự lắng nghe trên TCP. Chuyển phép thử sang TCP trên cùng số đó sẽ kiểm tra một bộ lắng nghe có thể không tồn tại, và với máy chủ chỉ dùng UDP thì nó sẽ làm hỏng một dịch vụ khỏe mạnh.
Việc khớp phép thử với phương thức truyền đã cấu hình đến trước lòng tin vào bất kỳ kết quả nào. Một triển khai UDP cần một tín hiệu khác, không phải một giao thức khác.
Ba bên gọi, ba câu hỏi khác nhau
Sự sẵn sàng phụ thuộc vào người hỏi. Trình quản lý dịch vụ khởi động lại một tiến trình đã chết cần biết rằng phiên bản đã khởi động và đã gắn bộ lắng nghe. Bộ cân bằng tải cần biết rằng một ứng dụng khách đến ngay bây giờ sẽ được chấp nhận. Hệ thống giám sát cần biết rằng đường đi từ một mạng thật vẫn mang một phiên đến tài nguyên được phép.
Đây không phải cùng một phép kiểm tra, và một phép thử không thể bao trùm cả ba một cách trung thực. Chọn bên gọi trước, rồi chọn bằng chứng.
Xây dựng phép thử từ phiên bản hiện tại
OpenVPN ghi một dòng khởi động khi một phiên bản hoàn tất khởi tạo, và dòng đó là bằng chứng hữu ích về việc khởi động cục bộ. Đọc nó từ lần khởi động hiện tại chứ không phải từ cuối một tệp được nối thêm, vì một thành công của tuần trước đọc y hệt một thành công của một phút trước. Máy chủ cũng có thể hoàn tất khởi tạo trước khi bất kỳ ứng dụng khách nào từng kết nối, nên dòng đó không nói gì về xác thực.
Với một phép kiểm tra khởi động, hãy ghép trạng thái tiến trình với bằng chứng nhật ký hiện tại và một bộ lắng nghe khớp với phương thức truyền đã cấu hình. Phép kiểm tra phải thất bại khi tiến trình đang chạy nhưng chưa hoàn tất khởi tạo, nghĩa là truy vấn nhật ký phải giới hạn trong lần khởi động này và đơn vị này.
systemctl is-active openvpn@server
sudo journalctl -u openvpn@server -b --no-pager | grep "Initialization Sequence Completed"
ss -lunp | grep 1194
Ba đầu ra, ba khẳng định: đơn vị đang hoạt động, lần khởi động này đã tạo ra dòng khởi tạo, và có thứ gì đó giữ cổng UDP. Không có cái nào nói rằng một ứng dụng khách có thể kết nối. Hãy để chúng riêng rẽ trên trang trạng thái để một sự cố không sụp thành một chấm xanh duy nhất.
Cố ý làm hỏng nó và quan sát phép thử
Một phép thử chỉ đáng tin sau khi bạn đã thấy nó thất bại. Dừng máy chủ, chạy phép thử và xác nhận kết quả mong đợi. Sau đó khởi động lại và xác nhận rằng phép thử phục hồi mà không có thay đổi nào khác.
sudo systemctl stop openvpn@server
nc -uz 203.0.113.10 1194; echo "exit=$?"
ss -lunp | grep 1194
sudo systemctl start openvpn@server
ss -lunp | grep 1194
Đọc khối theo từng dòng. Lệnh netcat in ra exit=0 trong khi không có gì được gắn, và đó là toàn bộ vấn đề trong một dòng. Cái thứ nhất ss không in gì, việc khởi động lại thành công, và cái thứ hai ss lại hiển thị bộ lắng nghe. Nếu phép thử của bạn vượt qua với máy chủ đã dừng, nó đang đo ngăn xếp cục bộ và không gì khác.
Thất bại ngược lại cũng quan trọng. Một phép thử thất bại với máy chủ khỏe mạnh gây ra những lần khởi động lại chưa bao giờ cần thiết, và một vòng lặp khởi động lại tự nó là một sự cố. Hãy thử cả hai chiều trước khi nối phép thử vào bất cứ thứ gì có thể hành động dựa trên nó.
Dòng trạng thái nên nói gì
Ghi lại ranh giới mà mỗi phép kiểm tra bao phủ: tiến trình, bộ lắng nghe, xác thực hay ứng dụng. Một phép kiểm tra hiếm khi bao phủ nhiều hơn một, và một trang trạng thái ép chúng thành “up” sẽ giấu đi khác biệt quan trọng trong sự cố. Với đường mạng, hãy dùng một ứng dụng khách thật với danh tính riêng, để nó hoàn tất bắt tay và một thao tác được phép vô hại, rồi ngắt kết nối. Điều đó rèn luyện kênh điều khiển, chính sách xác thực và bộ lắng nghe trong một bước.
Giữ danh tính đó tách khỏi người dùng thật và cấp cho nó quyền tối thiểu mà phép kiểm tra cần. Một phép thử sẵn sàng với quyền truy cập rộng là một bề mặt tấn công mới được thêm vào cho tiện. Luân chuyển thông tin xác thực của nó như mọi tài khoản khác, vì một phép thử ngừng xác thực trông y hệt một máy chủ ngừng chấp nhận ứng dụng khách.
Nêu tên ranh giới trong văn bản cảnh báo, để người ứng cứu đầu tiên biết nên xem đơn vị, ổ cắm, chứng chỉ hay tuyến đường. Một phép thử không thể nói mình đã chứng minh điều gì sẽ được tin vì lý do sai, và đó chính là cách phép kiểm tra bằng netcat sống sót ngay từ đầu.