Ba cái bẫy khi quản lý nhiều tài khoản: ẩn danh, đổi IP, mở nhiều profile Chrome đều chưa đủ
Mở hai cửa sổ ẩn danh trên cùng một máy, đăng nhập vào một trang ở cửa sổ thứ nhất, rồi gõ lại địa chỉ đó ở cửa sổ thứ hai: bạn vẫn đang đăng nhập. Chẳng cần công cụ gì để thấy chuyện này, và Chrome mô tả luôn hành vi đó trên trang trợ giúp. Nếu bạn đang ở một cửa sổ ẩn danh rồi mở thêm một cửa sổ nữa, phiên ẩn danh vẫn tiếp tục ở cửa sổ mới; muốn kết thúc phiên phải đóng hết mọi cửa sổ ẩn danh. Trong suốt phiên, Chrome tạm giữ cookie và dữ liệu site, chỉ xóa chúng sau khi phiên kết thúc.
Sai lầm của mình hồi đầu, khi mới bắt đầu quản lý nhiều tài khoản, là đếm bằng cửa sổ: một tài khoản, một cửa sổ, coi như xong. Thứ cần đếm lại là môi trường, gồm phần trình duyệt còn nhớ, phần máy tính lộ ra qua JavaScript, và phần nền tảng giữ ở phía server. Ba lớp ấy hiếm khi biến mất cùng lúc. Mình phải sửa lại cách đếm này ba lần.
Bẫy 1: hai cửa sổ ẩn danh vẫn chung một phiên
Mình từng coi mỗi cửa sổ ẩn danh là một tờ giấy trắng. Logic lúc đó khá gọn: ẩn danh không lưu lịch sử, không lưu cookie, nên mỗi cửa sổ là một người mới, và người mới đó sẽ biến mất khi mình đóng cửa sổ. Thói quen đi kèm là mở một cửa sổ cho mỗi tài khoản, làm xong thì đóng, hôm sau mở lại từ đầu.
Chỗ sai nằm ngay ở chữ phiên. Chrome dùng một phiên ẩn danh duy nhất cho mọi cửa sổ ẩn danh trong cùng một lần chạy trình duyệt. Trang trợ giúp có cả một câu rất thực tế: nếu thấy một con số hiện cạnh biểu tượng ẩn danh ở góc trên bên phải, nghĩa là bạn đang có nhiều cửa sổ ẩn danh, và chúng vẫn là một phiên. Cookie cùng dữ liệu site được giữ tạm trong phiên đó, chỉ bị xóa sau khi cửa sổ cuối cùng đóng. Cứ thử: Ctrl+Shift+N hai lần, đăng nhập ở cửa sổ A, mở cùng địa chỉ ở cửa sổ B, rồi vào DevTools, tab Application, mục Cookies. Hai cửa sổ đọc cùng một bộ giá trị. Chrome cũng ghi rõ là mặc định chặn cookie bên thứ ba trong ẩn danh, nên khác biệt với cửa sổ thường có thật, chỉ khác ở lớp đó.
Ngay cả khi phiên được dọn sạch, những giá trị còn lại vẫn y hệt. MDN định nghĩa dấu vân tay trình duyệt, hay fingerprint, là việc website thu thập và ghép các đặc điểm của trình duyệt và hệ điều hành, trong đó liệt kê phiên bản trình duyệt, múi giờ và ngôn ngữ ưu tiên, bộ codec video hoặc âm thanh, phông chữ đã cài, trạng thái thiết lập của trình duyệt, kích thước và độ phân giải màn hình. Đều là thuộc tính của máy, nằm ngoài phiên ẩn danh. Gõ navigator.userAgent, navigator.language, Intl.DateTimeFormat().resolvedOptions().timeZone, screen.width ở cửa sổ thường và cửa sổ ẩn danh rồi so sánh: kết quả trùng nhau, cũng trùng nhau giữa hai cửa sổ ẩn danh. Địa chỉ IP đi ra cũng là một, vì vẫn cùng máy và cùng đường mạng. Chrome nói thẳng trên trang trợ giúp là ẩn danh không làm bạn vô hình, và website vẫn có thể thu thập thông tin ngay cả khi bạn chưa đăng nhập.
Phía server còn một dấu nữa. Trợ giúp Google Account liệt kê các trường hợp tạo ra một session mới, trong đó có trường hợp đăng nhập ở cửa sổ ẩn danh hoặc riêng tư; trang google.com/devices cho xem những thiết bị đang đăng nhập hoặc đã đăng nhập trong vài tuần gần đây, mỗi mục mở ra được session, và thời điểm hiển thị là lần cuối thiết bị hoặc session trao đổi với hệ thống tại vị trí tương ứng. Một cửa sổ ẩn danh vì thế vẫn để lại một session đọc được, dù lịch sử trên máy không còn.
Giờ mình chỉ dùng ẩn danh để đọc. Đọc tài liệu, mở một link lạ, xem thử một trang mà chưa muốn đụng vào profile chính, những việc đó ẩn danh làm tốt. Khi cần tách phiên đăng nhập, mình đóng hết cửa sổ ẩn danh rồi mở lại, hoặc dùng hẳn một thư mục dữ liệu riêng. Và mình không còn đếm bằng số cửa sổ: mình đếm bằng số phiên thực sự kết thúc được.
Bẫy 2: đổi IP không xóa được cái trình duyệt đang nhớ
Lúc đó mình nghĩ thay proxy là có ngay một người mới. Mỗi tài khoản gắn một đầu ra riêng, địa chỉ IP khác nhau, vậy nền tảng thấy hai người khác nhau. Cách nghĩ này bỏ qua một chi tiết nhỏ: trình duyệt gửi gì lên server trong mỗi request.
Chi tiết bị bỏ qua nằm trong header Cookie. MDN mô tả luồng đăng nhập cơ bản: server xác thực xong thì trả cookie chứa session ID, và ở những request sau, trình duyệt gửi kèm cookie đó để báo rằng vẫn đang đăng nhập. Cũng theo MDN, mục đích đầu tiên của cookie là quản lý session, và cookie được gửi theo mọi request. Phạm vi của một cookie do Domain và Path quyết định; văn bản của MDN viết thẳng là hai thuộc tính này định nghĩa phạm vi của cookie, tức những URL nào thì cookie được gửi tới. Địa chỉ IP không có trong danh sách thuộc tính đó. Đổi proxy hay bật VPN làm thay đổi địa chỉ nguồn mà server nhìn thấy, còn chuỗi session ID trong header Cookie vẫn là chuỗi cũ.
Kiểm chứng thì nhanh: đăng nhập, mở DevTools, tab Network, chọn một request tới đúng domain đó, nhìn vào Cookie trong Request Headers; đổi đầu ra mạng rồi tải lại trang, so sánh lại chuỗi đó. Nó không đổi. Nếu session cookie có HttpOnly thì JavaScript cũng không đọc được, càng khó nhầm với chuyện dọn bằng tay trong console. MDN còn nhắc một cái bẫy nhỏ: session cookie vốn được xóa khi phiên kết thúc, nhưng một số trình duyệt dùng session restoring lúc khởi động lại, khiến chúng tồn tại lâu hơn dự kiến.
Những chỗ khác vẫn còn nguyên. MDN ghi localStorage lưu dữ liệu qua các phiên, không có thời hạn hết hạn, tách theo origin, và dữ liệu trong phiên riêng tư chỉ bị xóa khi tab riêng tư cuối cùng đóng; sessionStorage thì xóa khi page session kết thúc. IndexedDB cũng là một vùng lưu phía client. Thêm vào đó là lịch sử, mật khẩu đã lưu, dữ liệu tự động điền trong chính profile Chrome đang dùng. Đổi IP không đụng vào một dòng nào trong số này.
Muốn nhìn tận gốc, gõ chrome://version và đọc dòng Profile Path. Tài liệu User Data Directory của Chromium nói thư mục dữ liệu chứa history, bookmarks, cookie và các trạng thái cục bộ khác; mỗi profile là một thư mục con, thường là Default, nằm bên trong thư mục dữ liệu đó, và trên Windows mặc định là %LOCALAPPDATA%\Google\Chrome\User Data. Cũng theo tài liệu này, có thể truyền --user-data-dir để trỏ sang thư mục khác, và hai tiến trình Chrome đang chạy không dùng chung một thư mục dữ liệu. Trên Windows, khóa giải mã giá trị cookie nằm trong Local State tại os_crypt.encrypted_key, được bảo vệ bằng DPAPI, còn các bản Chrome mới chuyển dần sang app-bound encryption với os_crypt.app_bound_encrypted_key. Tên file cơ sở dữ liệu cookie thay đổi theo phiên bản nên mình không ghi cứng ở đây; điều cần nhớ là nó nằm trên đĩa trong thư mục profile, nằm ngoài tầm của nhà mạng.
Rồi còn phía server. Trợ giúp Google Account viết rằng google.com/devices liệt kê thiết bị đang đăng nhập hoặc đã đăng nhập trong vài tuần gần đây, mỗi mục mở ra xem được session, kèm nút Sign out. Một phiên đã tồn tại trên server không tự mất đi vì bạn đổi đường mạng. Đây là suy luận vận hành của mình, không phải điều khoản của nền tảng nào: nếu cùng một session ID tiếp tục được gửi đi từ một địa chỉ mới, phía server có đủ dữ liệu để thấy đó là một phiên đang tiếp diễn thay vì một người mới. Tài liệu công khai không nói các tín hiệu được chấm điểm ra sao, nên mình cũng không viết thành quy tắc.
Giờ mình tách bạch hai việc: đổi đường ra và đổi danh tính. Đổi đường ra thì chỉ cần thay đầu ra mạng đang dùng rồi kiểm tra lại địa chỉ; cookie giữ nguyên, chẳng có gì phải dọn. Đổi danh tính là một chuỗi khác: đăng xuất từ phía server trước, với Google là nút Sign out trong google.com/devices, rồi xóa cookie và site data trong đúng profile, dọn localStorage cùng IndexedDB nếu trang dùng chúng, tắt session restore và khởi động lại hẳn trình duyệt, sau đó mới đổi đầu ra. Cuối cùng mở tab Network xem header Cookie còn mang session ID cũ hay không. Làm ngược lại, IP mới mà session cũ, đúng là trường hợp mình dính ở cái bẫy này.
Bẫy 3: nhiều profile Chrome và câu hỏi "cái nào đang là cái nào"
Mình từng tin thêm một profile Chrome là thêm một môi trường. Chrome cho đặt tên, ảnh đại diện và màu sắc cho từng profile, lại có trình chuyển profile ngay góc trên bên phải. Nghe thì đúng tinh thần một tài khoản một trình duyệt: mỗi profile một bộ dữ liệu, mở song song, chẳng cần cài thêm gì.
Phần tách được thì có thật, phần còn lại vẫn dính vào nhau. Trang trợ giúp của Chrome ghi rõ profile giữ riêng bookmark, lịch sử, mật khẩu và các thiết lập khác, và có thể bật Show on startup để hiện danh sách profile mỗi lần mở trình duyệt. Nghĩa là cookie và lịch sử giữa các profile đã tách; cái bẫy này nằm ở chỗ khác.
Cùng một bản Chrome trên cùng một máy thì các giá trị lộ ra qua JavaScript vẫn giống hệt nhau: navigator.userAgent, múi giờ, độ phân giải màn hình, danh sách phông chữ, codec, và cả địa chỉ IP đi ra. Đó chính là nhóm đặc điểm MDN liệt kê khi định nghĩa fingerprint. Thêm profile không đổi được chúng; muốn đổi phải tách tới mức thư mục dữ liệu riêng bằng --user-data-dir, máy ảo, hoặc máy vật lý khác. Tài liệu của Chromium cũng nói mỗi profile chỉ là một thư mục con trong cùng thư mục dữ liệu, nên hai profile vẫn chung một nền tảng cài đặt. Và nếu đăng nhập Chrome bằng một Google Account, trang trợ giúp cho biết bookmark, mật khẩu và thiết lập sẽ được lưu vào tài khoản rồi dùng được trên các thiết bị khác đang đăng nhập, tức mình tự tạo thêm một điểm chung giữa các profile.
Chuyện còn lại nằm ở chỗ nhận diện, và đây mới là lý do mình bỏ cách làm này. Tên profile, màu sắc, ảnh đại diện để phân biệt người dùng với nhau, vốn không lưu được thông tin tài khoản đang chạy bên trong: tài khoản nào, gắn đầu ra nào, dùng vào việc gì, lần cuối kiểm tra khi nào. Mấy cửa sổ mở cạnh nhau trông gần như giống hệt, và mỗi lần chuyển sang một cửa sổ mình lại phải mở trang, nhìn vào tên đang đăng nhập để biết mình đang ở đâu. Chuyện dễ gặp nhất là gõ xong một đoạn nội dung rồi mới phát hiện mình đang ở sai tài khoản. Trang trợ giúp còn nhắc: xóa một profile khỏi Chrome sẽ xóa luôn bookmark, lịch sử, mật khẩu và thiết lập của profile đó khỏi máy. Muốn đặt lại một biến, mình phải hủy cả môi trường, và cái mình đang cố nhớ cũng biến mất theo.
Sau cái bẫy thứ ba: chỗ mình ghi thay vì nhớ
Trước hết là mấy cách không tốn tiền. Đặt tên profile hoặc thư mục --user-data-dir theo chính tài khoản và mục đích, đừng để Profile 1, Profile 2. Giữ một file văn bản đơn giản, mỗi tài khoản một dòng gồm tên tài khoản, thư mục dữ liệu, đầu ra mạng, mục đích và lần cuối kiểm tra. Mở cửa sổ xong, thói quen đầu tiên là nhìn tên đang đăng nhập trên trang trước khi gõ bất cứ thứ gì. Nếu cần tách sâu hơn, máy ảo hoặc vài máy vật lý làm được hết, chỉ là mỗi lần thêm một tài khoản lại thêm một chỗ phải dọn. Với ba bốn tài khoản thì đừng mua thêm gì cả, mấy dòng ghi chú là đủ.
Khi số lượng tăng đến mức file ghi chú bắt đầu lệch với thực tế, mình chuyển sang BitBrowser: trong tài liệu Add a new browser profile, một hồ sơ được tạo với Browser Name, Group, Platform, Username, Password, Open Urls và Proxy Type, trong đó Platform là trường bắt buộc, URL của nền tảng tự mở sau khi cửa sổ khởi chạy, Username và Password được tự điền cho nền tảng đó, và nếu tick vào Duplicate Validation mà platform, username, password trùng hoàn toàn với dữ liệu đã có thì hồ sơ mới sẽ không được thêm; Batch add còn có Browser Name Prefix cùng Group để đặt tên đồng loạt. Cái có ích cho bẫy thứ ba là ánh xạ tài khoản với cửa sổ được lưu thành dữ liệu ngay lúc tạo, nên mình mở đúng hồ sơ có tên thay vì đoán cửa sổ nào đang là ai. Dĩ nhiên nó không quyết định giúp mình tài khoản nào đi với đầu ra nào, cũng không sửa được dữ liệu mình gõ sai; máy ảo, --user-data-dir và vài máy vật lý vẫn làm được chuyện tương tự, chỉ tốn công hơn.
Một động tác tối nay
Mở hai cửa sổ ẩn danh, đăng nhập ở cái đầu rồi mở lại cùng địa chỉ ở cái sau. Nếu vẫn đang đăng nhập, bạn vừa tự kiểm chứng được cái bẫy thứ nhất mà chẳng cần tin vào bài viết này. Rồi mở chrome://version, đọc dòng Profile Path, và viết một dòng duy nhất cho mỗi tài khoản bạn đang giữ: tên tài khoản, thư mục dữ liệu, đầu ra mạng, mục đích, lần cuối kiểm tra. Ngày mai, trước mỗi cú gõ, bạn chỉ cần đọc dòng đó thay vì đoán cửa sổ.
All rights reserved