Tin tức

Sửa lỗi Ủy quyền X11 Giữa Các Máy Chủ bằng Việc Viết Lại Cookie Một Trường

Khi các ứng dụng X11 gặp lỗi 'Authorization required' trong container hoặc qua SSH, thủ phạm là cookie bị ghim theo tên máy chủ. Viết lại trường family thành FamilyWild (0xffff) bằng một lệnh sed duy nhất để làm cho cookie di động được.

August 2, 2026· 3 min read
Sửa lỗi Ủy quyền X11 Giữa Các Máy Chủ bằng Việc Viết Lại Cookie Một Trường

Chạy một ứng dụng X11 từ bên trong container, chroot, hoặc qua SSH thường kết thúc với lỗi đáng sợ Authorization required, but no authorization protocol specified. Tệp .Xauthority được gắn đúng nơi ứng dụng mong đợi, nhưng X vẫn từ chối kết nối. Nguyên nhân rất tinh vi, và cách sửa chỉ là một dòng sed.

Tệp .Xauthority lưu trữ các cookie được khóa theo familyhostname. Khi một ứng dụng kết nối, nó tìm mục có hostname khớp với máy mà nó tin rằng nó đang chạy—không chỉ bất kỳ cookie nào. Bên trong container hoặc qua socket không được chuyển tiếp, hostname khác với hostname mà cookie được tạo ra, vì vậy ứng dụng không bao giờ cung cấp cookie và X rơi vào trạng thái 'no authorization protocol'.

Bạn có thể kiểm tra khóa bằng xauth list; phần đầu myhost/unix:0 ghim cookie vào myhost.

FamilyWild đến giải cứu

X định nghĩa một family wildcard, FamilyWild, với giá trị số 0xffff. Một cookie trong family này khớp với bất kỳ hostname nào. Thay vì làm cho hostname của ứng dụng khớp với cookie, bạn viết lại cookie để khớp với mọi máy chủ.

Sử dụng xauth nlist để in các mục ở định dạng số, trong đó trường đầu tiên là family 4 chữ số hex. Ghi đè nó bằng ffff và hợp nhất vào một tệp mới:

: > /tmp/portable.Xauthority && xauth nlist :0 | \
    sed 's/^..../ffff/' | xauth -f /tmp/portable.Xauthority nmerge -
# Thay :0 bằng giá trị $DISPLAY của bạn

Thay đổi chỉ là một trường

Một mục .Xauthority là một bản ghi nhị phân đóng gói: family 2 byte, sau đó là địa chỉ có tiền tố độ dài, số hiển thị, tên xác thực và cookie. Kết xuất tệp gốc cho thấy family trong hai byte đầu tiên—0100, tức là FamilyLocal. Sau khi viết lại, mọi thứ giống hệt từng byte ngoại trừ hai byte đó, bây giờ là ffff. Địa chỉ vẫn ghi myhost, nhưng X không còn quan tâm vì family 0xffff khớp vô điều kiện.

Gắn bind-mount (hoặc scp) /tmp/portable.Xauthority vào ứng dụng, trỏ XAUTHORITY vào đó, và kết nối sẽ được chấp nhận bất kể hostname có khớp hay không.

Còn xhost + thì sao?

xhost + vô hiệu hóa hoàn toàn kiểm soát truy cập dựa trên host, cho phép bất kỳ ứng dụng nào kết nối mà không cần cookie. Trên máy một người dùng, điều đó nghe có vẻ vô hại, nhưng X không có sự cô lập giữa các ứng dụng: bất kỳ ai có thể truy cập máy chủ đều có thể đọc phím bấm, lấy nội dung cửa sổ và chèn đầu vào. xhost + trao điều đó cho mọi người dùng cục bộ và, nếu TCP được bật, cho cả mạng. Ngay cả xhost +local: cũng tin tưởng mọi UID trên máy.

Cookie FamilyWild giữ cửa khóa—ứng dụng vẫn phải trình bày bí mật—trong khi chỉ loại bỏ ràng buộc hostname. Hãy dùng nó thay vì xhost +, và giữ tệp cookie ở quyền 0600.

Một lưu ý

Cookie FamilyWild cố tình ít cụ thể hơn: bất kỳ ai có thể truy cập socket X của bạn và đọc tệp đều có thể nói chuyện với màn hình của bạn. Chỉ cung cấp nó cho các môi trường cần nó, và đừng để lại bản sao trên các máy dùng chung.

Thủ thuật này là một phần của thiết lập lớn hơn để chuyển tiếp X vào các container LXC không đặc quyền, được chi tiết trong bài viết của tác giả Enhancing x11 Application Security with LXC.

Cookie FamilyWild giữ cửa khóa—ứng dụng vẫn phải trình bày bí mật—trong khi chỉ loại bỏ ràng buộc hostname đang cản trở.
Ban biên tập Manul X