Hệ điều hành (OS), Linux

10 Nguyên Tắc Bảo Mật Linux Thực Chiến Nhất Cho Production Server

Nhớ lại cách đây một vài năm, tôi đã từng nhận được một cuộc gọi vào lúc gần 2 giờ sáng để xử lý sự cố cho một website bán hàng của khách bị hack. Hacker không xóa dữ liệu, không thay đổi giao diện của trang web. Họ chỉ lặng lẽ cài một backdoor nhỏ trong server và dùng nó để gửi spam, đào coin, và pivot sang các hệ thống khác. Điều đáng nói là: Server đó đã được cấu hình và bật firewall, đã đổi port SSH, đã disable root login. Thực tế thì chỉ cần một cấu hình nhỏ trong hệ thống Linux Server sai vậy toàn bộ production server vẫn bị xuyên thủng.

Sau hơn 20 năm làm vận hành & quản trị hệ thống và triển khai phát triển các hạ tầng Networks, Servers System, ứng dụng dịch vụ từ đơn giản đến phức tạp trong môi trường thực tế cho doanh nghiệp, tôi rút ra một điều:

80% servers bị hack không phải vì zero-day.
Mà vì những lỗi cấu hình rất cơ bản mà người quản trị hay quản lý “ có thể chủ quan và nghĩ là như vậy đã ổn rồi ”.

Trong bài viết này, tôi không nói về lý thuyết bảo mật.
Tôi chỉ chia sẻ 10 nguyên tắc bảo mật Linux thực chiến nhất mà tôi luôn áp dụng cho các production servers thật — những nguyên tắc giúp bạn giảm ngay 80–90% rủi ro bị tấn công mà trong khi bạn chỉ cần mất một vài giờ chịu khó ngồi cấu hình server.

Nếu bạn đang vận hành Linux server cho website, API, ERP, hay bất kỳ hệ thống production nào,
thì bài viết này..tôi nghĩ rằng có thể giúp bạn tránh được một cuộc gọi vào lúc 2 giờ sáng giống như tôi đã từng nhận.

Vậy chúng ta hãy bắt đầu với nguyên tắc đầu tiên nhé!

1. Vô hiệu hóa đăng nhập trực tiếp bằng root – Phải làm

Vì cổng SSH là tuyến đầu của cuộc chiến, đừng để nó mở toang cho kẻ địch. Trên Linux server nói chung, SSH thường cho phép đăng nhập bằng mật khẩu và đôi khi cả root user. Do vậy việc đầu tiên và quan trọng nhất là cấm cho phép đăng nhập SSH trực tiếp với tài khoản root. Tài khoản root có toàn quyền trên hệ thống Linux, nên cũng là mục tiêu ưa thích của tin tặc – như để ngỏ cửa hậu vậy. Vậy chúng ta không cho phép root login trực tiếp trong file cấu hình /etc/ssh/sshd_config

Cách thực hiện: chúng ta mở file cấu hình SSH:

sudo nano /etc/ssh/sshd_config

Trong file này, tìm và thêm dòng sau:

PermitRootLogin no

Điều này có nghĩa là dù ai đó có biết mật khẩu root, cũng sẽ không thể SSH vào server trực tiếp với quyền root.

Tiếp theo, bạn nên tắt tính năng socket activation của SSH để tránh hiện tượng dịch vụ tự động bật tắt không kiểm soát:

sudo systemctl disable --now ssh.socket

Sau đó, đảm bảo dịch vụ SSH được bật và khởi động lại:

sudo systemctl enable ssh
sudo systemctl restart ssh

Mình luôn ưu tiên sự rõ ràng: “mỗi dịch vụ – một nhiệm vụ” để dễ kiểm soát và dễ kiểm tra (audit) hệ thống.

Chuyển sang SSH Key thay vì mật khẩu

Ngay sau khi chặn quyền đăng nhập của root, chúng ta không dùng mật khẩu nữa, mà chuyển sang xác thực bằng SSH key – như dùng cặp khóa bí mật và công khai. Trên máy client dành cho việc quản trị hệ thống, hãy tạo key mới:

ssh-keygen -t ed25519

Sau đó, copy public key lên server:

ssh-copy-id admin@server_ip # ví dụ: ssh-copy-id admin@192.168.146.4

Giải thích nhanh: file id_ed25519 là private key (không được chia sẻ cho bất cứ ai!), còn id_ed25519.pub là public key được phép upload lên Linux Server.

Bây giờ chúng ta có thể đăng nhập mà không cần mật khẩu, đơn giản chỉ cần sử dụng lệnh sau (nhớ thay đổi IP trong lệnh dưới bằng IP của Linux server của bạn):

ssh admin@192.168.146.4

Đầu tiên hệ thống sẽ yêu cầu mật khẩu của private key trên máy bạn (nếu bạn đặt mật khẩu), nhưng sau đó sẽ sử dụng cặp key để xác thực.

Đổi cổng SSH – giảm quét tự động

Theo mặc định dịch vụ SSH của Linux Server dùng cổng 22, đây là mục tiêu bị quét tự động nhiều nhất trên Internet. Chúng ta đổi sang một cổng khác, ví dụ cổng 2222:

sudo nano /etc/ssh/sshd_config

Trong file cấu hình SSH, sửa dòng Port:

Port 2222

Xác nhận lại cấu hình:

sudo sshd -T | grep port
sudo systemctl restart ssh

Sau đó, thử login từ client với cổng 2222:

ssh myuser@192.168.146.4 -p 2222

Việc này không hẳn khiến server “bất khả xâm phạm” , nhưng sẽ giảm được đến một mức VD trên 90% các bot quét tự động trên Internet – do hầu hết chúng chỉ dò cổng 22.

Tắt hoàn toàn đăng nhập bằng mật khẩu

Sau khi SSH key đã được thiết lập xong như trong bước trên, nên tắt hẳn việc đăng nhập bằng mật khẩu. Mở lại file SSH config:

sudo nano /etc/ssh/sshd_config

Tìm dòng cấu hình PasswordAuthentication và sửa như sau (nếu không thấy dòng này hãy thêm vào dòng như bên dưới):

# Đổi thành:
PasswordAuthentication yes

Sau đó khởi động lại SSH để dịch vụ nhận cấu hình mới:

sudo systemctl restart ssh

Từ giờ chỉ các key hợp lệ mới vào được server, cơ bản cắt đứt cách tấn công brute-force thông qua mật khẩu.

2. Nguyên tắc ít đặc quyền – Chỉ cấp quyền vừa đủ

Hệ thống chỉ cho phép người dùng có quyền cần thiết nhất, ít nhất có thể. Mỗi người chỉ được phép làm đúng việc mình cần. Để làm điều này, ta chỉnh sửa cấu hình file sudoers qua visudo:

sudo visudo

Ví dụ, nếu có user chỉ cần quyền khởi động lại Apache, chúng ta giới hạn cho user này chỉ dùng đúng lệnh đó:

myuser ALL=(ALL) /usr/bin/systemctl restart apache2
app_runner ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/myapp.log

Giải thích ví dụ myuser ALL=(ALL) /usr/bin/systemctl restart apache2:

  • myuser: Là user được cấp quyền

  • ALL: Được áp dụng trên mọi host

  • (ALL): user này được chạy lệnh với quyền root

  • /usr/bin/systemctl restart apache2: chỉ lệnh duy nhất mà user được phép chạy với quyền root.

Sau khi lưu lại cấu hình xong, hãy test thử xem có giống như cấu hình mong muốn hay không: Đăng nhập với myuser, chạy lệnh cho phép:

su - myuser
sudo systemctl restart apache2

Lệnh sẽ chạy thành công do lệnh này chúng ta đã cấu hình cấp phép. Nếu user thử chạy các lệnh khác VD như:

sudo systemctl stop apache2

Chúng ta sẽ thấy kết quả báo bị cấm chạy lệnh và báo lỗi – chứng tỏ chúng ta đã phân quyền chính xác.

Lưu ý nguy hiểm không nên áp dụng cấu hình này: không bao giờ viết cấu hình myuser ALL=(ALL) ALL trong sudoers! Câu lệnh đó biến user thành “root trá hình”, cực kỳ nguy hiểm vì cấp cho user mọi quyền trong Linux Server.

Ngoài ra, theo mặc định, Linux không ghi lại đầy đủ mọi lệnh sudo mà user chạy, khiến việc:

  • Điều tra sự cố

  • Kiểm tra an toàn hệ thống

  • Truy vết xem ai đã chạy các lệnh nguy hiểm ảnh hưởng xấu đến hệ thống

  • Phân tích vấn đề production gặp khó khăn.

Vì thế, hãy bật việc ghi log sudo trong môi trường Production Server:

Defaults logfile="/var/log/sudo.log"

Bất kỳ lệnh nào chạy qua quyềnsudo sẽ được lưu vào file /var/log/sudo.log. Để kiểm tra, bạn có thể chạy thử một lệnh sudo:

sudo ls /root
sudo cat /var/log/sudo.log

Nội dung file log sẽ có dòng tương tự thể hiện việc ghi tất cả các logs:

Bây giờ các bạn có thể thấy chúng ta đã có nhật ký log rõ ràng, để biết ai chạy lệnh gì, vào lúc nào.

3. Thường xuyên cập nhật hệ thống

Rất nhiều server bị hacker xâm nhập chỉ vì quá lâu không cập nhật hệ thống Servers. Lỗi bảo mật của phần mềm thường được nhà phát triển vá khi cập nhật, nên chúng ta phải thường xuyên phải chạy:

sudo apt update && sudo apt upgrade -y

Mình có thể diễn giải với bạn theo kinh nghiệm hơn 20 năm của mình: Nếu không cập nhật Server, chúng ta như không có được một tuyến phòng thủ mới nhất. Nhiều hệ thống bị tổn hại bởi virus hay hackers thực ra rất đơn giản là chỉ vì quên quét và cập nhật các bản vá lỗi. Hãy coi việc cập nhật định kỳ cho hệ thống như “tiêm vắc-xin” cho server, tăng cường các bản vá lỗi phần mềm giúp cho server có “hệ miễn dịch tốt hơn”.

4. Quản lý tài khoản người dùng – Tránh “tài khoản ma”

Trên các server tồn tại chạy một thời gian khá dài, thường có thể có nhiều tài khoản gồm các users không còn sử dụng hoặc bị lãng quên. Mỗi tài khoản dư thừa là một “cánh cửa phụ” có thể bị hacker lợi dụng. Ví dụ, khi người cũ nghỉ việc hay users của khách hàng cũ của công ty mà admin quên xóa tài khoản của họ.

Giải pháp: định kỳ kiểm tra danh sách các users và xóa hoặc khóa các tài khoản này. Ví dụ, liệt kê tất cả user với lệnh:

cut -d: -f1 /etc/passwd

Nếu thấy user cũ không dùng nữa, xóa chúng:

sudo userdel -r old_user

và khóa các tài khoản dịch vụ (service accounts) không cần có quyền đăng nhập vào server:

sudo usermod -s /sbin/nologin service_account

Một lời cảnh báo: “Tài khoản bị lãng quên có thể trở thành cánh cửa hậu cho hacker.” Trong thực tế có nhiều vụ tai nạn như do vô ý xóa các files quan trọng, hay tắt dịch vụ sai do quyền sudo quá rộng đều xuất phát từ việc quá nhiều tài khoản và quyền không có kiểm soát. Hãy coi việc quản lý tài khoản như dọn dẹp vệ sinh hệ thống, luôn loại bỏ “tài khoản ma” để giảm rủi ro.

5. Tắt các dịch vụ không dùng

Một nguyên nhân rất phổ biến nữa khiến server bị tấn công là chạy quá nhiều dịch vụ dư thừa. Mỗi dịch vụ đang chạy là một cổng mở ra cho hacker vào. Vì vậy, hãy check danh sách các dịch vụ đang chạy và tắt những dịch vụ không cần thiết, dư thừa:

systemctl list-units --type=service --state=running
ss -tulnp

Sau đó, nếu thấy dịch vụ không dùng, tắt nó ngay. Ví dụ, server không cần các dịch vụ như avahi-daemon hay cups, chúng ta chạy lệnh sau để disable:

sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now cups

Lưu ý: Tắt dịch vụ không dùng sẽ:

  • Giảm bề mặt tấn công (attack surface) – hacker có ít ngách tấn công hơn

  • Tiết kiệm tài nguyên máy chủ

  • Giúp hệ thống ổn định hơn, và dễ quản lý

  • best practice trong hardening Linux

Tóm lại, bất cứ dịch vụ nào “không rõ đang làm gì, chưa dùng đến” thì chúng ta cần đóng gói lại cho nó gọn gàng cho hệ thống của chúng ta chạy mượt hơn.

6. Firewall – Chỉ mở các cổng cần thiết

Luật an toàn mạng cổ điển: Chỉ cho phép các cổng dịch vụ thực sự cần thiết được mở. Ví dụ, nếu server của bạn chỉ phục vụ trên các cổng SSH, HTTP và HTTPS, hãy thiết lập firewall (ví dụ dùng UFW) như sau:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp # Mở cổng SSH (gõ đúng cổng bạn đã chọn)
sudo ufw allow 80/tcp # Mở cổng HTTP
sudo ufw allow 443/tcp # Mở cổng HTTPS
sudo ufw enable

Lưu ý, mặc định UFW cho phép mọi kết nối từ bên trong server ra bên ngoài (outgoing) cho tiện. Nhưng trong môi trường production, bạn nên hạn chế hơn: Đó là chặn hết outgoing tức là không cho server truy cập được ra bên ngoài và chỉ mở khi cần. Ví dụ:

sudo ufw default deny outgoing
sudo ufw allow out on lo # Cho phép loopback
sudo ufw allow out 53/udp # DNS
sudo ufw allow out 53/tcp # DNS
sudo ufw allow out 80/tcp # HTTP (cập nhật gói)
sudo ufw allow out 443/tcp # HTTPS
sudo ufw allow out 123/udp # NTP (đồng bộ thời gian)

Như vậy, server chỉ có thể chủ động kết nối ra ngoài đến những dịch vụ thiết yếu, giảm nguy cơ bị mã độc hay attacker sử dụng băng thông vô tội vạ.

Lưu ý: Nhớ kiểm tra kỹ rule: tuyệt đối phải ufw allow ssh rồi mới ufw enable, nếu không bạn sẽ bị khóa luôn cả đường ssh vào server.

7. Chống tấn công dò mật khẩu (Brute-force)

Nếu hệ thống của bạn còn cho phép đăng nhập bằng mật khẩu, nhất thiết phải có cơ chế chống đoán mật khẩu liên tục. Ở đây mình áp dụng PAM module để khóa user sau một vài lần nhập sai mật khẩu. Các bước làm như sau:

  1. Bắt buộc phải chuyển sang quyền root (không dùng sudo):

    sudo -i
  2. Backup file cấu hình PAM mặc định:

    mv /etc/pam.d/common-auth /etc/pam.d/common-auth.bak
  3. Tạo file cấu hình mới:

    nano /etc/pam.d/common-auth
  4. Thêm vào nội dung sau (hệ thống sẽ cài đặt module pam_faillock):

    # 1. Kiểm tra xem user đã bị khoá (thực thi đầu tiên)
    auth required  pam_faillock.so preauth silent deny=5 unlock_time=900
    # 2. Xác thực mật khẩu củauser
    auth [success=1 default=ignore]  pam_unix.so nullok
    # 3. Ghi nhận các lần xác thực thất bại
    auth [default=die]  pam_faillock.so authfail deny=5 unlock_time=900
    # 4. Cho phép tiếp tục xác thực nếu hợp lệ
    auth required  pam_permit.so

    Giải thích ngắn: Sau 5 lần nhập sai liên tiếp, user sẽ bị khóa 900 giây (15 phút) hoặc đến khi admin giải khoá.

  5. Lưu lại và chạy lệnh reset để PAM tạo thư mục theo dõi việc users đăng nhập vào hệ thống:

    faillock --reset
  6. Để test thử, mở file SSH config một lần nữa:

    sudo nano /etc/ssh/sshd_config

    Tìm dòng PasswordAuthentication yes và thêm # ở đầu (đã comment) để tái kích hoạt cho phép đăng nhập ssh bằng password để kiểm tra. Sau đó khởi động lại SSH:

    sudo systemctl restart ssh
  7. Bây giờ, thử SSH vào server với user nào đó, gõ sai mật khẩu 5 lần. Bạn sẽ thấy user bị khóa và không thể đăng nhập được nữa.

  8. Trên máy chủ, kiểm tra:

    faillock --user myuser

    Lệnh trên sẽ hiển thị thông tin user bị khóa.

  9. Nếu muốn mở lại quyền đăng nhập cho user, chạy:

    faillock --user myuser --reset

    User myuser sẽ được bỏ khóa. Kiểm tra lại bằng cách đăng nhập thử với mật khẩu đúng.

Qua quy trình trên, dù hacker cố brute-force dò mật khẩu, sau vài lần sai liên tiếp, họ sẽ bị tự động “bốc hơi” và không thể tiếp tục.

8. Yêu cầu mật khẩu mạnh

Người dùng thường đặt mật khẩu dễ đoán, dễ nhớ (như 123456, password). Để phòng kẻ gian, ta cần ép buộc người dùng phải đặt mật khẩu mạnh. Mở file cấu hình PAM cho việc cấu hình mật khẩu:

sudo nano /etc/pam.d/common-password

Tìm dòng có pam_pwquality.so và sửa thành:

password requisite pam_pwquality.so retry=3 minlen=14 ucredit=-1 lcredit=-1 dcredit=-2 ocredit=-1

Giải thích các tham số chính cho việc đặt mật khẩu của users :

  • minlen=14: ít nhất phải có 14 ký tự

  • ucredit=-1: ít nhất 1 chữ hoa

  • lcredit=-1: ít nhất 1 chữ thường

  • dcredit=-2: ít nhất 2 chữ số

  • ocredit=-1: ít nhất 1 ký tự đặc biệt

  • retry=3: nhập sai mật khẩu có thể thử lại 3 lần trước khi hủy.

Sau đó, hãy kiểm tra. Ví dụ thử test đổi mật khẩu cho một user nào đó:

passwd myuser

Và thử các mật khẩu dưới đây:

  • password123 → ❌ (quá ngắn, chỉ chữ thường và số)

  • Password1234! → ❌ (bị báo thiếu độ dài)

  • Abcdef1234! → ❌ (vẫn chưa đủ ký tự, chỉ 11 ký tự)

  • StrongPass!2024 → ✅ (thỏa mãn trên 14 ký tự, có chữ hoa, chữ thường, chữ số và ký tự đặc biệt)

Quá trình này cho thấy nếu không có việc cấu hình ràng buộc kỹ thuật, người dùng hay tái sử dụng mật khẩu cũ, đặt mật khẩu yếu. Cuối cùng, chính hệ thống phải bắt người dùng tuân thủ – đừng tin vào việc tự nhận thức bảo mật của người dùng!

9. Quản lý chu kỳ thay đổi mật khẩu

Trong nhiều môi trường doanh nghiệp, việc quản lý tuổi thọ mật khẩu thường bị lơ là, nhưng lại rất quan trọng. Ví dụ, nếu ai đó biết mật khẩu cũ, họ có thể chờ thời điểm để truy cập sau này. Vì thế, chúng ta cần cấu hình để bắt buộc phải thay đổi theo định kỳ. Mở file /etc/login.defs:

sudo nano /etc/login.defs

Tìm và chỉnh sửa các giá trị:

PASS_MAX_DAYS 60
PASS_WARN_AGE 7

Ý nghĩa:

  • PASS_MAX_DAYS: mật khẩu sẽ hết hạn sau 60 ngày kể từ lần thay đổi cuối cùng

  • PASS_WARN_AGE: hệ thống sẽ cảnh báo 7 ngày trước khi hết hạn

Ví dụ minh họa:

  • Ngày 1: user đặt mật khẩu mới.

  • Từ ngày 53–59: khi login vào, hệ thống nhắc user cần thay đổi mật khẩu.

  • Đến ngày 60: nếu user chưa đổi mật khẩu, hệ thống sẽ bị buộc phải thay và không thể đăng nhập thêm vào hệ thống được nữa nếu bỏ qua.

Mục tiêu là không để người dùng dùng một “mật khẩu cố định” mãi mãi.

Sau khi cập nhật cấu hình, bạn tạo user thử nghiệm:

sudo adduser test
sudo chage -l test

Lệnh chage -l test sẽ hiển thị chính sách mật khẩu áp dụng, và bạn sẽ thấy password của user test sẽ hết hạn sau 60 ngày, với cảnh báo bắt đầu từ 7 ngày trước. Như vậy, mọi account mới đều được áp dụng quy tắc bắt buộc phải đổi mật khẩu theo định kỳ.

10. Ghi log và tập trung log – Đôi mắt của hệ thống

Cuối cùng nhưng không kém phần quan trọng: Cần phải ghi log đầy đủ và tập trung. Việc không có log thì giống như xem phim mà tắt tiếng – cực kì thiếu thông tin và là lỗ hổng lớn. Linux tự động lưu hầu hết các sự kiện quan trọng trong thư mục /var/log. Ví dụ, file /var/log/auth.log ghi lại tất cả sự kiện liên quan đến xác thực – từ đăng nhập thành công/thất bại đến việc dùng sudo. Hãy thường xuyên theo dõi file này để phát hiện sớm kẻ lạ:

sudo tail -f /var/log/auth.log

Ngoài ra còn có /var/log/syslog (ghi chung nhiều thông tin), /var/log/kern.log (thông tin kernel), /var/log/dmesg… mỗi file như một cuốn “phim tài liệu” ghi chép mọi hoạt động. Bạn cũng có thể dùng công cụ như logwatch hoặc goaccess để tổng hợp và gửi email đến cho bạn hàng ngày.

Một bước nâng cao là chuyển log về một máy chủ log tập trung. Đừng để log chỉ nằm trên server đang bảo vệ: nếu server đó hỏng vật lý chẳng hạn, thì log cũng bị mất đi. Cấu hình rsyslog hoặc systemd-journald để đẩy log về một server chuyên dụng.

Tóm lại, log giống như “phim giám sát” của hệ thống. Hãy đọc kỹ từng log, đặt cảnh báo khi phát hiện bất thường (ví dụ nhiều lần đăng nhập thất bại liên tiếp, truy cập từ IP lạ, hay việc thay đổi cấu hình …), và xử lý kịp thời. Bạn hãy như một thám tử giỏi, bạn sẽ phát hiện ra kẻ đột nhập trước khi chúng kịp gây hại.

Kết luận

Bảo mật không đến từ một lệnh đơn lẻ nào; nó đến từ một tư duy đúng đắn, cấu hình chính xác và vận hành kỷ luật. Hãy tuân thủ nghiêm ngặt bắt đầu với 10 nguyên tắc trên, vì mỗi một nguyên tắc như trong bài viết này ít nhất cũng là một lớp phòng thủ cho server của bạn. Môi trường production không cho phép sơ hở – chỉ cần một lỗ hổng cũng đủ để tạo ra các hậu quả lớn. Nhớ rằng việc củng cố an toàn hệ thống là cả một quá trình liên tục, không chỉ dừng lại sau một ngày làm việc.

Chúc các bạn xây dựng được hệ thống Linux an toàn và mạnh mẽ! Vì sự thành công của bạn!

#LinuxSecurity #UbuntuServer #Sysadmin #DevOps #AnToanHeThong

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *