Sửa resolv.conf không khắc phục được DNS sau khi VPN ngắt kết nối
Một resolver của đường hầm đã chết ở đầu danh sách khiến mỗi lần tra cứu mất một khoảng chờ. Hãy kiểm tra ai sở hữu tệp, đặt lại trạng thái liên kết và ngừng chỉnh sửa phần đầu ra được tạo.
Bạn ngắt VPN, ping 1.1.1.1 vẫn trả lời, và mọi lần tra cứu tên đều treo trước khi trang cuối cùng bỏ cuộc. Sau đó cat /etc/resolv.conf hiển thị một máy chủ tên từng tồn tại chỉ bên trong đường hầm, thường là mục đầu tiên trong danh sách. Xóa dòng đó có vẻ khắc phục được khoảng mười phút, cho đến khi một lần tạm ngủ, một lần chuyển vùng Wi-Fi hay một lần khởi động lại đưa nó trở lại. Tệp bạn đã sửa không phải là thiết lập; nó là bản trình bày trạng thái liên kết do một thành phần khác sở hữu.
Vì sao một mục cũ khiến mỗi lần tra cứu mất vài giây
Resolver của glibc duyệt danh sách máy chủ tên theo thứ tự và chờ hết một khoảng thời gian chờ trước khi thử máy chủ tiếp theo, và resolv.conf(5) giới hạn danh sách đó ở ba mục. Đặt một resolver phía đường hầm như 10.8.0.1 lên đầu sau khi đường hầm biến mất, và mọi lần tra cứu đều trả giá bằng khoảng chờ trước khi chuyển sang máy chủ trả lời được. Đó là lý do triệu chứng trông như kết nối chết chứ không phải lỗi DNS: trình duyệt bị chặn, hết thời gian và đôi khi phục vụ một địa chỉ trong bộ nhớ đệm mà sau này trở nên cũ.
Điều này cũng giải thích vì sao lời phàn nàn đến dưới dạng «internet hỏng rồi». Ping tới một địa chỉ IP chứng minh liên kết vẫn tốt, khiến lỗi trông như của ứng dụng. Danh sách resolver là thứ đầu tiên cần đọc và là thứ cuối cùng cần sửa.
Lầm tưởng: resolv.conf là một tệp cấu hình
Hãy hỏi đường dẫn đó thực sự là gì trước khi thay đổi nó:
ls -l /etc/resolv.conf
readlink -f /etc/resolv.conf
Trên một máy chủ systemd-resolved, nó là một liên kết tượng trưng tới tệp stub trỏ tới 127.0.0.53, và các máy chủ thật sống trong trạng thái theo từng liên kết mà resolvectl in ra. Trên một máy chủ NetworkManager, nó có thể là tệp do NetworkManager ghi từ kết nối đang hoạt động. Với một số ứng dụng khách của nhà cung cấp, nó là tệp thường bị ghi đè tại chỗ khi kết nối và, nếu bạn không may, không bao giờ được khôi phục khi ngắt kết nối. Đó là ba chủ sở hữu khác nhau, và việc sửa hai cái đầu bằng tay hoặc không làm gì hoặc chỉ kéo dài đến sự kiện mạng tiếp theo.
resolvectl status là góc nhìn nói sự thật: máy chủ DNS theo từng liên kết, miền định tuyến và liên kết đường hầm còn tồn tại hay không. resolvectl query example.com đi xa hơn và cho biết giao diện nào đã trả lời. Hãy dùng cả hai trước khi chạm vào tệp, và nhớ rằng trình duyệt có DNS bảo mật riêng sẽ bỏ qua tất cả những điều này.
Tìm chủ sở hữu trước khi sửa bất cứ thứ gì
Thông thường ba thành phần cạnh tranh cho cùng một thiết lập: systemd-resolved, NetworkManager và thứ mà ứng dụng khách VPN đã cài. Trước tiên hãy xác định thành phần còn sống:
systemctl is-active systemd-resolved
nmcli connection show --active
ps aux | grep -E "openvpn|wg-quick|vpn"
Nếu resolved đang hoạt động và liên kết tượng trưng trỏ tới stub của nó, tệp toàn cục là đầu ra được tạo và việc sửa của bạn chỉ là hình thức. Nếu NetworkManager sở hữu kết nối, các máy chủ thuộc hồ sơ kết nối, vì vậy cách khắc phục là thay đổi thuộc tính bằng nmcli chứ không phải sửa tệp. Nếu một daemon của nhà cung cấp đang chạy, chỉ đường khôi phục của chính nó mới sống sót qua lần kết nối tiếp theo.
Dọn trạng thái liên kết mà ứng dụng khách để lại
Một ứng dụng khách bị giết không thể chạy hook dọn dẹp của nó. SIGKILL hoàn toàn không thể bắt được, trong khi SIGINT và SIGTERM thì có thể, nên một đường hầm «chỉ dừng lại» sau khi bị giết cưỡng bức thường để lại cả đăng ký giao diện lẫn mục resolver tại chỗ. Hãy tìm PID cụ thể và chỉ gửi tín hiệu cho nó:
ps aux | grep -E "openvpn|wg-quick"
sudo kill <pid>
resolvectl revert tun0
Đừng với tay tới pkill -f vpn hay killall vpn trước khi đọc toàn bộ danh sách khớp. -f khớp với toàn bộ dòng lệnh, nên nó có thể kết thúc một script bọc, một phiên trình soạn thảo hoặc một tiến trình không liên quan có đường dẫn chứa chuỗi đó. Kết thúc sai tiến trình giữa chừng là cách một sự cố resolver trở thành một tệp bị mất.
resolvectl revert đặt lại cấu hình DNS lúc chạy của liên kết đó, hẹp hơn so với khởi động lại resolver và hẹp hơn nhiều so với sửa tệp toàn cục. Nếu liên kết đường hầm đã mất hoàn toàn, systemctl restart NetworkManager dựng lại trạng thái kết nối và đó là bước mà các luồng nguồn liên tục quay lại. Hãy chú ý tới trình quản lý dịch vụ có Restart=always, vì nó có thể đưa một ứng dụng khách bị giết và các thiết lập DNS của nó trở lại ngay.
Hướng còn lại: DNS được đẩy nhưng không bao giờ tới
Hình ảnh phản chiếu của mục cũ là một đường hầm không có resolver nào dùng được. Một tùy chọn DNS trong hồ sơ là một yêu cầu; thành phần quản lý kết nối phải chuyển nó cho resolver. Nếu nhật ký cho thấy máy chủ đã nhận được nhưng liên kết đường hầm không mang thiết lập DNS nào, thì thứ thiếu là tích hợp, không phải máy chủ.
Hãy thử việc bàn giao bằng cách làm thủ công, điều này tách «máy chủ sai» khỏi «không ai áp dụng nó»:
resolvectl dns tun0 10.10.10.10
resolvectl domain tun0 ~.
Miền định tuyến bắt tất cả gửi mọi tên tới liên kết đó, đúng điều một ứng dụng khách đường hầm đầy đủ muốn và điều DNS tách không được dùng. Những thiết lập này biến mất ở lần kết nối tiếp theo. Để làm chúng bền vững trong NetworkManager, hãy tắt DNS tự động, đặt máy chủ trên kết nối và thêm miền:
nmcli connection modify office ipv4.ignore-auto-dns yes
nmcli connection modify office ipv4.dns 10.10.10.10
nmcli connection modify office ipv4.dns-search "~."
Với một đường hầm công ty chỉ nên trả lời tên nội bộ, hãy liệt kê các vùng đó với dấu ngã ở đầu thay vì bắt tất cả, để các tên công khai tiếp tục dùng resolver cục bộ.
Những cách lách trở thành sự cố tiếp theo
Sao chép resolv.conf trước khi kết nối và khôi phục sau đó là một dòng hợp lệ trong runbook, và đó là cách lách chứ không phải sửa chữa. Nó thất bại đúng lúc quan trọng, vì một lần sụp đổ hoặc khởi động lại cưỡng bức bỏ qua việc khôi phục. Hãy ghi nó là cách lách để người tiếp theo không xây dựng trên đó.
Tắt systemd-resolved và mã hóa cứng máy chủ công cộng là nước đi phổ biến còn lại. Nó khiến việc kết nối và ngắt kết nối trở nên dễ đoán và bỏ DNS theo từng liên kết cho mọi mạng khác, điều này phá DNS tách cho tên nội bộ và vô hiệu mục đích của một đường hầm nhằm giữ các truy vấn bên trong. Cài resolvconf và ghim máy chủ công cộng tốn như vậy với thêm một lớp. Hãy coi mỗi cách là chẩn đoán: nếu nó khôi phục việc duyệt web, bạn đã biết rằng tích hợp resolver là thủ phạm, chứ không phải máy chủ công cộng đúng.
Cách sửa bền vững là một chủ sở hữu cho mỗi lớp: quyết định thành phần nào sở hữu DNS của liên kết đường hầm và thành phần nào sở hữu mặc định toàn cục, ghi lại điều đó và loại bỏ những cái khác khỏi đường đi. Sau đó xác minh sau khi ngắt kết nối bằng một tên chỉ VPN phân giải được. Nếu một tên riêng vẫn trả lời, đăng ký chưa bị gỡ; nếu không gì phân giải được, tệp trỏ tới một máy chủ không còn tồn tại. Cả hai đều thấy được trong resolvectl trước khi bạn mở trình duyệt.