Lý do để mã hóa một máy chủ bạn đi thuê hẹp hơn nhiều so với những gì quảng cáo gợi ý, nhưng lại mạnh hơn nhiều trong đúng phạm vi hẹp đó. Ổ NVMe hỏng và bị trả về nhà cung cấp trong khi dữ liệu của bạn vẫn còn nằm trên đó. Node bị ngừng hoạt động và phần lưu trữ bị bán lại. Phần cứng bị sao chụp, hoặc bị mang ra khỏi rack. Trong mọi trường hợp đó, LUKS chính là ranh giới giữa một hệ thống tệp đọc được — các khóa, cơ sở dữ liệu, hộp thư của bạn — và một khối nhiễu mà chẳng ai làm được gì với nó.
Điều nó không làm là bảo vệ bạn khỏi chính cỗ máy bạn đang chạy trên đó. Sự phân biệt đó là toàn bộ nội dung của hướng dẫn này, nên nó được nói trước tiên, trước cả câu lệnh đầu tiên. Sau đó mới đến phần việc thực sự: một volume LUKS2 được thiết lập đúng cách, một bản sao lưu header, swap được mã hóa, mở khóa từ xa qua SSH, và kế hoạch khôi phục cho lần khởi động lại không quay về. Cỗ máy bên dưới bạn có thể thuê mà không cần giấy tờ tùy thân và thanh toán bằng Monero; mã hóa là một lớp bạn thêm vào phía trên đó, không phải một thứ thay thế cho nó.
Mã hóa dữ liệu tĩnh thực sự bảo vệ điều gì
Mã hóa toàn ổ đĩa trả lời một câu hỏi duy nhất và trả lời nó một cách trọn vẹn: chuyện gì xảy ra khi người khác nắm giữ ổ đĩa trong lúc nó đã tắt nguồn? Trên hạ tầng đi thuê, đó không phải là chuyện giả định. Ổ đĩa hỏng và được trả về nhà cung cấp. Node bị ngừng hoạt động và phần lưu trữ bị bán lại. Volume bị sao chụp trong một cuộc điều tra, hoặc rời khỏi tòa nhà trong một thùng hàng.
- Được bảo vệ. Một ổ đĩa đã tắt nguồn, một bản sao chụp ngoại tuyến của volume, một ổ đĩa được trả lại theo bảo hành, một node đã ngừng hoạt động, một tệp snapshot được sao chép. Trong mọi trường hợp đó, kẻ tấn công chỉ nắm trong tay dữ liệu đã mã hóa và một header, và không có passphrase thì câu chuyện dừng lại ở đó.
- Không được bảo vệ: một cỗ máy đang chạy. Ngay khi volume được mở, khóa đã nằm trong bộ nhớ kernel và hệ thống tệp lộ rõ với bất cứ thứ gì có quyền root.
- Không được bảo vệ: lưu lượng của bạn. Các byte trên đường truyền là chuyện của TLS và WireGuard. LUKS chưa bao giờ nhìn thấy chúng.
- Không được bảo vệ: một tài khoản root đã bị xâm phạm. Một kẻ xâm nhập đã ở bên trong sẽ đọc tệp của bạn qua đúng điểm mount mà bạn dùng. Đó là lý do tăng cường bảo mật tồn tại, và hai biện pháp này không thể thay thế cho nhau.
Danh sách này cố tình ngắn gọn. Mã hóa dữ liệu tĩnh là một biện pháp rẻ tiền, giá trị cao với phạm vi được giới hạn chính xác, và gần như mọi sự thất vọng người ta gặp phải với nó đều bắt nguồn từ việc âm thầm kỳ vọng nó cũng bao trùm luôn ba điều còn lại.
Điều kiện ràng buộc của phần cứng đi thuê, nói thẳng ra
Khi volume đã mã hóa của bạn được mở, khóa nằm trong RAM của guest — và trên bất kỳ VPS nào ở bất cứ đâu, RAM đó cũng nằm trên một cỗ máy mà nhà vận hành kiểm soát về mặt vật lý. Một hypervisor có thể đọc được bộ nhớ của guest. Đây không phải là lỗi của LUKS, của KVM, hay của riêng nhà cung cấp này; đó là bản chất của việc đi thuê một cỗ máy, và bất kỳ nhà cung cấp nào nói khác đi đều đang mô tả một sản phẩm không hề tồn tại.
Vậy nên phép tính này rất phũ phàng: mã hóa dữ liệu tĩnh biến cuộc tấn công ngoại tuyến thành bất khả thi, còn cuộc tấn công trực tuyến thì vẫn y nguyên như cũ. Một ổ đĩa rời khỏi rack trở nên vô giá trị. Một máy chủ đang chạy vẫn lộ diện y như hôm qua. Cả hai nửa của câu đó đều đúng cùng một lúc, và một hướng dẫn chỉ nói cho bạn nghe nửa đầu thì không phải đang giúp ích gì cho bạn.
Thứ thực sự làm dịch chuyển được nửa còn lại là một tập hợp biện pháp khác, và chúng chồng lên mã hóa chứ không thay thế nó. Không có gì được lưu hồ sơ để tiết lộ, vì việc đăng ký ở đây là không cần KYC — chỉ một email để gửi thông tin đăng nhập và không gì khác. Khoản thanh toán được xử lý on-chain thay vì qua ngân hàng. Và pháp lý nơi máy chủ đặt tại quyết định lệnh nào có thể ép buộc được điều gì. Bài phân tích thẳng thắn về những gì một VPS trả bằng crypto che giấu được của chúng tôi sẽ đi sâu vào phần còn lại, và mục Fourteen Eyes nói về khía cạnh chia sẻ tình báo. Đọc như một lớp trong số nhiều lớp, LUKS là một khoản đầu tư cực kỳ xứng đáng. Đọc như một lá chắn chống lại chính nhà cung cấp của bạn, đó là một sự hiểu lầm.
Volume dữ liệu hay hệ thống tệp root: chọn trước khi gõ lệnh
Có hai hình thức mà việc này có thể theo, và lựa chọn nằm ở mức độ rủi ro, chứ không phải ở độ mạnh yếu.
- Một volume dữ liệu được mã hóa. Một container LUKS nằm bên cạnh hệ điều hành. Mọi thứ quan trọng — cơ sở dữ liệu, email, khóa, tệp tải lên, bản sao lưu — đều sống bên trong nó; còn bản thân hệ điều hành vẫn ở dạng rõ. Mười phút công sức, không có rủi ro boot nào cả, và có thể đảo ngược ở bất kỳ thời điểm nào. Đây là thứ mà đa số độc giả nên xây dựng, và đó cũng là điều các bước bên dưới sẽ thực hiện.
- Một hệ thống tệp root được mã hóa. Mọi thứ đều nằm bên trong, kể cả log, danh sách gói và lịch sử shell mà bạn đã quên mất. Mạnh hơn hẳn về mặt bảo mật, nhưng cũng thực sự khó áp dụng hơn lên một cỗ máy đang chạy sẵn.
Lý do cho sự khó khăn đó đáng được nói rõ vì chẳng hướng dẫn nào từng làm vậy: bạn không thể mã hóa một hệ thống tệp đang được mount ở chế độ đọc-ghi và đang phục vụ chính phiên SSH của bạn. Cả hai phương pháp thực sự — thu nhỏ rồi sao chép, hoặc dùng cryptsetup reencrypt tại chỗ — đều cần root phải offline. Trên một máy có console ngoài băng, bạn khởi động một trình cài đặt và đó là việc thường ngày. Trên một VPS không có console, bạn phải chuyển hệ thống đang chạy sang một RAM disk trước, và nếu bất kỳ phần nào trong đó trục trặc, máy chủ sẽ không quay lại được nữa và con đường khôi phục duy nhất là cài lại từ đầu, tức là xóa sạch ổ đĩa.
Vì vậy: hãy xây dựng volume dữ liệu ngay hôm nay, đưa mọi thứ quan trọng vào đó, và coi việc mã hóa root là một quyết định bạn đưa ra ngay lúc triển khai, trên một máy chủ chưa có gì để mất. Phần cuối của bài sẽ nói về hướng đi đó, bao gồm cả dropbear-initramfs để gõ passphrase qua SSH lúc khởi động.
Những gì bạn cần trước khi bắt đầu
Không nhiều, và đó cũng là một phần lý do vì sao việc này đáng làm.
- Một gói. Mã hóa không đòi hỏi thêm RAM và gần như không tốn thêm CPU. Cub (1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo) là đủ; Scout (2 vCPU / 4 GB / 70 GB, $9.00/mo) là kích cỡ thoải mái hơn nếu máy chủ còn chạy thêm một dịch vụ thực sự. Con số duy nhất thực sự quan trọng là dung lượng ổ đĩa, vì volume mã hóa của bạn sẽ được trích ra từ đó.
- Debian 12 hoặc 13 từ thư viện template, hoặc Ubuntu LTS — các lệnh bên dưới mang phong cách Debian và tên gói ở nơi khác sẽ khác đi. Triển khai chỉ mất khoảng một phút, và ảo hóa KVM đầy đủ nghĩa là một kernel thật sự có sẵn các module
dm-crypt, chứ không phải một container mượn kernel của người khác. - Mười phút tăng cường bảo mật cơ bản trước đã. Mã hóa trên một máy chủ vẫn còn chấp nhận đăng nhập bằng mật khẩu chẳng khác nào một ổ khóa gắn trên cánh cửa không có khung.
- Một passphrase mà bạn chưa từng dùng ở bất cứ đâu khác, được tạo ngẫu nhiên chứ không phải tự nghĩ ra, và được lưu ở một nơi vẫn còn tồn tại kể cả khi bạn mất chiếc máy này. Không có khôi phục, không có đặt lại, và không có ticket hỗ trợ nào giúp được.
- Một nơi bên ngoài máy chủ để giữ bản sao lưu header. Snapshot hàng tuần đã có sẵn trong mọi gói, nhưng snapshot của một volume đã mã hóa thì vẫn ở dạng mã hóa — hữu ích để rollback, vô dụng nếu passphrase đã mất.
Vị trí đặt máy chủ không ảnh hưởng gì đến bất kỳ điều nào ở trên, nên hãy chọn theo giá hoặc theo pháp lý: Amsterdam, Paris, Bucharest và Sofia có giá cơ bản, còn Zurich, Reykjavik, Stockholm và Kuala Lumpur có hệ số nhân thêm.
Từng bước một
- Triển khai, tăng cường bảo mật, và xác nhận CPU có AES-NI
Triển khai Debian 13 từ thư viện template và dành mười phút cho các bước cơ bản trước đã: chỉ dùng SSH key, tắt đăng nhập bằng mật khẩu cho root, nftables mặc định chặn tất cả, và cập nhật bảo mật tự động. Sau đó, hãy xác nhận rằng phần cứng sẽ không bắt bạn phải trả giá cho việc này:
grep -o -m1 ' aes ' /proc/cpuinfo apt update && apt install -y cryptsetup cryptsetup benchmarkBạn cần tìm các con số
aes-xtsở mức gigabyte mỗi giây. Bất kỳ CPU máy chủ x86-64 nào trong thập kỷ qua đều có AES-NI, nên mã hóa sẽ không phải là điểm nghẽn của bạn — NVMe bên dưới nó mới là điểm nghẽn, y hệt như trước đây. - Tạo khoảng trống cho volume
Nếu ổ đĩa của gói bạn còn khoảng trống chưa được phân vùng, hãy dùng nó — một phân vùng thật là thứ sạch sẽ nhất để mã hóa:
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT sgdisk -n 0:0:0 -c 0:secure /dev/vda partprobe /dev/vdaNếu template đã lấp đầy ổ đĩa, đừng cố chống lại điều đó. Một container dựa trên tệp hoàn toàn được hỗ trợ đầy đủ ở đây, không tốn chút thông lượng nào trên NVMe, và có thể mở rộng sau này:
fallocate -l 20G /var/lib/secure.img chmod 600 /var/lib/secure.img losetup --find --show /var/lib/secure.imgHãy ghi lại thiết bị loop mà nó in ra — thường là
/dev/loop0. Mọi chỗ bên dưới đều dùng/dev/disk/by-partlabel/secure; hãy thay bằng thiết bị loop của bạn nếu bạn chọn hướng dùng container. - Định dạng nó thành LUKS2 — và giới hạn chi phí bộ nhớ
Đây là câu lệnh quyết định mọi thứ, nên nó đáng để đọc kỹ chứ không chỉ dán vào:
cryptsetup luksFormat --type luks2 \ --cipher aes-xts-plain64 --key-size 512 \ --pbkdf argon2id --pbkdf-memory 262144 --iter-time 5000 \ /dev/disk/by-partlabel/secure--key-size 512là AES-256 ở chế độ XTS, vốn chia khóa làm đôi — đây không phải AES-512, vì thứ đó không tồn tại.--pbkdf argon2idlà hàm dẫn xuất khóa memory-hard, khiến việc brute-force passphrase của bạn tốn kém cả về RAM lẫn CPU.--pbkdf-memory 262144giới hạn con số đó ở 256 MB, và đây chính là dòng mà người ta hay bỏ sót rồi phải hối hận. Nếu để mặc định,cryptsetupsẽ tự điều chỉnh chi phí bộ nhớ theo lượng RAM khả dụng tại thời điểm định dạng. Mở khóa cùng một header đó sau này ở một nơi có ít RAM hơn — một gói 1 GB, một môi trường rescue, một initramfs — và nó có thể thất bại hoàn toàn. Hãy chủ động giới hạn nó. - Mở nó ra, tạo hệ thống tệp, rồi mount nó
cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue \ --allow-discards open /dev/disk/by-partlabel/secure secure mkfs.ext4 -L secure /dev/mapper/secure mkdir -p /srv/secure mount -o noatime /dev/mapper/secure /srv/secure df -h /srv/secureHai flag workqueue chỉ có ý nghĩa trên NVMe và không nơi nào khác;
--allow-discardsgiữ cho TRIM hoạt động, đánh đổi bằng việc để lộ block nào đang được dùng cho bất kỳ ai đang giữ ổ đĩa đã tắt nguồn. Cả hai được bàn kỹ hơn ở bên dưới — các giá trị mặc định ở trên là lựa chọn đúng cho một máy chủ đa dụng. - Sao lưu header của LUKS, ra khỏi máy chủ
Hãy làm việc này ngay bây giờ, trước khi có bất cứ thứ gì đáng mất nằm trên volume. Header là khoảng 16 MB metadata chứa các keyslot, và một header bị hỏng đồng nghĩa với việc dữ liệu đã mã hóa không thể khôi phục được, dù bạn có nhớ passphrase chính xác đến đâu:
cryptsetup luksHeaderBackup /dev/disk/by-partlabel/secure \ --header-backup-file /root/secure-header.img sha256sum /root/secure-header.imgHãy sao chép nó sang một nơi khác — dùng
scpđể tải xuống, cho vào trình quản lý mật khẩu, in ra hash — rồi xóa bản sao cục bộ. Hãy coi tệp đó tương đương với chính passphrase, bởi vì khi kết hợp với bất kỳ passphrase nào nó từng mang, nó đúng là như vậy. - Chuyển những gì quan trọng vào volume
Một volume đã mã hóa mà không ai ghi vào thì chẳng bảo vệ được gì cả. Hãy dừng dịch vụ trước, di chuyển state của nó, rồi bind-mount lại đường dẫn cũ để không có gì khác cần cấu hình lại:
systemctl stop postgresql rsync -aHAX --info=progress2 /var/lib/postgresql/ /srv/secure/postgresql/ mv /var/lib/postgresql /var/lib/postgresql.old mkdir /var/lib/postgresql echo '/srv/secure/postgresql /var/lib/postgresql none bind 0 0' >> /etc/fstab mount /var/lib/postgresql systemctl start postgresqlHãy xác nhận dịch vụ hoạt động khỏe mạnh trước khi
shredhoặc xóa thư mục.old— và hãy nhớ rằng trên một hệ thống tệp copy-on-write hoặc một NVMe có wear levelling, xóa bản rõ không đồng nghĩa với việc hủy nó hoàn toàn. Phiên bản sạch sẽ của câu chuyện này là tạo volume mã hóa trước khi dịch vụ đó tồn tại. - Quyết định cách nó mở khóa, và hãy thành thật về điều đó
Đây là ngã rẽ mà ai cũng gặp phải. Hãy thêm volume vào
/etc/crypttabvớinoautođể không có gì chặn quá trình boot, và tự tay mở khóa nó qua SSH khi cần:echo 'secure /dev/disk/by-partlabel/secure none \ luks,noauto,discard,no-read-workqueue,no-write-workqueue' >> /etc/crypttab cryptdisks_start secureĐó là cấu hình trung thực: khóa chỉ tồn tại khi bạn có mặt, và một lần khởi động lại sẽ để volume ở trạng thái đóng cho tới khi bạn ra lệnh khác. Cái giá phải trả là những lần khởi động lại không người giám sát sẽ quay về với dịch vụ ở trạng thái ngừng chạy.
Lựa chọn thay thế là một keyfile trong
/etc/crypttabđể volume tự động mở. Nếu keyfile đó nằm trên cùng ổ đĩa, bạn chưa mã hóa được gì cả — bất kỳ ai giữ ổ đĩa đã tắt nguồn cũng sẽ giữ luôn chiếc khóa nằm ngay cạnh ổ khóa đó. Nó chỉ thực sự có ý nghĩa khi khóa đến từ một nơi mà ổ đĩa không có: được lấy qua một đường hầm WireGuard lúc boot, hoặc được gõ vào một initramfs qua SSH như ở phần cuối bài. Hãy chọn một cách có chủ đích; mặc định mở khóa thủ công mới là lựa chọn đúng như tên gọi của nó. - Mã hóa swap, và xác minh toàn bộ hệ thống
Swap là nơi bộ nhớ biến thành một dấu vết trên ổ đĩa, nên một volume đã mã hóa nằm cạnh một swap ở dạng rõ sẽ làm lộ đúng những bí mật mà bạn đang cố bảo vệ. Một khóa ngẫu nhiên cho mỗi lần boot là câu trả lời đúng đắn — không có gì phải quản lý, không có gì để mất. Hãy kiểm tra
swapon --showtrước và thay bằng thiết bị của riêng bạn; nếu template cấp cho bạn một tệp swap thay vì một phân vùng, hãy xóa nó và dùng một phân vùng nhỏ thay thế, vì một thiết bị dùng khóa ngẫu nhiên cần một block device:swapoff -a sed -i '/swap/s/^/#/' /etc/fstab echo 'swap /dev/vda3 /dev/urandom \ swap,cipher=aes-xts-plain64,size=512' >> /etc/crypttab echo '/dev/mapper/swap none swap sw 0 0' >> /etc/fstabSau đó hãy khởi động lại — trong lúc việc sai sót vẫn còn rẻ — và kiểm tra kết quả một cách trung thực:
lsblk -o NAME,FSTYPE,MOUNTPOINT cryptsetup status secure blkid /dev/disk/by-partlabel/secure # should say crypto_LUKS swapon --show # should show /dev/mapper/swapPhép thử thực sự có giá trị: với volume đã đóng, hãy xác nhận
/srv/securetrống rỗng và dịch vụ phụ thuộc vào nó từ chối khởi động. Nếu cả hai điều đó đúng, việc mã hóa là thật chứ không chỉ mang tính hình thức.
Keyslot, header và passphrase bạn đã xoay vòng
LUKS2 giữ tối đa 32 keyslot. Mỗi keyslot chứa một bản sao của cùng một master key, được bọc bằng một passphrase khác nhau, đó là lý do vì sao bạn có thể thêm một passphrase thứ hai mà không cần mã hóa lại bất cứ thứ gì:
cryptsetup luksAddKey /dev/disk/by-partlabel/secure
cryptsetup luksDump /dev/disk/by-partlabel/secure | grep -A2 '^Keyslots'
cryptsetup luksKillSlot /dev/disk/by-partlabel/secure 1Có hai passphrase ngay từ đầu là lựa chọn mặc định đúng đắn: một cái bạn dùng hàng ngày, một cái được ghi lại và cất ở một nơi khác. Mất quyền truy cập duy nhất vào một volume chỉ vì gõ sai một ký tự trong trình quản lý mật khẩu là cách phổ biến nhất khiến người ta mất dữ liệu LUKS, còn phổ biến hơn bất cứ điều gì một kẻ tấn công có thể làm.
Và đây là cái bẫy. Một bản sao lưu header được lấy trước khi bạn xoay vòng passphrase vẫn sẽ mở được volume bằng passphrase cũ. Keyslot nằm trong header, nên một bản sao cũ của header cũng là một bản sao cũ của các keyslot — trong khi master key bên dưới thì chưa từng thay đổi. Nếu bạn xoay vòng passphrase vì nghi ngờ nó đã bị lộ, bạn phải hủy mọi bản sao lưu header được lấy trước lần xoay vòng đó và lấy một bản mới. Nếu không, việc xoay vòng chẳng đạt được gì ngoài việc khiến bạn cảm thấy yên tâm hơn một cách vô căn cứ.
Chính sự thật đó khiến bản sao lưu header cũng nhạy cảm không kém: tệp 16 MB đó cộng với bất kỳ passphrase nào nó từng biết là đủ để giải mã volume. Hãy cất nó ở nơi bạn cất passphrase, không phải nơi bạn cất snapshot.
Hiệu năng: AES-NI, NVMe và hai flag đáng biết
cryptsetup benchmark cho bạn biết sự thật về đúng vCPU của bạn chỉ trong khoảng mười lăm giây. Trên bất kỳ CPU nào có AES-NI — tức là bất kỳ bộ xử lý máy chủ x86-64 nào trong thập kỷ qua — hãy kỳ vọng vài gigabyte mỗi giây cho aes-xts, nhanh hơn thoải mái so với NVMe bên dưới nó. Chi phí thực tế trên khối lượng công việc thật chỉ là vài phần trăm ít ỏi, và đó là chi phí CPU, không phải độ trễ.
Có hai tùy chọn cryptsetup quan trọng trên bộ lưu trữ tốc độ cao, và chỉ trên bộ lưu trữ tốc độ cao mà thôi:
cryptsetup --perf-no_read_workqueue --perf-no_write_workqueue \
--allow-discards open /dev/disk/by-partlabel/secure secureCác flag workqueue này bỏ qua hàng đợi nội bộ của dm-crypt và chuyển I/O thẳng tới thiết bị. Trên một ổ đĩa cơ, chúng chẳng thay đổi gì cả; trên NVMe RAID10, chúng loại bỏ một điểm nghẽn thực sự ở mức queue depth cao. Hãy thêm chúng vào dòng option của crypttab dưới dạng no-read-workqueue,no-write-workqueue để chúng có hiệu lực vĩnh viễn.
--allow-discards là tùy chọn có sự đánh đổi. Nó cho phép TRIM đi xuyên qua tới NVMe, giúp duy trì hiệu năng ghi theo thời gian — nhưng đồng thời cũng để lộ cho bất kỳ ai đang giữ ổ đĩa đã tắt nguồn biết block nào đang được dùng và block nào còn trống. Đó là một rò rỉ thông tin có thật, dù khiêm tốn: nó hé lộ khoảng mức độ đầy của volume và có thể gợi ý về cấu trúc hệ thống tệp. Trên một máy chủ đa dụng, hãy chấp nhận đánh đổi để lấy hiệu năng. Nếu nội dung của volume thuộc dạng mà kích thước của nó cũng nhạy cảm, hãy tắt discard đi.
Hướng đi mã hóa root, và mở khóa từ xa qua SSH
Nếu bạn muốn mã hóa mọi thứ, hãy làm điều đó trên một máy chưa có gì cả — triển khai, chuyển đổi, rồi mới xây dựng. Bản thân việc chuyển đổi khá chuẩn mực: thu nhỏ hệ thống tệp root trong lúc nó offline, tạo một container LUKS2 trong khoảng trống vừa giải phóng, sao chép toàn bộ hệ thống sang bằng rsync -aHAX, trỏ /etc/fstab và /etc/crypttab vào thiết bị mapper, rồi chạy update-initramfs -u -k all và cài lại GRUB. Phần khiến chuyện này trở thành vấn đề riêng của VPS không console nằm ở cụm từ trong lúc nó offline: để đạt được điều đó mà không có console nghĩa là phải chuyển hệ thống đang chạy sang một root tạm trên RAM trước, và đó chính là bước kết thúc bằng việc cài lại từ đầu khi có gì đó trục trặc.
Thứ khiến một root đã mã hóa còn khả dụng được trên một máy từ xa chính là dropbear-initramfs — một SSH server nặng khoảng 200 KB được tích hợp thẳng vào boot image, lắng nghe trong lúc kernel chờ passphrase:
apt install dropbear-initramfs cryptsetup-initramfs
# Debian 12/13: /etc/dropbear/initramfs/
cp ~/.ssh/unlock_key.pub /etc/dropbear/initramfs/authorized_keys
chmod 600 /etc/dropbear/initramfs/authorized_keys
echo 'DROPBEAR_OPTIONS="-I 300 -j -k -p 2222 -s -c cryptroot-unlock"' \
>> /etc/dropbear/initramfs/dropbear.conf
echo 'IP=:::::eth0:dhcp' >> /etc/initramfs-tools/initramfs.conf
update-initramfs -u -k allSau đó bạn ssh -p 2222 root@your-ip trong lúc máy khởi động, và lệnh cryptroot-unlock bị buộc chạy sẽ hỏi passphrase. Có ba điều đáng biết trước khi bạn phụ thuộc vào cơ chế này. initramfs có host key riêng của chính nó, nên client của bạn sẽ cảnh báo về sự không khớp trên cổng 2222 — điều đó là bình thường, và cũng là lý do nên dùng một cổng riêng cho nó. Host key đó cùng với authorized_keys của bạn nằm trên một phân vùng boot không mã hóa, có thể đọc được bởi bất kỳ ai đang giữ ổ đĩa, nên hãy dùng một khóa unlock không dùng cho việc gì khác. Và -s vô hiệu hóa đăng nhập bằng mật khẩu trong initramfs, điều này không phải tùy chọn có thể bỏ qua.
Chi tiết khác gây rắc rối trên các gói nhỏ chính là điều đã nói ở bước ba, và nó gây rắc rối nặng nhất ở chính đây. initramfs chạy trước khi phần lớn RAM của bạn sẵn sàng cho bất cứ điều gì thoải mái, nên một header được định dạng với chi phí bộ nhớ Argon2id lớn có thể không mở khóa được ngay trên chính chiếc máy đã tạo ra nó. Hãy định dạng với --pbkdf-memory đã bị giới hạn, và thử khởi động lại trong khi bạn vẫn chưa có gì để mất.
Ngày thứ hai: điều gì thay đổi, và điều gì không
Rất ít thứ thay đổi, và đó chính là điểm mấu chốt. Một volume LUKS đã mở là một block device bình thường; fsck, rsync, df và công cụ sao lưu của bạn đều hoạt động y hệt như trước. Việc nâng cấp kernel không bị ảnh hưởng vì dm-crypt đã nằm sẵn trong cây kernel. Mở rộng volume sau khi nâng cấp gói chỉ cần hai lệnh — cryptsetup resize rồi đến lệnh resize của chính hệ thống tệp — và không cần mã hóa lại.
Có ba thói quen đáng xây dựng. Diễn tập việc khởi động lại theo lịch trình định kỳ, thay vì phát hiện lúc 3 giờ sáng rằng một passphrase bạn chưa từng ghi lại là bản sao duy nhất còn tồn tại. Giữ cho các bản sao lưu được mã hóa một cách độc lập — dùng restic hoặc borg tới một đích lưu trữ ngoài máy chủ, đây là một biện pháp tách biệt với volume và vẫn sống sót ngay cả khi bạn mất trắng máy chủ; gói bổ sung sao lưu ngoài máy chủ hàng ngày có giá $2.00/mo nếu bạn không muốn tự xây dựng việc này. Và hãy đóng volume lại trước khi bạn thôi quan tâm đến máy chủ: chạy cryptsetup close secure trước một lần tắt máy có kế hoạch, di chuyển hoặc cài lại nghĩa là khóa đã ra khỏi bộ nhớ trước khi ổ đĩa thôi thuộc về bạn.
Về mặt chính sách, không có gì để thương lượng cả. Bạn có toàn quyền root trên một guest KVM, và bạn làm gì với tầng block là chuyện của riêng bạn; mã hóa volume của chính mình là công việc quản trị hệ thống bình thường, không phải một trường hợp ngoại lệ. Chính sách sử dụng chấp nhận được nói về hành vi — giới hạn cứng là không CSAM và không khủng bố — và không hề nói gì về dm-crypt cả. Điều mà mã hóa thực sự thay đổi là hình dạng của một ngày tồi tệ giả định: một volume đã tắt nguồn rời khỏi tòa nhà này chỉ là nhiễu, và điều đó xứng đáng với mười phút thời gian của bạn.
Câu hỏi thường gặp
Mã hóa toàn ổ đĩa có ngăn được nhà cung cấp hosting đọc dữ liệu của tôi không?
Không, khi máy chủ đang chạy thì không. Một khi volume đã được mở khóa, khóa nằm trong RAM của guest, và trên bất kỳ VPS nào, bộ nhớ đó cũng nằm trên phần cứng do nhà vận hành kiểm soát — một hypervisor có thể đọc được nó. Điều mà LUKS làm được một cách trọn vẹn là khiến ổ đĩa đã tắt nguồn trở nên vô giá trị: một ổ đĩa được trả về nhà cung cấp, một node đã ngừng hoạt động, một bản sao chụp ngoại tuyến. Bất kỳ ai quảng cáo mã hóa ổ đĩa như một sự bảo vệ khỏi chính nhà cung cấp của bạn đều đang mô tả một thứ không hề tồn tại.
Tôi có thể mã hóa một VPS không có console hay KVM-over-IP không?
Với một volume dữ liệu được mã hóa thì có — hoàn toàn qua SSH, không rủi ro boot, trong khoảng mười phút. Một hệ thống tệp root được mã hóa thì khác: mọi phương pháp đều cần root phải offline, mà trên một máy không console nghĩa là phải chuyển hệ thống đang chạy sang một RAM disk trước. Nó có thể làm được, nhưng đó cũng là cách người ta thường làm mất máy chủ. Hãy chuyển đổi ngay lúc triển khai khi máy chưa có gì, và dùng dropbear-initramfs để có thể gõ passphrase qua SSH lúc khởi động.
LUKS thực sự tốn bao nhiêu hiệu năng?
Chỉ vài phần trăm ít ỏi trên bất kỳ CPU nào có AES-NI, tức là bất kỳ vCPU x86-64 hiện đại nào. Chạy cryptsetup benchmark và bạn sẽ thấy aes-xts đạt mức gigabyte mỗi giây — nhanh hơn cả NVMe mà nó chạy trên đó, nên bộ lưu trữ vẫn là điểm nghẽn. Trên các ổ đĩa nhanh, --perf-no_read_workqueue và --perf-no_write_workqueue lấy lại phần lớn hiệu năng còn thiếu ở mức queue depth cao.
Điều gì xảy ra nếu tôi mất passphrase?
Dữ liệu coi như mất. Không có cơ chế khôi phục, không có master key nào được ai khác nắm giữ, và không có ticket hỗ trợ nào giúp được — đó chính là đặc tính mà bạn đã bỏ tiền ra mua. Hãy giảm thiểu rủi ro này từ trước: thêm một passphrase thứ hai vào một keyslot riêng bằng cryptsetup luksAddKey, và giữ một bản sao lưu header ở bên ngoài máy chủ. Lưu ý rằng một bản sao lưu header được lấy trước khi xoay vòng passphrase vẫn sẽ mở được volume bằng passphrase cũ, nên hãy hủy các bản sao cũ mỗi khi bạn xoay vòng.
Tôi cần gói VPS nào để chạy một volume đã mã hóa?
Mã hóa không đòi hỏi thêm RAM và gần như không tốn thêm CPU, nên cấp gói được quyết định bởi khối lượng công việc của bạn chứ không phải bởi LUKS. Cub (1 vCPU / 2 GB / 40 GB NVMe, $5.00/mo) chạy một volume mã hóa mà chẳng hề hấn gì; Scout (2 vCPU / 4 GB / 70 GB, $9.00/mo) là kích cỡ thoải mái khi máy chủ còn chạy thêm một cơ sở dữ liệu hoặc một mail server. Ràng buộc thực sự duy nhất là dung lượng ổ đĩa, vì volume được trích ra từ đó.
Việc mã hóa máy chủ của tôi có được phép trên các gói của bạn không?
Có — đó là công việc quản trị hệ thống bình thường. Bạn có toàn quyền root trên một guest KVM với kernel thật, nên dm-crypt, phân vùng tùy chỉnh và bất cứ điều gì khác ở tầng block đều do bạn tự cấu hình. Chính sách sử dụng chấp nhận được điều chỉnh hành vi, không phải cấu hình kỹ thuật, và giới hạn cứng ở đó là không CSAM và không khủng bố.
Tôi có cần mã hóa cả swap không?
Có, và đây là bước mà hầu hết các hướng dẫn khác bỏ qua. Swap là nơi bộ nhớ kernel — bao gồm cả khóa và các buffer đã giải mã — kết thúc thành một dấu vết trên ổ đĩa, nên một swap ở dạng rõ nằm cạnh một volume đã mã hóa sẽ làm lộ chính thứ bạn đang cố bảo vệ. Hãy dùng một khóa ngẫu nhiên cho mỗi lần boot thông qua /etc/crypttab: không có gì phải quản lý và không có gì để mất. Hệ quả là hibernation trở nên bất khả thi, điều mà trên một VPS chẳng tốn kém gì cả.

