HướNG DẫN
Cách bảo mật một VPS mới: mười phút đầu tiên
Một server mới dễ bị tấn công nhất ngay tại thời điểm nó nhận được một địa chỉ IP. Các scanner tự động quét liên tục toàn bộ không gian IPv4, nên những lượt đăng nhập đầu tiên nhắm vào một máy vừa triển khai một phút trước thường đã xuất hiện trước khi bạn đọc xong màn hình chào mừng của nó. Không có gì trong số đó nhắm riêng vào bạn — đó chỉ là bức xạ nền, và đó là lý do một server chưa gia cố với mật khẩu trên root bị chiếm quyền trong vài giờ chứ không phải vài tháng. Tin tốt là việc khóa kín nó lại chỉ mất chút công sức: mười phút thực hiện các bước theo đúng thứ tự loại bỏ gần như toàn bộ rủi ro mang tính cơ hội. Hướng dẫn này trình bày checklist đó, thứ tự giúp bạn không tự khóa mình ở ngoài server, và một điều mà hầu hết các hướng dẫn gia cố khác không bao giờ nhắc tới — những chi tiết cá nhân mà một cấu hình mặc định âm thầm ghi lên một cỗ máy bạn thuê riêng để nó không bị gắn với bạn.
Gia cố thực sự bảo vệ bạn khỏi điều gì
Gia cố đáng để làm chính vì lợi ích của nó vừa hẹp vừa thực chất. Hiểu rõ ranh giới đó giúp bạn tránh một cảm giác an toàn giả tạo ở những vùng mà nó không chạm tới.
- Nó loại bỏ hoàn toàn kẻ tấn công cơ hội. Bot credential-stuffing, brute force SSH và các lượt quét tìm bảng quản trị bị lộ ra ngoài đều thất bại trước xác thực chỉ bằng khóa và một firewall mặc định từ chối.
- Nó giới hạn phạm vi ảnh hưởng khi có thứ gì đó bạn đang chạy bị lỗi. Một dịch vụ chỉ bind vào localhost phía sau một cổng đã đóng thì không người lạ nào chạm tới được, kể cả đúng ngày CVE của nó được công bố.
- Nó giảm bớt cái giá phải trả cho một sai lầm. Người dùng không có đặc quyền, các khóa tách biệt và vá lỗi tự động nghĩa là một quyết định sai cũng không trao luôn cả cỗ máy cho kẻ khác.
- Nó không giấu được server khỏi nhà cung cấp host. Bất kỳ ai có quyền truy cập vào hypervisor thì về nguyên tắc đều có thể đọc được bộ nhớ của một cỗ máy đang chạy — đó là câu hỏi về việc bạn thuê của ai, không phải về các quy tắc firewall của bạn.
- Nó không khiến bạn ẩn danh. Gia cố bảo vệ cỗ máy; còn việc cỗ máy đó có gắn với tên bạn hay không được quyết định ngay từ lúc đăng ký và lúc thanh toán, rất lâu trước khi bạn đăng nhập lần đầu.
Sự phân biệt cuối cùng đó chính là điều nhiều người hiểu ngược. Một server được gia cố hoàn hảo nhưng mua bằng thẻ tín dụng đứng tên thật của bạn thì vẫn là một server đứng tên thật của bạn. Hai lớp này bổ trợ cho nhau: hosting không KYC và một số dư nạp bằng tiền mã hóa quyết định trên giấy tờ cỗ máy đó thuộc về ai, còn mười phút dưới đây quyết định ai có thể vào được bên trong nó.
Thứ tự giúp bạn không tự khóa mình ở ngoài
Gần như mọi câu chuyện kinh hoàng về gia cố đều là cùng một câu chuyện: ai đó tắt xác thực bằng mật khẩu trước khi xác nhận khóa của họ hoạt động, hoặc bật firewall với bộ quy tắc không có SSH, rồi tự khóa mình ở ngoài một cỗ máy mà họ không còn cách nào chạm tới. Thứ tự các bước tồn tại chính là để loại trừ khả năng đó. Cài khóa trước và chứng minh nó hoạt động ở một cửa sổ thứ hai. Chỉ sau đó mới tắt mật khẩu. Thêm quy tắc firewall cho SSH trước khi bật firewall, không bao giờ làm sau.
Cũng đáng để biết trước đường khôi phục của bạn là gì trước khi cần đến nó. Một VPS mà bạn chỉ có thể chạm tới qua SSH thì chỉ có đúng một cánh cửa, nên console trong khu vực khách hàng của nhà cung cấp chính là phương án dự phòng biến một lần bị khóa ngoài thành một sự bất tiện thay vì phải dựng lại từ đầu. Hãy kiểm tra rằng bạn có thể mở được nó trong khi mọi thứ vẫn đang hoạt động bình thường.
Từng bước: mười phút đầu tiên trên một cỗ máy mới
- 01Cập nhật chỉ mục gói và các gói đã cài đặtMột image mới chỉ là một bản chụp nhanh tại thời điểm nó được dựng. Đưa nó về trạng thái mới nhất là hành động có giá trị cao nhất trong toàn bộ danh sách, và chỉ mất chưa tới một phút.
- 02Tạo một người dùng không có đặc quyền, kèm sudoLàm việc với root mọi lúc nghĩa là mọi lỗi gõ nhầm và mọi tiến trình đều chạy với toàn quyền. Hãy tạo một người dùng bình thường, thêm nó vào nhóm sudo hoặc wheel, và dùng người dùng đó.
- 03Sao chép khóa công khai của bạn sang người dùng đóTạo một khóa ed25519 trên chính máy của bạn nếu chưa có, rồi đẩy nửa công khai của nó lên bằng ssh-copy-id. Khóa riêng tư không bao giờ rời khỏi laptop của bạn.
- 04Mở một terminal thứ hai và xác nhận đăng nhập bằng khóa hoạt độngĐừng bỏ qua bước này. Đăng nhập bằng người dùng mới với khóa đó, trong một cửa sổ mới, trước khi thay đổi bất cứ điều gì liên quan đến xác thực.
- 05Tắt xác thực bằng mật khẩu và đăng nhập rootĐặt PasswordAuthentication no và PermitRootLogin prohibit-password, rồi tải lại sshd. Brute force nhắm vào máy giờ đây không còn gì để đoán.
- 06Bật một firewall mặc định từ chối, cho phép SSHTừ chối toàn bộ kết nối đến, cho phép cổng SSH của bạn, rồi mới bật firewall lên. Sau đó thêm dần từng cổng mà các dịch vụ của riêng bạn cần, mỗi lần một cổng.
- 07Bật cập nhật bảo mật tự độngunattended-upgrades trên Debian và Ubuntu, dnf-automatic trên các bản RHEL. Đây chính là thứ giữ cho cỗ máy an toàn ở tháng thứ sáu, khi bạn đã ngừng để ý tới nó.
- 08Liệt kê những gì đang lắng nghe và đóng những gì không nên mởChỉ một lệnh ss -tulpn cho bạn biết mọi socket đang mở. Bất cứ thứ gì bạn không chủ ý đặt ở đó nên được gỡ bỏ hoặc chuyển về bind ở localhost.
SSH: chỉ dùng khóa, và những thiết lập thực sự quan trọng
Xác thực bằng khóa công khai chính là toàn bộ việc gia cố SSH. Một khi mật khẩu đã tắt, kẻ tấn công cần một khóa riêng tư mà chúng không có, và đoán bao nhiêu lần cũng không tạo ra được nó. Hãy tạo khóa ed25519 — chúng ngắn, nhanh, và là lựa chọn mặc định hiện đại — và đặt một passphrase cho khóa để một chiếc laptop bị đánh cắp không đồng nghĩa với một server bị đánh cắp. Mọi thứ khác trong sshd_config chỉ là sự tinh chỉnh thêm trên nền quyết định duy nhất đó.
- PasswordAuthentication no — thiết lập chấm dứt brute force. Hãy xác nhận khóa của bạn hoạt động trước, trong một phiên thứ hai.
- PermitRootLogin prohibit-password — root vẫn có thể được truy cập bằng khóa để khôi phục, nhưng không bao giờ bằng mật khẩu. Đặt nó thành no ngay khi người dùng sudo của bạn đã được xác nhận hoạt động.
- AllowUsers hoặc AllowGroups — một allowlist tường minh về việc ai được phép đăng nhập, để một tài khoản dịch vụ do một gói phần mềm nào đó tạo ra không bao giờ có thể trở thành điểm vào qua SSH.
- KbdInteractiveAuthentication no — đóng nốt con đường tương tác còn lại, thứ có thể âm thầm bật lại lời nhắc mật khẩu trên một số bản phân phối.
- Một khóa thứ hai cho một thiết bị thứ hai, thay vì sao chép một khóa riêng tư duy nhất đi khắp nơi. Mất một chiếc điện thoại chỉ nên đồng nghĩa với việc xóa một dòng khỏi authorized_keys, chứ không phải xoay vòng lại toàn bộ.
- Chuyển SSH ra khỏi cổng 22 giúp giảm mạnh khối lượng log, nhưng hãy coi đó là cách giảm nhiễu chứ không phải bảo mật thực sự — nó không thay đổi gì với bất kỳ ai thực sự đang để ý tới IP của bạn.
Nếu bạn muốn đi xa hơn khóa, cách sắp xếp mạnh nhất là không để lộ SSH ra công khai chút nào: đặt cỗ máy phía sau một đường hầm WireGuard và chặn cổng 22 trên firewall để nó chỉ chấp nhận kết nối từ địa chỉ của đường hầm đó. Điều đó biến daemon SSH của bạn thành thứ mà internet không thể nhìn thấy, một kết quả tốt hơn bất kỳ mức độ gia cố cấu hình nào trên một cổng đang lộ ra ngoài.
Firewall: mặc định từ chối, rồi chỉ mở đúng những gì bạn dùng
Một firewall chỉ có ý nghĩa khi mặc định của nó là từ chối. Cho phép mọi thứ rồi mới chặn những cổng đã biết là xấu là làm ngược: bạn chỉ bảo vệ được những dịch vụ mà mình nhớ, còn để lộ ra những dịch vụ mình quên mất. Hãy từ chối toàn bộ lưu lượng đến, cho phép lưu lượng đi, rồi mở từng cổng riêng lẻ khi bạn triển khai những thứ thực sự cần đến chúng. Linux hiện đại dùng nftables ở bên dưới, còn ufw hay firewalld chỉ là những giao diện phía trước hoàn toàn ổn cho nó — công cụ nào quan trọng ít hơn nhiều so với việc mặc định là gì.
- Cho phép SSH trước khi bạn bật firewall, không phải sau. Đây là cách phổ biến thứ hai khiến bạn tự khóa mình ở ngoài.
- Chỉ mở những cổng mà một dịch vụ thực sự cần từ bên ngoài. Một web server cần 80 và 443; một cơ sở dữ liệu thì hầu như không bao giờ cần gì cả.
- Bind các dịch vụ chỉ dùng nội bộ vào 127.0.0.1 thay vì 0.0.0.0. Một cổng đã đóng và một dịch vụ không bao giờ lắng nghe công khai là hai lớp bảo vệ độc lập, và bạn muốn có cả hai.
- Viết quy tắc cho cả IPv6 lẫn IPv4. Một bộ quy tắc chỉ bao phủ v4 trên một cỗ máy chạy dual-stack sẽ để nguyên dịch vụ đó mở toang trên địa chỉ v6 của nó.
- Giới hạn các cổng quản trị theo địa chỉ nguồn bất cứ khi nào có thể. Nếu việc quản trị luôn luôn đến từ một endpoint VPN duy nhất, hãy ghi rõ điều đó trong quy tắc.
- Đọc lại các quy tắc sau mỗi lần thêm một dịch vụ. Những cổng từng mở cho thứ gì đó mà bạn đã gỡ bỏ từ lâu chính là sự tích tụ âm thầm phá hỏng một khởi đầu sạch sẽ.
Một số khối lượng công việc lại đảo ngược logic đó và cần một cổng mở toang một cách cố ý — một Tor relay phải chấp nhận kết nối từ bất cứ đâu, còn một node Bitcoin đầy đủ chỉ phục vụ được các peer nếu cổng 8333 có thể truy cập được. Điều đó hoàn toàn ổn. Quy tắc ở đây không phải là "không mở gì cả", mà là "mở một cách có chủ đích", và một dịch vụ được thiết kế để công khai là một lựa chọn có chủ đích.
fail2ban, và vì sao nó quan trọng ít hơn bạn nghĩ
fail2ban theo dõi log của bạn và ban các địa chỉ liên tục xác thực thất bại. Nó thực sự hữu ích, nhưng cũng đáng để thành thật về việc nó làm được gì một khi bạn đã tắt xác thực bằng mật khẩu: lúc đó không ai có thể thành công bằng cách đoán mò nữa, nên fail2ban không còn ngăn chặn một cuộc đột nhập nào cả. Thứ nó ngăn chặn là hàng nghìn dòng log vô nghĩa mỗi ngày, phần CPU mà các lượt kết nối đó tiêu tốn, và nguy cơ một sự kiện thật sự bị chôn vùi trong mớ nhiễu mà bạn đã ngừng đọc từ nhiều tháng trước.
Dù vậy vẫn đáng bỏ ra mười giây để thiết lập, và nó trở nên thực sự hữu ích ngay khi bạn chạy thứ gì đó có chấp nhận mật khẩu — một trang đăng nhập ứng dụng web, một mail server, một control panel. Hãy trỏ nó vào những log đó thay vì chỉ trỏ vào sshd. Đặt khoảng thời gian ban tính bằng giờ thay vì bằng phút, và thêm địa chỉ của chính bạn vào danh sách bỏ qua để một lần gõ nhầm mật khẩu không khóa bạn ở ngoài chính cỗ máy của mình.
Những bản cập nhật bạn không cần phải nhớ
Mối đe dọa thực tế đối với một server đã được cấu hình tốt không phải là ai đó đánh bại được khóa SSH của bạn. Đó là một lỗ hổng được công bố cho thứ gì đó bạn đã cài rồi quên mất, bị một scanner khai thác ba ngày sau đó trong lúc bạn đang bận việc khác. Cập nhật bảo mật tự động chính là câu trả lời, và trên Debian hay Ubuntu đó là unattended-upgrades được cấu hình để cài riêng phần bảo mật; trên Fedora, Rocky hay Alma đó là dnf-automatic. Hãy bật nó lên ngay trong mười phút đầu tiên, và cỗ máy sẽ tiếp tục tự vá lỗi rất lâu sau khi sự chú ý của bạn đã chuyển sang nơi khác.
Các bản cập nhật kernel và libc là ngoại lệ vẫn cần đến bạn: chúng chỉ có hiệu lực sau khi khởi động lại, nên một server đã chạy liên tục bốn trăm ngày gần như chắc chắn đang chạy mã đã được vá trên đĩa từ cả năm trước. needrestart của Debian sẽ cho bạn biết dịch vụ nào đang chạy dựa trên các thư viện đã bị xóa, và một khung giờ khởi động lại theo lịch — dù chỉ mỗi tháng một lần — chính là khác biệt giữa bản vá đã được cài và bản vá đã thực sự có hiệu lực. Dù sao thì mọi thứ bạn chạy cũng nên sống sót qua một lần khởi động lại bất ngờ; nếu không, đó là một vấn đề khác đáng để sửa riêng.
Những rò rỉ danh tính mà một checklist gia cố bỏ sót
Đây là phần quan trọng nếu bạn cố ý chọn một host offshore, không KYC. Một hướng dẫn gia cố tiêu chuẩn được viết cho một server công ty mà chủ sở hữu là thông tin công khai, nên nó không bao giờ đặt câu hỏi cấu hình mặc định đang ghi lại những gì về bạn. Trên một cỗ máy bạn thuê một cách ẩn danh, một vài giá trị mặc định đó lại âm thầm gắn tên bạn trở lại vào nó.
- Khóa công khai SSH của bạn mang theo một comment — mặc định là username cục bộ và hostname laptop của bạn, kiểu như alex@alex-macbook — và comment đó được lưu nguyên văn trong authorized_keys trên server. Hãy đặt nó bằng cờ -C khi tạo khóa, hoặc sửa lại dòng đó sau khi đã sao chép.
- Hostname server mà bạn chọn sẽ xuất hiện trong log, trong header email, trong dữ liệu giám sát và đôi khi trong banner của dịch vụ. Một hostname chung chung không tiết lộ điều gì; còn tên bạn hay tên công ty bạn thì có.
- Múi giờ hệ thống. Các image cloud mặc định là UTC, thứ không tiết lộ gì cho ai cả. Đặt nó về múi giờ địa phương của bạn sẽ thu hẹp phạm vi nơi bạn đang ở, và dấu thời gian trong mọi log sau đó sẽ xác nhận luôn cả giờ giấc làm việc của bạn.
- Cấu hình Git được sao chép lên máy, thứ mang theo tên và địa chỉ email mà bạn dùng để commit. File lịch sử shell, dotfiles đồng bộ từ máy trạm của bạn, và bất kỳ thông tin đăng nhập nào bị cache lại trong một lần test vội cũng vậy.
- Địa chỉ email bạn đưa cho Let's Encrypt khi xin chứng chỉ, thứ trở thành một phần của hồ sơ công khai cho chứng chỉ đó. Hãy dùng một địa chỉ không gắn với danh tính của bạn.
- Banner phiên bản của web server và header X-Powered-By, cùng với bất kỳ công cụ analytics, crash reporter hay agent giám sát nào của nhà cung cấp âm thầm gửi dữ liệu về từ cỗ máy đó kèm theo một định danh tài khoản.
Đáng để giữ các lớp này tách bạch rõ ràng. Gia cố giữ người lạ tránh xa khỏi cỗ máy. Những chi tiết này giữ cho cỗ máy không mô tả lại bạn với bất kỳ ai đang nhìn vào nó. Còn lớp thanh toán quyết định liệu có từng tồn tại một cái tên để tìm ra hay không — một chủ đề được bàn thẳng thắn trong liệu mua VPS bằng Bitcoin có thực sự ẩn danh hay không, và được đẩy xa hơn nữa bởi việc nạp tiền bằng Monero. Mỗi lớp tự nó đều có thể thất bại; nhưng cùng nhau, chúng đứng vững.
Sao lưu: phần việc mà gia cố không thể làm thay bạn
Không quy tắc firewall nào bảo vệ được bạn trước một cơ sở dữ liệu bị xóa, một ổ đĩa hỏng hay một thay đổi cấu hình từng có vẻ hợp lý vào thời điểm đó. Sao lưu là biện pháp kiểm soát duy nhất giúp bạn phục hồi sau chính những sai lầm do mình gây ra — và xét về mặt thống kê, đó chính là cách phổ biến nhất khiến bạn mất dữ liệu trên một cỗ máy đã được bảo mật tốt. Hãy mã hóa chúng trước khi chúng rời khỏi server, giữ ít nhất một bản sao ở nơi mà chính server đó không thể chạm tới, và đặt lịch để chúng tự chạy thay vì chờ đến khi bạn nhớ ra.
Điểm cuối đó quan trọng hơn vẻ ngoài của nó: một quy trình sao lưu mà server có thể ghi đè lên chính là một bản sao lưu mà bất cứ thứ gì có quyền root trên server đó cũng có thể phá hủy. Đẩy các archive đã mã hóa sang một máy chủ storage riêng biệt — hoặc kéo chúng về từ đó, để thông tin xác thực không nằm trên chính cỗ máy đang được sao lưu — cho bạn một bản sao sống sót qua cả cỗ máy gốc. Và hãy thử khôi phục một lần, một cách chủ động, ngay khi mọi thứ vẫn đang ổn. Một bản sao lưu chưa từng được kiểm thử chỉ là một giả thuyết, không phải một lưới an toàn.
Những sai lầm âm thầm phá hỏng mọi công sức
- Tắt xác thực bằng mật khẩu trước khi thử nghiệm khóa, rồi phát hiện ra sai lầm đó từ một chiếc laptop không còn đăng nhập được nữa.
- Bật firewall trước khi cho phép SSH — cùng một kiểu bị khóa ngoài, chỉ là đến từ hướng ngược lại.
- Chỉ viết quy tắc cho IPv4, và để nguyên mọi dịch vụ có thể truy cập được qua địa chỉ IPv6 của cỗ máy.
- Gia cố cẩn thận ngay ngày đầu tiên, rồi sau đó cài một control panel, một cơ sở dữ liệu và một stack giám sát mà mỗi thứ đều tự mở cổng riêng của nó mà không ai yêu cầu.
- Chạy mọi thứ bằng root chỉ vì đỡ phải gõ thêm sudo, để rồi lỗi đầu tiên trong bất kỳ thứ gì cũng trở thành một cuộc chiếm quyền toàn diện.
- Coi fail2ban như vật thay thế cho khóa, khiến trò chơi đoán mật khẩu vẫn tiếp diễn, chỉ là chậm hơn một chút.
- Cho rằng một server đi thuê có thể được giấu kín khỏi nhà cung cấp host chỉ bằng cách mã hóa ổ đĩa — mã hóa toàn ổ đĩa chỉ bảo vệ bạn trước một ổ đĩa bị đánh cắp, chứ không phải một ổ đĩa đang chạy.
- Không bao giờ khởi động lại, khiến nhiều tháng bản vá kernel đã cài đặt cứ nằm im trên đĩa trong khi kernel cũ vẫn tiếp tục chạy.
Không điều gì trong số này khó, và cũng không điều gì mất nhiều thời gian. Hãy làm theo đúng thứ tự, chứng minh từng bước từ một terminal thứ hai trước khi đi tiếp, và cỗ máy bạn vừa triển khai vài phút trước sẽ thôi là một cơ hội cho bất kỳ ai đang quét qua cả dải địa chỉ. Sau đó hãy triển khai bất cứ thứ gì bạn thực sự đến đây để chạy — một website, một node, một đường hầm, một endpoint model riêng tư — trên một nền tảng mà bạn có thể nắm rõ và suy luận được.