Khi khởi động, một unit socket gắn địa chỉ VPN cố định có thể thất bại trước khi đường hầm gán địa chỉ đó, và dịch vụ phía sau sẽ không bao giờ khởi động. Hai công tắc trông như cách sửa và giải quyết hai nửa khác nhau của vấn đề đó. FreeBind cho phép systemd tạo trình lắng nghe khi địa chỉ vẫn chưa có. After= chỉ sắp xếp các tác vụ, nên nó thay đổi thời điểm mọi thứ khởi động mà không làm địa chỉ đến sớm hơn.

Hai vấn đề khác nhau, hai công tắc khác nhau

Vấn đề thứ nhất là lỗi gắn kết: kernel từ chối lắng nghe trên một địa chỉ mà máy chủ không sở hữu, nên unit socket thất bại ngay lập tức và dịch vụ không bao giờ được kích hoạt. Vấn đề thứ hai là lỗi sẵn sàng: địa chỉ rốt cuộc vẫn tồn tại, nhưng thứ gì đó cố dùng nó trước khi đường hầm mang lưu lượng. FreeBind xử lý vấn đề thứ nhất và không làm gì cho vấn đề thứ hai. Các chỉ thị thứ tự không xử lý trực tiếp cả hai, vì chúng chỉ quyết định cái gì khởi động theo thứ tự nào. Gọi tên đúng lỗi bạn thực sự có chính là toàn bộ quyết định.

Xác nhận bạn có lỗi nào trong hai lỗi từ nhật ký, không phải từ mô tả dịch vụ. Lỗi gắn kết nêu một địa chỉ và báo rằng không thể gán nó. Lỗi sẵn sàng thường xuất hiện muộn hơn, dưới dạng hết thời gian hoặc kết nối bị từ chối nhìn từ phía bên kia, trong khi nhật ký có một unit socket hoàn toàn khỏe mạnh.

FreeBind: trình lắng nghe tồn tại trước địa chỉ

FreeBind bảo kernel cho phép gắn vào một địa chỉ không phải cục bộ, để systemd có thể tạo socket lắng nghe khi khởi động và trao nó cho ứng dụng mỗi khi ứng dụng khởi động. Đó là ý nghĩa của kích hoạt bằng socket, và là lý do socket có thể sống lâu hơn dịch vụ phía sau nó.

[Socket]
ListenStream=
ListenStream=10.8.0.1:8443
FreeBind=yes

Phép gán rỗng xóa các mục lắng nghe kế thừa từ unit của nhà cung cấp trước khi thêm mục mới, điều này ngăn một trình lắng nghe wildcard còn sót lại trả lời trên mọi giao diện. Thay địa chỉ và cổng bằng của bạn và xác minh unit hiệu lực, không chỉ tệp drop-in. Dùng một drop-in dưới tên unit thay vì sửa tệp gói tại chỗ, vì bản cập nhật gói tiếp theo sẽ ghi đè chỉnh sửa và không để lại dấu vết nào của ý định. Sau đó áp dụng nó qua quy trình nạp lại và khởi động lại mà unit socket mong đợi.

Tài liệu tham chiếu socket của systemd ghi lại hành vi IPv4 và IPv6 đằng sau tùy chọn này, và chi tiết quan trọng là nó áp dụng cho việc gắn kết chứ không phải định tuyến. Không có gì trong đó gán địa chỉ hay khởi động VPN. FreeBind là quyền được cấp cho trình lắng nghe, không phải thứ thay thế giao diện.

After= và Wants=: thứ tự không phải sự sẵn sàng

Thứ tự và yêu cầu là hai trục riêng, và trộn lẫn chúng tạo ra những unit khởi động đúng thứ tự mà vẫn thất bại. After=vpn-client.service chỉ có nghĩa là nếu cả hai tác vụ được khởi động, cái này chờ cái kia được khởi động. Nó không kéo VPN vào và không chờ VPN kết nối xong.

Các chỉ thị yêu cầu như Wants= và Requires= xử lý việc kích hoạt, và chúng khác nhau ở điều gì xảy ra khi phụ thuộc thất bại: một cái tiếp tục, cái kia dừng lại. Không cái nào biết đường hầm đã kết nối nghĩa là gì. Một tiến trình VPN có thể đang hoạt động mà không có địa chỉ được gán, hoặc có địa chỉ được gán mà không có tuyến đến đối tác, và cả hai trạng thái đều thỏa mãn phụ thuộc. Nếu ứng dụng cần địa chỉ tồn tại, hãy mô hình hóa điều kiện đó một cách rõ ràng thay vì coi việc tiến trình khởi động là bằng chứng của sự sẵn sàng.

Kiểm tra unit thực sự khai báo gì bằng systemctl cat và systemctl show -p After -p Wants -p Requires. Các drop-in từ ba thư mục khác nhau có thể thêm những chỉ thị bạn chưa từng viết, và systemd chỉ đọc unit hiệu lực.

Điều network-online.target không làm

Một unit được sắp sau network-online.target chờ trình quản lý mạng tuyên bố mạng dùng được, đó là một điểm đồng bộ khi khởi động chứ không phải điều kiện liên tục. Nó không nói gì về việc một đường hầm cụ thể có hoạt động hay không, và nó sẽ không kích hoạt lại khi VPN kết nối lại vào giữa buổi chiều. Coi nó là giám sát kết nối lại là cách đọc sai phổ biến nhất của mục tiêu đó.

Dự án systemd ghi lại sự khác biệt đó một cách trực tiếp, và hệ quả thực tế là bất cứ thứ gì cần địa chỉ đường hầm đều phải tự sở hữu phụ thuộc. Một unit chờ network-online rồi gắn địa chỉ đường hầm chỉ đúng khi đường hầm tình cờ lên trước, và đó là sự trùng hợp chứ không phải thiết kế.

Kiểm tra vòng đời bạn thực sự đã chọn

Kiểm tra khởi động sạch, một yêu cầu sau khi địa chỉ xuất hiện, và hành vi sau khi VPN sập rồi trở lại. Ba trường hợp đó tách một trình lắng nghe hoạt động khỏi một dịch vụ hoạt động.

systemd-analyze verify myapp.socket
systemctl cat myapp.socket
ss -ltn "sport = :8443"

Lệnh đầu tiên bắt lỗi tệp unit trước khi khởi động lại, lệnh thứ hai hiển thị unit đã hợp nhất, và lệnh thứ ba chứng minh trình lắng nghe có tồn tại và trên địa chỉ nào. Một trình lắng nghe trên địa chỉ wildcard ở nơi bạn mong đợi địa chỉ đường hầm chính là phần dư mà ListenStream rỗng lẽ ra phải xóa. Lặp lại lệnh thứ ba sau khi VPN kết nối lại để xem địa chỉ có dịch chuyển không.

Chọn vòng đời một cách có chủ đích: hoặc một trình lắng nghe được gắn tự do chờ một địa chỉ ổn định trở lại, hoặc một dịch vụ dừng cùng đường hầm và khởi động lại khi phục hồi. Đó là những thiết kế khác nhau và chúng thất bại theo những cách khác nhau. Sau đó giữ chính sách truy cập gắn với các nguồn và đường dẫn bạn dự định, vì việc gắn địa chỉ đích không đòi hỏi các gói được chấp nhận phải đến qua một giao diện đáng tin cậy.

Bài viết liên quan