0

Ba lớp quản lý đa tài khoản TikTok cho một agency vận hành ba mươi tài khoản

Một tài khoản TikTok không đứng một mình. Nó đi kèm dấu vân tay thiết bị, địa chỉ IP, lịch sử phiên đăng nhập và nhịp làm việc hằng ngày. Khi ba mươi tài khoản của một agency cùng chạy trên một địa chỉ IP văn phòng, chính những dấu vết ấy khiến nền tảng gom chúng thành nhóm rủi ro.

Bài viết bắt đầu từ một sự cố có thật của đội bốn người ở Hà Nội: hai nhân viên cùng mở một tài khoản làm video nhảy vị trí, còn năm tài khoản bị giới hạn chức năng sau một đêm. Bài mổ xẻ ba lớp kỹ thuật đứng sau mỗi tài khoản: dấu vân tay trình duyệt, dữ liệu phiên cùng cookie, địa tuyến IP cùng múi giờ, ngôn ngữ và WebRTC. Tách đủ ba lớp mới xong, thiếu một lớp thì vẫn hỏng.

Anh Tuấn, 31 tuổi, điều hành một agency bốn người ở Đống Đa, Hà Nội. Văn phòng nằm ở tầng năm một dãy nhà cũ trên phố nhỏ, thang máy hay kêu ở tầng ba, cửa sổ nhìn ra sân chung chất đống xe máy. Sáng nào đội cũng bắt đầu bằng cốc cà phê mua ở quán đầu ngõ, rồi leo thang, rồi mở laptop trước khi kịp pha thêm cốc nữa.

Bốn người gồm anh Tuấn, hai nhân viên sáng tạo nội dung tên Mai và Huy, và một bạn quản lý tài khoản tên Long. Nghề của họ là vận hành nội dung TikTok thay khách hàng: sáu khách hàng, ba mươi tài khoản, mảng mỹ phẩm, nội thất và phụ kiện. Mỗi tài khoản gắn với một khách hàng và một quy trình đăng video riêng, kiểu bốn tài khoản cho khách hàng mỹ phẩm chuyên son và kem chống nắng, ba tài khoản cho khách nội thất, phần còn lại chia đều cho mảng phụ kiện.

Chiều thứ Tư trước mùa mưa, khoảng bốn giờ chiều, Mai gọi lên: “Anh ơi, video em đăng lúc nãy biến mất khỏi trang cá nhân, mà bên bảng số liệu của khách thì trống mất một dòng.” Cô gái nói giọng hơi gấp, kiểu vừa chạy vừa gọi.

Anh Tuấn mở trang quản trị của khách, không thấy video ấy đâu. Trong danh sách video của tài khoản, thứ tự đã lộn xộn: vài video cũ của tháng trước nhảy lên đầu, còn video của Mai nhảy vị trí, lọt xuống cuối danh sách. Anh mở danh sách phiên đăng nhập thì thấy hai thiết bị cùng nằm trong danh sách phiên hoạt động của tài khoản đó, máy của Mai và máy của Huy.

Huy giải thích là anh đăng nhập để kiểm tra một video đang chờ duyệt, thấy nó biến khỏi chỗ cũ, tưởng lỗi hiển thị nên đăng nhập lại lần nữa. Phiên của Mai bị ghi đè, và những dữ liệu tài khoản lưu theo phiên, từ token đăng nhập tới mã định danh thiết bị và lịch sử tương tác cục bộ, bị thay bằng bộ giá trị của phiên mới. Video không mất khỏi máy chủ TikTok, nhưng chỗ nó đứng trong danh sách lẫn các chỉ số đi kèm đều lệch, nên khách hàng nhìn vào bảng số liệu thấy một video bốc hơi và mất luôn dữ liệu của ngày hôm đó.

Anh Tuấn xin lỗi khách, rồi ngồi nhìn màn hình một lúc lâu. Ở đội bốn người, mỗi người một máy, mỗi máy đăng nhập ba tới bốn tài khoản khác nhau, và cả bốn máy đều đi qua một đường Wi-Fi văn phòng với một địa chỉ IP cố định mà ai cũng biết.

Chuyện tệ hơn đến vào đêm thứ Bảy. Sáng chủ nhật, khách hàng nội thất gọi báo năm tài khoản của họ bị giới hạn chức năng: vẫn xem được, vẫn vào được trang cá nhân, nhưng không đăng được video, không ghim được bình luận, không bật được quảng cáo tăng trưởng. Năm tài khoản thuộc ba khách hàng khác nhau, nội dung khác nhau, không dính dáng gì đến nhau, cùng bị trong một đêm.

Anh Tuấn mở nhật ký đối chiếu thì thấy ngay: tối đó ba người ngồi cùng lúc trên ba tài khoản khác nhau, cùng IP văn phòng, cùng một đợt đăng video lúc hai mươi giờ, cùng nhấn like và bình luận trong vòng mười lăm phút. Đúng cái nhịp mà một nhóm người thật ngồi trong văn phòng nhỏ cũng có thể tạo ra, nhưng lặp đều đặn ở quy mô ba mươi tài khoản thì thành một cụm tín hiệu rõ ràng.

Cái nhìn mới đến từ một bạn freelancer anh Tuấn quen, đang làm cho một agency khác bên kia cầu Thanh. Người nói thẳng một câu anh Tuấn nhớ khá lâu: “Ba mươi tài khoản của anh không hỏng vì nội dung. Chúng hỏng vì anh đang cho chúng sống trong cùng một căn hộ.” Cùng IP, cùng máy, cùng hồ sơ trình duyệt, cùng lịch sử đăng nhập, cùng giờ vào giờ ra.

Từ đó anh Tuấn dừng mọi việc thử nghiệm cứu vãn và bắt đầu dựng lại từ gốc, theo ba tầng. Mỗi tài khoản một danh tính riêng, mỗi danh tính một phiên riêng, mỗi phiên nằm trong một cấu trúc tổ chức có người chịu trách nhiệm. Mỗi khách hàng một nhóm cửa sổ riêng để lọc công việc, mỗi nhân viên một ghế thành viên riêng, mỗi tài khoản một chuỗi xác thực hai lớp riêng, mọi thao tác đăng nhập, đăng video và đổi cấu hình đều để lại một dòng nhật ký.

Tiền không phải rào cản lớn của cuộc chơi. Một ghế thành viên thêm là 51.746 đồng một tháng theo mức giá hiện tại, còn ba mươi môi trường thì vượt mức mười môi trường miễn phí, nên phải cân nhắc gói. Nhưng anh Tuấn tính đơn giản hơn thế: mất một khách hàng còn đắt hơn nhiều so với tiền công cụ.

Vấn đề thật sự nằm ở đâu

Khi nền tảng đánh giá một tài khoản, nó không nhìn thẻ “tài khoản”, mà nhìn chuỗi tín hiệu ghép lại. Chuỗi đó có ba nhóm: thiết bị, phiên và hành vi. Nhóm thiết bị gồm dấu vân tay trình duyệt mà trang web đọc được trong vài phần nghìn giây. Nhóm phiên gồm cookie, localStorage, IndexedDB, cache và các mã định danh thiết bị mà máy chủ sinh ra khi bạn đăng nhập. Nhóm hành vi gồm nhịp độ thao tác, khung giờ hoạt động, thứ tự và khoảng cách giữa các lần đăng nhập.

Sự cố của anh Tuấn nằm ở chỗ cả ba nhóm đều bị dùng chung. Một chi tiết đáng nói: nhiều nền tảng đọc localStorage và IndexedDB trước cả cookie, nên nếu các tài khoản dùng chung một kho dữ liệu trình duyệt, chúng sẽ thấy cùng một mã định danh thiết bị dù cookie đã khác nhau. Cách ly vì thế phải nằm ở mức thư mục hồ sơ của trình duyệt, chứ không phải mở thêm nhiều cửa sổ ẩn danh.

Mở cửa sổ ẩn danh thường được coi là nhanh gọn, nhưng nó không tách được phần lớn tín hiệu. Cùng một địa chỉ IP văn phòng, cùng hệ thống font của máy, cùng cấu hình phần cứng, cùng thư mục cache cấp hệ thống, cùng cấu hình WebRTC. Tín hiệu nào không tách được thì đó là tín hiệu còn lại trong bộ hồ sơ chung.

Với IP, hệ thống kiểm tra trước tiên, và đây là lý do năm tài khoản của anh Tuấn sập cùng lúc. IP là tín hiệu mạnh vì nó rẻ, dễ thu thập, dễ so sánh giữa hàng triệu tài khoản. Hệ thống xét loại IP là trung tâm dữ liệu, dân dụng hay di động, ASN của nhà cung cấp, lịch sử bị ghi nhận trong các danh sách đen, và tần suất đổi IP.

Điểm hay bị bỏ qua là dải IP: nếu ba mươi tài khoản dùng các địa chỉ nằm trong cùng một khối liên tiếp, hệ thống vẫn gom được chúng dễ dàng hơn là bốn mươi địa chỉ rải rác. Một bộ IP nên trải trên nhiều ASN và nhiều tỉnh thành, đừng dồn về một khối cho tiện. Với đội đang vận hành tài khoản ở Việt Nam, IP di động 4G và IP dân dụng trong nước là lựa chọn tự nhiên hơn so với IP của trung tâm dữ liệu.

Còn một lớp nữa ít khi được nói tới: sự khớp chặt giữa các tín hiệu. Múi giờ, ngôn ngữ giao diện, vị trí và IP phải nói cùng một câu. Một tài khoản có IP tại Việt Nam nhưng múi giờ đặt theo Châu Âu, hoặc địa chỉ IP ở Đức nhưng độ trễ ping như người ở Hà Nội, đều là những dấu hiệu rẻ tiền để bị soi. Máy chủ có nhìn, nhưng cả hành vi cũng bị xét tới: đăng bài lúc ba giờ sáng theo giờ Việt Nam nhưng lịch sử tương tác lại theo giờ Mỹ, là một kiểu bất thường mà người dùng thật rất hiếm tạo ra.

Ở tầng kỹ thuật sâu hơn là dấu vân tay của lớp bắt tay TLS, thường gọi là JA3. Nhiều hệ thống chấm điểm dựa trên chuỗi bắt tay này, nên một nhóm máy dùng chung thư viện mã hóa sẽ bị gom lại dù địa chỉ IP đã khác nhau. Khi dựng hồ sơ trình duyệt, mỗi hồ sơ nên có một chuỗi JA3 riêng và giữ ổn định, thay vì đổi mỗi lần mở trình duyệt hoặc dùng chung một chuỗi cho cả đội.

Cuối cùng là nhịp. Hệ thống chống gian lận hiện đại nhìn cả thiết bị lẫn nhịp độ hành vi. Ba mươi tài khoản cùng mở app đúng một giờ, cùng đăng video đúng một giờ, cùng nhấn like trong cùng ba giây, đăng nhập ở sáu múi giờ khác nhau trong vòng một giờ, đó là hành vi theo lô, theo kiểu bursty mà máy làm, không phải người làm. Ngược lại, một tài khoản mới mở lên mà xem có chủ đề, lướt có chọn lọc, đăng một video ngắn, rồi nghỉ, tạo ra một lịch sử hoạt động nhịp tự nhiên, giống người hơn nhiều.

Ba lớp quản lý: danh tính, phiên, tổ chức

Anh Tuấn dựng lại hệ thống theo ba tầng, và ba tầng này không thay thế nhau. Thiếu tầng dưới thì tầng trên cũng không cứu được.

Lớp danh tính: hồ sơ trình duyệt, dấu vân tay, IP

Mỗi tài khoản cần một hồ sơ trình duyệt riêng, và hồ sơ đó phải có dấu vân tay khớp với IP đi kèm. Các chiều thông tin cần khớp gồm Canvas, WebGL, AudioContext, danh sách font, chuỗi User-Agent, hệ điều hành và số nhân CPU, dung lượng bộ nhớ, độ phân giải màn hình, WebRTC, dấu vân tay IPv6 và dấu vân tay JA3 của lớp bắt tay TLS. Hai chiều dễ bị bỏ sót là danh sách font và số nhân CPU, vì chúng gần như không đổi theo thời gian nên rất dễ bị gom nhóm khi nhiều hồ sơ cùng kế thừa từ một máy.

Điểm thứ hai của lớp này là cách ly bộ nhớ. Cookie, localStorage, IndexedDB, cache và sessionStorage phải nằm trong thư mục riêng của từng hồ sơ, không chia sẻ. Với BitBrowser, mỗi cửa sổ trình duyệt là một hồ sơ có thư mục lưu trữ riêng và có thể gắn một proxy riêng; khi nhập IP, phần mềm còn tự điền quốc gia, tỉnh thành, thành phố và có thể tự đồng bộ múi giờ cùng ngôn ngữ theo vị trí IP, để tránh ra tình huống kiểu IP Việt Nam đi kèm múi giờ Hà Nội trong lúc nền tảng lại đang nhìn một IP ở nước ngoài.

Lớp phiên: cookie, session, xác thực hai lớp

Lớp này quyết định một tài khoản có ổn định hay không. Phiên đăng nhập phải ở trạng thái ổn định dài ngày, không phải đăng nhập lại mỗi buổi sáng. Mỗi tài khoản một chuỗi xác thực hai lớp riêng, mã xác thực của tài khoản này không dùng để đăng nhập tài khoản kia, và không có hai thiết bị cùng giữ một phiên. Cũng cần nhớ rằng một tài khoản không được đăng nhập đồng thời trên nhiều máy, nên khi một đội nhiều người cùng cần dùng, cách đúng là cấp một ghế thành viên riêng cho từng người, mỗi ghế là một tài khoản quản lý độc lập.

Lớp tổ chức: nhóm, vai trò, phân quyền, nhật ký

Đây là tầng mà nhiều đội bỏ qua, và cũng là tầng giảm rủi ro nhanh. Nhóm cửa sổ theo khách hàng giúp lọc công việc: một khách hàng một nhóm, nhân viên chỉ thấy nhóm được cấp. Trong BitBrowser, quyền được gán theo nhóm cửa sổ và theo vai trò, nên một người làm video cho khách A không nhìn thấy khách B, không sửa được proxy của người khác, và cũng không xoá được cửa sổ đang chạy.

Phần nhật ký là lớp thứ ba trong cùng tầng đó. Mỗi lần đăng nhập, mỗi lần đăng video, mỗi lần đổi proxy hay đổi cấu hình đều nên để lại một dòng có thời gian, người thực hiện, tài khoản và hành động. BitBrowser có sẵn nhật ký vận hành và một bộ ghi log độc lập qua Local API, đủ để ghi nhận những sự kiện cần tự theo dõi. Khi khách hàng hỏi video tuần trước do ai đăng, câu trả lời phải lấy được trong vòng một phút, không phải mở nhóm chat đoán.

Cấu hình thực tế

Trong các ví dụ bên dưới, BitBrowser được dùng làm mẫu tham chiếu vì nó có sẵn cơ chế tách hồ sơ theo thư mục, khớp múi giờ theo IP và Local API để kéo dữ liệu. Phần logic thì áp dụng được cho mọi công cụ quản lý đa tài khoản, kể cả khi dựng trên nền tảng khác.

Đoạn JSON dưới đây là ví dụ minh hoạ cho lệnh tạo một hồ sơ trình duyệt TikTok tại Việt Nam qua Local API. Các giá trị cụ thể nên đối chiếu lại với tài liệu API chính thức tại doc.bitbrowser.net trước khi áp dụng vào dự án thật.

{
  "groupId": "2c9c29a28161edd0018161f3790d0002",
  "name": "TK-HN-MYPHAM-01",
  "remark": "Khach hang MyPham - Han Noi - video 1",
  "platform": "https://www.tiktok.com",
  "url": "https://www.tiktok.com/",
  "proxyMethod": 2,
  "proxyType": "socks5",
  "host": "203.113.128.45",
  "port": 1080,
  "proxyUserName": "ten-dang-nhap-proxy",
  "proxyPassword": "mat-khau-proxy",
  "browserFingerPrint": {
    "coreProduct": "chrome",
    "coreVersion": "112",
    "ostype": "PC",
    "os": "Win32",
    "osVersion": "10",
    "userAgent": "",
    "isIpCreateTimeZone": true,
    "isIpCreateLanguage": false,
    "languages": "vi-VN,vi",
    "isIpCreateDisplayLanguage": false,
    "displayLanguages": "vi-VN",
    "webRTC": "2",
    "position": "1",
    "isIpCreatePosition": true,
    "fontType": "2",
    "canvas": "0",
    "canvasValue": 240000,
    "webGL": "0",
    "webGLValue": 315000,
    "webGLMeta": "0",
    "audioContext": "0",
    "audioContextValue": 30,
    "hardwareConcurrency": "8",
    "deviceMemory": "8",
    "doNotTrack": "1",
    "clientRectNoiseEnabled": true,
    "clientRectNoiseValue": 1200,
    "portScanProtect": "0"
  }
}

Dưới đây là đoạn mã minh hoạ luồng mở cửa sổ ở chế độ chạy ẩn rồi điều khiển bằng Playwright qua cổng gỡ lỗi, kèm đọc cookie thời gian thực và ghi một dòng nhật ký vận hành. Địa chỉ Local API lấy trong phần cài đặt hệ thống của ứng dụng.

const LOCAL_API = 'http://127.0.0.1:54345';
 
async function callApi(path, body = {}) {
  const res = await fetch(`${LOCAL_API}${path}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  const json = await res.json();
  if (!json.success) {
    throw new Error(json.msg || 'Loi khong xac dinh');
  }
  return json.data;
}
 
async function main() {
  const browserId = '2c9c29a28sdd33dds8026f78se380142';
 
  // Mo cua so che do chay an, khong mo san cac trang mac dinh.
  const opened = await callApi('/browser/open', {
    id: browserId,
    args: ['--headless'],
    queue: true,
    ignoreDefaultUrls: true,
  });
 
  // Noi vao phien vua mo qua giao thuc DevTools.
  const { chromium } = require('playwright');
  const browser = await chromium.connectOverCDP('http://' + opened.http);
  const context = browser.contexts()[0];
  const page = await context.newPage();
  await page.goto('https://www.tiktok.com/', { waitUntil: 'domcontentloaded' });
 
  // Doc cookie thoi gian thuc de dong bo kho.
  const cookies = await callApi('/browser/cookies/get', { browserId: browserId });
 
  // Ghi nhat ky van hanh.
  await callApi('/extralog/add', {
    log_name: 'mo-phien-tiktok',
    log_key: 'tk-hn-mypham-01-' + Date.now(),
    log_type: 'phien',
    log_value: 'da-mo-va-ghi-log',
    log_desc: 'Mo profile TK-HN-MYPHAM-01 qua Local API',
    log_remark: 'may-cong-tu-van',
    log_extra_info: JSON.stringify({ pid: opened.pid, coreVersion: opened.coreVersion }),
  });
 
  console.log('So cookie doc duoc:', cookies.length);
  await browser.close();
}
 
main().catch((err) => {
  console.error(err.message);
  process.exit(1);
});

Vì sao phải bật ignoreDefaultUrls khi chạy ẩn: nếu hồ sơ có cấu hình mở sẵn nhiều địa chỉ, chế độ không giao diện sẽ báo lỗi vì không hỗ trợ mở nhiều trang cùng lúc ngay khi khởi động. Cách an toàn là để hồ sơ không có địa chỉ mặc định, rồi tự điều hướng bằng mã sau khi cửa sổ đã mở.

Quy trình bàn giao tài khoản cho nhân viên mới

Đây là phần mà đội nào cũng làm vội, và là phần hay sinh sự cố. Một nhân viên mới cần dùng ba tài khoản của khách hàng mỹ phẩm, quy trình dưới đây giữ được cả ba tầng mà không phải đưa mật khẩu tài khoản TikTok cho bất kỳ ai.

Bốn cấp vai trò trong BitBrowser được thiết kế đúng cho tình huống này. Mỗi cấp gắn với một nhóm cửa sổ và một phạm vi việc khác nhau, nên đội anh Tuấn không cần chế độ thủ công cho từng tài khoản.

Điểm quan trọng ở dòng cuối là vai trò tùy chỉnh chỉ hữu ích khi đi kèm một quy trình duy trì. Nếu không ai rà soát lại quyền theo quý, quyền tùy chỉnh sẽ dần biến thành quyền chung, và lớp tổ chức mất tác dụng.

Bảng kiểm tra mười tiêu chí

Mười tiêu chí này nên được soi trước khi nhận thêm một khách hàng mới, chứ không phải sau khi sự cố xảy ra. Riêng tiêu chí số 10 cần để ý hơn, vì quy trình bàn giao tài khoản chính là nơi thông tin nhạy cảm của khách hàng hay bị rò rỉ.

Kết luận

Nhìn lại sáu tháng vừa qua, anh Tuấn không hề thay đổi nội dung video, không đổi lịch đăng, cũng không mua thêm tài khoản nào. Cái anh đổi là cách ba mươi tài khoản cũ được vận hành và cách bốn người được phép chạm vào chúng. Đó mới là phần khó khi mở rộng quy mô, và cũng là phần quyết định khách hàng có tiếp tục ở lại hay không.

Nếu đội đang vận hành dưới mười tài khoản, thứ tự nên làm là chuẩn hóa quy trình trước khi mua thêm công cụ. Viết ra một trang quy trình vận hành mà bất kỳ người mới nào đọc là hiểu: tài khoản này của khách hàng nào, ai được phép mở, đăng video lúc mấy giờ, ai duyệt nội dung trước khi đăng, sự cố xảy ra thì báo ai. Sau đó mới chuẩn hóa danh sách kiểm tra khi nhận thêm tài khoản, mà bảng mười tiêu chí ở trên là một mẫu.

Bên cạnh quy trình, cần một chính sách phê duyệt nội dung. Video của một tài khoản trong danh mục của anh Tuấn phải qua tay Long trước khi lên lịch, và Long kiểm tra ba thứ: có nhãn quảng cáo đúng quy định khi nói về sản phẩm, có thông tin khách hàng nhúng vào video đúng chỗ, và nội dung không trùng lặp với các tài khoản cùng ngành hàng. Một nhân viên không có đủ thông tin để tự quyết định những điều đó, và đó là lý do phân quyền cần gắn với vai trò chứ không phải với niềm tin.

Bài học rút ra từ sáu tháng qua, theo anh Tuấn, là công cụ chỉ giữ được kỷ luật chứ không tự tạo ra kỷ luật. Một hồ sơ tách sạch vẫn hỏng nếu người ngồi sau đó đăng năm video cùng một lúc vào hai giờ sáng. Một nhóm cửa sổ rõ ràng vẫn vô nghĩa nếu không có ai chịu trách nhiệm duyệt nội dung trước khi đăng. Công cụ tốt làm cho việc tuân thủ quy trình rẻ hơn và ít sót hơn, còn quy trình thì mới là thứ giữ được danh mục tài khoản của khách hàng sống lâu.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.