Khi làm việc với nhiều dự án thuộc nhiều khách hàng khác nhau, bạn cần có sự tách biệt phù hợp để bảo vệ quyền riêng tư và bảo mật. Một trong những cách hiệu quả nhất là dùng các hồ sơ trình duyệt riêng biệt cho từng dự án hoặc khách hàng.

Tuy nhiên, nếu các hồ sơ này chạy trên cùng một máy Linux với cùng một dấu vân tay trình duyệt và cùng một IP ra ngoài, các tài khoản mà bạn muốn giữ riêng có thể bị gắn với nhau một cách âm thầm. Vì vậy cần có thêm các công cụ như proxy.

Bài viết này trình bày ba mức độ cô lập trình duyệt, từ nhẹ đến chặt chẽ: hồ sơ trình duyệt gốc, sandbox Firejail và container đầy đủ. Chúng ta sẽ xem từng phương pháp hoạt động ra sao để chọn giải pháp phù hợp với nhu cầu của bạn.

Tóm tắt chính về cô lập trình duyệt Linux

  • Thách thức: Hồ sơ trình duyệt gốc tách dữ liệu nhưng không tách tiến trình hay lưu lượng mạng. Điều này khiến các nền tảng bạn đang dùng dễ liên kết các tài khoản với nhau.
  • Firejail: Firejail thêm lớp cô lập cấp tiến trình bằng namespaces và seccomp. Namespaces kiểm soát những gì tiến trình có thể thấy; seccomp kiểm soát những gì tiến trình được phép làm. Nhờ đó, trình duyệt bị kẹp chặt hơn so với chỉ chạy bằng một thư mục hồ sơ riêng.
  • Container: Container là phương pháp duy nhất cũng cô lập ngăn xếp mạng. Mỗi phiên bản trình duyệt có lớp mạng riêng: giao diện mạng, định tuyến IP và phân giải DNS riêng.
  • Vai trò của proxy: Hồ sơ riêng lẻ không làm thay đổi địa chỉ IP của bạn, do đó bạn cần một proxy đáng tin cậy. Mỗi hồ sơ nên có proxy riêng, đặt theo từng phiên bản trình duyệt, không đặt toàn hệ thống.
  • Liên kết hồ sơ: Dấu vân tay trùng khớp vẫn có thể liên kết các hồ sơ, ngay cả khi cookie sạch. Đặc điểm trình duyệt và thiết bị có thể nhận dạng một hồ sơ mà không cần dữ liệu lưu trữ.
  • Quản lý thông tin đăng nhập và tiện ích mở rộng: Các thứ này nên được quản lý theo từng hồ sơ, không dùng chung. Dùng chung thông tin đăng nhập hoặc tiện ích giữa các hồ sơ tạo ra một liên kết giữa chúng, bất chấp sự cô lập kỹ thuật.
  • Quản lý vòng đời: Xóa hồ sơ khi dự án kết thúc thay vì tái sử dụng. Tái sử dụng hồ sơ có thể mang cookie, bộ nhớ đệm hoặc thông tin đăng nhập cũ sang một ngữ cảnh mới không liên quan.

Môi trường trình duyệt cô lập là gì?

Môi trường trình duyệt cô lập nghĩa là một danh tính trình duyệt, bao gồm dữ liệu hồ sơ, cookie, bộ nhớ đệm và tiện ích mở rộng, được giữ trong bộ nhớ riêng của nó, tách khỏi mọi danh tính khác trên máy.

Trên Linux, sự tách biệt này có ba mức độ mạnh yếu:

  • Hồ sơ trình duyệt gốc cô lập chính dữ liệu.
  • Sandbox Firejail thêm cô lập tiến trình lên trên lớp đó.
  • Container đi xa hơn nữa: cô lập hệ thống tệp, cây tiến trình và ngăn xếp mạng.

Lập trình viên dùng các mức độ này để giữ dữ liệu sạch sẽ, tách biệt giữa các dự án hoặc khách hàng, và chọn mức độ phù hợp với độ nhạy cảm của sự tách biệt cần có.

Điều gì có thể rò rỉ giữa các hồ sơ không được cô lập?

Nếu không cô lập đúng cách, các hồ sơ trình duyệt có thể chia sẻ dữ liệu và tín hiệu với nhau theo nhiều cách, phá vỡ sự tách biệt mà chúng được tạo ra để đảm bảo. Cụ thể:

  • Cookie và localStorage dùng chung cho phép trang web đọc dữ liệu do một hồ sơ khác lưu lại.
  • Một IP dùng chung gắn mọi hồ sơ vào cùng một nguồn gốc mạng.
  • Dấu vân tay trình duyệt giống hệt nhau (phông chữ, kích thước màn hình, chi tiết phần cứng) có thể khiến các hồ sơ bị xác định là có liên quan, ngay cả khi bộ nhớ sạch.
  • Phiên đăng nhập lưu trong keyring hệ điều hành có thể tự động đăng nhập một hồ sơ vào tài khoản dành cho hồ sơ khác.

Trong ảnh chụp màn hình ở trên, cả hai hồ sơ đều được chạy qua bài kiểm tra Canvas Fingerprinting của BrowserLeaks và trả về chữ ký giống hệt nhau (31ACF141A4A7B424AA48797B6D5F565D) dù là hai hồ sơ riêng biệt, không cô lập. Cùng GPU, cùng hệ điều hành, cùng kết quả kết xuất. Điều đó đủ để các nền tảng liên kết chúng như một khách truy cập mà không cần một cookie nào.

Cô lập hồ sơ không thể làm gì?

Cô lập hồ sơ đôi khi bị hiểu lầm là đảm nhận nhiều khả năng bảo mật và quyền riêng tư khác. Thực tế, cô lập hồ sơ không thể:

  • Mã hóa lưu lượng truy cập.
  • Thay đổi dấu vân tay trình duyệt.
  • Che giấu địa chỉ IP.

Để đạt được sự tách biệt hoàn toàn cho dữ liệu dự án hoặc khách hàng, bạn có thể cần kết hợp cô lập hồ sơ với quản lý dấu vân tay và một proxy riêng cho mỗi hồ sơ.

Điều kiện tiên quyết

  • Môi trường desktop Linux: Cần để chạy và xem giao diện đồ họa của trình duyệt.
  • Quyền sudo: Cần để cài đặt Firejail và Podman qua các lệnh quản lý gói trong Phương pháp 2 và Phương pháp 3.
  • Firefox và/hoặc Chromium: Dùng để triển khai Phương pháp 1, tức hồ sơ trình duyệt gốc, cách đơn giản nhất trong ba cách.
  • Firejail và Podman: Chỉ cần khi triển khai Phương pháp 2 (Firejail) và Phương pháp 3 (container). Không bắt buộc nếu bạn chỉ dùng hồ sơ gốc.
  • Phiên bản đã kiểm thử: Ubuntu 24.04 LTS, Firefox ESR 128, Chromium 126, Firejail 0.9.72, Podman 5.0.

Bây giờ, chúng ta cùng xem ba phương pháp để chạy nhiều hồ sơ trình duyệt một cách an toàn trên Linux.

Phương pháp 1: Hồ sơ trình duyệt gốc

Đây là tùy chọn dễ nhất và nhanh nhất, không cần phần mềm bổ sung. Tuy nhiên, nó chỉ tách dữ liệu chứ không tách tiến trình.

Thực hiện ba bước sau để tạo hồ sơ trong Firefox:

Bước 1: Tạo hồ sơ Firefox riêng bằng Profile Manager

Chạy firefox -P trong terminal, hoặc mở Firefox rồi vào about:profiles, để tạo và đặt tên một hồ sơ mới. Muốn chạy hai hồ sơ cùng lúc, hãy khởi chạy hồ sơ thứ hai bằng lệnh firefox -no-remote -P "ProfileName".

Cờ -no-remote là bắt buộc trên các bản dựng Firefox mặc định ở chế độ single-instance; nếu thiếu nó, Firefox chỉ mở một cửa sổ mới trong hồ sơ đang chạy thay vì khởi động một hồ sơ riêng.

Trong ảnh chụp màn hình ở trên, Profile Manager của Firefox được mở bằng lệnh firefox -P, là nơi tạo và đặt tên hồ sơ mới trước khi khởi chạy từng hồ sơ một cách độc lập.

Bước 2: Chạy Chromium với --user-data-dir riêng

Tạo một hồ sơ trong Chromium bằng lệnh sau trong terminal:

chromium-browser --user-data-dir=~/profiles/client-a

Lệnh này yêu cầu Chromium lưu toàn bộ dữ liệu của phiên đó, gồm cookie, tiện ích mở rộng, bộ nhớ đệm, thông tin đăng nhập và lịch sử duyệt web, vào thư mục ~/profiles/client-a thay vì vị trí mặc định.

Mỗi lần bạn khởi chạy Chromium với một đường dẫn --user-data-dir khác, bạn sẽ có một hồ sơ riêng biệt và được cô lập.

Nếu khởi chạy Chromium mà không có cờ này, nó sẽ quay về hồ sơ mặc định.

Trong ảnh chụp màn hình ở trên, chrome://version xác nhận cờ --user-data-dir thực sự có hiệu lực. Profile Path hiển thị /home/tom-sankara/~/profiles/client-a/Default, khớp với thư mục được truyền khi khởi chạy, chứng minh dữ liệu của phiên này đang được ghi vào thư mục cô lập, không phải hồ sơ mặc định của Chromium.

Cài tiện ích Firefox Multi-Account Containers, sau đó tạo một container riêng cho từng dự án và ghim các trang web liên quan vào container đó.

Tùy chọn này hữu ích khi một hồ sơ riêng biệt là quá mức cần thiết; ví dụ khi bạn cần kiểm thử nhiều tài khoản đã đăng nhập trên cùng một trang web, hoặc giữ cho vài dự án phụ không làm lẫn cookie của nhau trong một hồ sơ duy nhất. Container vẫn dùng chung một hồ sơ và một IP, nên chúng chỉ thêm sự tiện lợi, không phải cô lập hoàn toàn.

Như trong ảnh chụp màn hình ở trên, cả hai tab container (Work và Personal) đều tải x.com mà không có phiên đăng nhập dùng chung. Vì các container dùng chung một tiến trình trình duyệt và một IP, điều này chỉ chứng minh sự tách biệt cookie/bộ nhớ, không phải cô lập mạng.

Phương pháp 2: Sandbox từng hồ sơ bằng Firejail

Firejail chạy trình duyệt bên trong một môi trường bị giới hạn, cô lập nó khỏi phần còn lại của hệ thống. Đây là bước tiến từ sự tách biệt chỉ-dữ-liệu của hồ sơ gốc lên cô lập tiến trình đầy đủ, dùng namespaces để kiểm soát những gì tiến trình sandbox có thể thấy và dùng seccomp để hạn chế những gì nó được phép làm.

Hãy xem các bước để sandbox hồ sơ bằng Firejail:

Bước 1: Cài đặt Firejail trên bản phân phối của bạn

Debian/Ubuntu:

sudo apt install firejail

Fedora:

sudo dnf install firejail

Arch:

sudo pacman -S firejail

Trong hướng dẫn này, chúng tôi dùng Ubuntu.

Bước 2: Cấp cho mỗi hồ sơ một thư mục home riêng

Chạy lệnh sau để cấp cho hồ sơ một thư mục home riêng:

firejail --noprofile --private=~/profiles/client-a /home/tom-sankara/firefox/firefox

Thay “tom-sankara” bằng tên người dùng của bạn; các ảnh chụp màn hình trong hướng dẫn này được chụp trên máy kiểm thử, nên terminal của bạn sẽ hiển thị tên khác. Điều đó là bình thường và không ảnh hưởng đến kết quả. Lệnh này ánh xạ lại mọi thứ mà sandbox nhìn thấy là $HOME thành ~/profiles/client-a; trình duyệt không thấy thư mục home thật của bạn, chỉ thấy những gì nằm trong thư mục đó.

Cửa sổ Firefox mới mở ra xác nhận điều này: không có bookmark đã nhập, không có thông tin đăng nhập đã lưu, không có lịch sử cũ, chỉ có các widget mặc định của tab mới. Đó là sự cô lập hoạt động đúng như thiết kế, không phải lỗi.

Bước 3: Khởi chạy sandbox và xác nhận nó đang hoạt động

Khi sandbox vẫn đang chạy, mở một terminal thứ hai và chạy:

firejail --list
firejail --tree

Như trong ảnh chụp màn hình ở trên, lệnh firejail --list xác nhận một sandbox đang hoạt động gắn với đúng lệnh --private= đã khởi chạy nó. Lệnh firejail --tree hiển thị toàn bộ tiến trình nằm bên dưới sandbox: tiến trình Firefox, các tiến trình nội dung và trình trợ giúp sự cố đều chạy như tiến trình con của trình bao bọc firejail thay vì trực tiếp trên máy chủ. Đầu ra của bạn sẽ hiển thị tên người dùng máy bạn thay cho tên trong hình.

Đây là bằng chứng thực sự cho thấy trình duyệt đã được sandbox, không chỉ đơn thuần là một cửa sổ được mở.

Phương pháp 3: Chạy mỗi hồ sơ trong một container Podman hoặc Docker

Container đóng gói trình duyệt và các phụ thuộc của nó vào một môi trường cô lập hoàn toàn, với hệ thống tệp, không gian tiến trình và ngăn xếp mạng riêng. Đây là phương pháp mạnh nhất trong ba phương pháp và là phương pháp duy nhất cũng tách riêng lớp mạng.

Hãy xem các bước triển khai:

Bước 1: Kéo hoặc dựng image container trình duyệt

Tải image container Firefox bằng Docker hoặc Podman:

podman pull docker.io/jlesage/firefox

Lệnh này tải về một image container Firefox đã được dựng sẵn, vì vậy bạn không cần tự dựng. Nếu muốn thiết lập tùy chỉnh, bạn có thể dựng từ một Containerfile tối thiểu để cài trình duyệt và các phụ thuộc. Người dùng Docker có thể chạy lệnh tương đương docker pull docker.io/jlesage/firefox.

Bước 2: Khởi động một container cho mỗi hồ sơ lập trình viên

Chạy lệnh sau trong terminal:

podman run -d \
--name firefox-client-a \
--shm-size=2gb \
-p 5800:5800 \
-v client-a-profile:/config \
jlesage/firefox

Mỗi cờ có một mục đích cụ thể:

  • --name firefox-client-a đặt cho container một tên dễ đọc thay vì chuỗi ngẫu nhiên, giúp các lệnh sau này (stop, logs, remove) dễ nhắm đến.
  • --shm-size=2gb cấp đủ bộ nhớ dùng chung để trình duyệt chạy mượt, vì giá trị mặc định của container thường quá nhỏ.
  • -p 5800:5800 ánh xạ giao diện web noVNC tích hợp của container tới một cổng trên máy chủ. Khác với trình duyệt cài cục bộ, image này không truy cập trực tiếp vào màn hình của bạn, nên nó phục vụ Firefox dưới dạng một luồng để bạn xem trong tab trình duyệt thông thường.
  • -v client-a-profile:/config gắn một named volume để dữ liệu của hồ sơ đó được giữ lại qua các lần khởi động lại.

Sau khi chạy lệnh, mở http://localhost:5800 trong bất kỳ trình duyệt nào trên máy chủ. Firefox tải ngay bên trong trang, hiển thị qua noVNC.

Lặp lại với tên, cổng và volume khác để tạo một container riêng cho mỗi hồ sơ lập trình viên:

podman run -d \
--name firefox-client-b \
--shm-size=2gb \
-p 5801:5800 \
-v client-b-profile:/config \
jlesage/firefox

Truy cập phiên bản thứ hai tại http://localhost:5801.

Chạy lệnh podman ps để xác nhận cả hai container đều đang chạy, mỗi container có ánh xạ cổng và volume riêng. Đó là bằng chứng hai hồ sơ đang chạy trong các container hoàn toàn tách biệt, không dùng chung một container.

Bước 3: Giữ dữ liệu hồ sơ giữa các phiên chạy

Named volumes (chẳng hạn client-a-profile và client-b-profile ở trên) được Podman quản lý tự động và tồn tại giữa các lần khởi động lại container mà không cần cấu hình thêm. Chạy lệnh podman volume ls để xác nhận chúng tồn tại.

Để sao lưu một hồ sơ, hãy tìm đường dẫn thật của nó bằng podman volume inspect client-a-profile và sao chép nội dung sang nơi khác. Để đặt lại hồ sơ về trạng thái sạch, hãy dừng container, xóa volume, rồi để Podman tạo lại volume đó ở lần chạy kế tiếp:

podman stop firefox-client-a && podman rm firefox-client-a
podman volume rm client-a-profile
podman run -d --name firefox-client-a --shm-size=2gb -p 5800:5800 -v client-a-profile:/config jlesage/firefox

Cấp cho mỗi hồ sơ một địa chỉ IP riêng

Ngay cả khi dữ liệu, tiến trình và mạng đã được cô lập hoàn hảo, ba hồ sơ cùng đi ra qua cùng một IP gia đình vẫn dễ bị liên kết với nhau; bất kỳ trang web nào cũng có thể thấy chúng đến từ cùng một mạng hoặc thiết bị.

Điều này quan trọng nhất trong quản lý tài khoản, nơi các nền tảng chủ động tìm IP dùng chung để gắn cờ các tài khoản có liên quan.

Bạn có thể khắc phục bằng cách cấp cho mỗi hồ sơ một địa chỉ IP khác nhau qua một nhà cung cấp proxy thương mại.

Chọn nhà cung cấp proxy

Để minh họa, chúng tôi dùng dịch vụ ProxyWing cho thiết lập này. ProxyWing cung cấp các endpoint residential, mobile, ISP và datacenter proxy với xác thực bằng tên đăng nhập/mật khẩu hoặc danh sách IP được phép, cùng tùy chọn chọn quốc gia; mỗi hồ sơ dùng một endpoint. Điều này khớp tự nhiên với bước cấu hình proxy bên dưới mà không cần thêm cơ sở hạ tầng.

Như mọi khi, hãy tự nghiên cứu và so sánh giá trước khi cam kết với bất kỳ nhà cung cấp nào.

Bước 1: Đặt proxy cho từng phiên bản trình duyệt, không đặt toàn hệ thống

Cấu hình proxy ở cấp trình duyệt. Trong Firefox, vào Settings > Privacy & Security > Connection & Software Security > Configure proxy rồi nhập thông tin proxy của hồ sơ đó.

Bạn sẽ được nhắc nhập thông tin xác thực vào lần đầu kết nối qua proxy này. Vì thông tin này được lưu cho riêng hồ sơ đang dùng (-p), các hồ sơ Firefox khác không bị ảnh hưởng.

Trong Chromium, không có giao diện đồ họa tương đương cho từng hồ sơ, nên hãy truyền proxy trực tiếp lúc khởi chạy bằng lệnh --proxy-server=http://user:pass@host:port; lệnh này chỉ áp dụng cho phiên bản trình duyệt đó.

Bước 2: Xác minh IP, DNS và WebRTC của từng hồ sơ

Cấu hình proxy không đảm bảo proxy thực sự hoạt động. Cấu hình sai hoặc rò rỉ vẫn có thể lộ IP thật của mạng hoặc thiết bị. Hãy mở một công cụ tra cứu IP (ví dụ ProxyWing’s IP checker) và một bài kiểm tra rò rỉ WebRTC (như browserleaks.com/webrtc) trong từng hồ sơ, sau đó so sánh kết quả cạnh nhau.

Một thiết lập đúng sẽ hiển thị một IP riêng cho mỗi hồ sơ, khớp với vị trí của proxy; DNS cũng định tuyến qua proxy thay vì qua ISP của bạn; và không có rò rỉ WebRTC nào làm lộ IP cục bộ hoặc IP công khai thật.

Tự động hóa khởi chạy hồ sơ bằng script và desktop entries

Một script shell ngắn nhận tên hồ sơ và khởi chạy đúng trình duyệt, sandbox và proxy trong một lệnh. Kết hợp script đó với một tệp .desktop sẽ biến mỗi hồ sơ thành một biểu tượng khởi chạy riêng trong menu ứng dụng.

Các biện pháp bảo mật tốt nhất cho nhiều hồ sơ lập trình viên

  • Không bao giờ dùng chung một hồ sơ cho hai khách hàng.
  • Giữ thông tin đăng nhập trong một kho riêng cho mỗi hồ sơ.
  • Tắt đồng bộ trình duyệt.
  • Kiểm tra tiện ích mở rộng theo từng hồ sơ.
  • Xóa hồ sơ khi dự án kết thúc.
  • Xác nhận proxy đang hoạt động trước khi đăng nhập.
  • Không bao giờ sao chép cookie hoặc dữ liệu phiên giữa các hồ sơ.

Các sự cố thường gặp và cách khắc phục

1. Cửa sổ trình duyệt thứ hai mở trong hồ sơ đầu tiên

Cả hai trình duyệt đều mặc định ở chế độ single-instance, nên lần khởi chạy thứ hai chỉ mở một cửa sổ trong hồ sơ đang chạy. Để khắc phục:

  • Với Firefox, thêm cờ -no-remote để buộc tạo một phiên bản mới thực sự.
  • Với Chromium, bảo đảm mỗi lần khởi chạy dùng một đường dẫn --user-data-dir riêng biệt, vì dùng lại cùng đường dẫn hoặc bỏ qua cờ này chính là nguyên nhân gây ra hành vi quay về hồ sơ cũ.

2. Trang web vẫn gắn các hồ sơ của bạn vào một người

Để xử lý, hãy kiểm tra theo thứ tự sau:

  • IP ra ngoài bị dùng chung: khắc phục bằng một proxy riêng cho mỗi hồ sơ.
  • Dấu vân tay trùng hệt: khắc phục bằng các cài đặt làm ngẫu nhiên hóa dấu vân tay.
  • Múi giờ/ngôn ngữ khớp nhau: điều chỉnh cho phù hợp với khu vực của proxy.
  • Tài khoản đồng bộ đã đăng nhập: tắt đồng bộ trên các hồ sơ khác.

3. Trình duyệt trong sandbox hoặc container không khởi động

Một số nguyên nhân phổ biến:

  • Thiếu quyền truy cập display socket.
  • /dev/shm quá nhỏ: tăng bằng --shm-size.
  • SELinux chặn mount: điều chỉnh context hoặc thêm :z.
  • Một quy tắc Firejail chặn đường dẫn: chỉnh sửa profile.

Hãy đọc thông báo lỗi; nó thường chỉ ra nguyên nhân nào đang áp dụng.

Nên chọn thiết lập nào?

Thiết lập bạn chọn phần lớn phụ thuộc vào nhu cầu. Dưới đây là một khung tham chiếu đơn giản:

  • Dùng nhiều tài khoản thông thường: hồ sơ gốc là đủ.
  • Tách biệt khách hàng: dùng Firejail vì nó thêm lớp bảo vệ thực sự mà không tốn nhiều chi phí.
  • Kiểm thử không được đụng tới máy chủ: container là giải pháp đáng tin cậy duy nhất.

Câu hỏi thường gặp

Hỏi: Tôi có thể chạy hai hồ sơ Firefox cùng lúc trên Linux không?

Đáp: Có. Sau khi khởi chạy hồ sơ đầu tiên, bạn khởi chạy hồ sơ thứ hai bằng -no-remote -P "ProfileName" nếu bản dựng của bạn mặc định single-instance.

Hỏi: Firejail có đủ để giữ các hồ sơ trình duyệt tách biệt không?

Đáp: Firejail cô lập hệ thống tệp và tiến trình, không cô lập mạng. Bạn vẫn cần một proxy riêng cho mỗi hồ sơ. Proxy cho phép bạn cấp một địa chỉ IP duy nhất cho mỗi hồ sơ.

Hỏi: Tôi có cần một địa chỉ IP khác nhau cho mỗi hồ sơ trình duyệt không?

Đáp: Với hầu hết nhu cầu thông thường, bạn có thể dùng cùng một IP. Tuy nhiên, với các tác vụ như quản lý tài khoản hoặc kiểm thử theo vùng địa lý, bạn sẽ cần một địa chỉ IP khác nhau cho mỗi hồ sơ.

Hỏi: Sự khác biệt giữa container Firefox và hồ sơ Firefox là gì?

Đáp: Container chia tách cookie trong cùng một hồ sơ. Hồ sơ là một danh tính hoàn toàn riêng biệt với bộ nhớ riêng của nó.

Hỏi: Chạy trình duyệt trong Docker có làm chậm không?

Đáp: Có một chút chi phí đến từ runtime và display socket. Tuy nhiên, khác biệt về hiệu suất thường không đáng kể trên phần cứng hiện đại.

Hỏi: Dùng nhiều tài khoản lập trình viên từ một máy có được phép không?

Đáp: Nhìn chung là được, miễn là bạn tuân thủ điều khoản dịch vụ của từng nền tảng.