DevOps

SSH hardening nâng cao trên Ubuntu 24.04: policy, AllowUsers và audit

SSH hardening nâng cao

Sau khi đã biết kết nối SSH bằng key, quản lý user/sudobật firewall nền, bước tiếp theo là đưa SSH từ mức “đăng nhập được” lên mức “chịu được internet”. Một VPS public sẽ luôn bị quét port, thử user phổ biến, thử mật khẩu yếu và bị bot đụng đến mỗi ngày. Vì vậy, SSH hardening nâng cao không nên chỉ dừng ở việc tắt root login hoặc đổi port cho yên tâm.

Bài SSH hardening nâng cao: policy, allowlist users và audit đi theo hướng production-ready tối thiểu cho Ubuntu 24.04 LTS: có policy rõ ràng, cấu hình bằng file riêng trong sshd_config.d, dùng allowlist user hoặc group, tắt các kiểu đăng nhập không cần thiết, kiểm tra bằng sshd -tsshd -T, giữ phiên SSH dự phòng, rồi đọc log để audit sau thay đổi.

Mục tiêu không phải là tạo một file SSH config “cứng nhất có thể”. Mục tiêu là cấu hình đủ chặt để giảm rủi ro, nhưng vẫn đủ thực tế để bạn không tự khóa chính mình khỏi VPS, không phá workflow deploy, không làm team mất quyền truy cập hợp lệ và có đường rollback rõ ràng khi cần.

1. Hiểu đúng về SSH hardening nâng cao

1.1. SSH hardening không chỉ là đổi port 22

Đổi port SSH từ 22 sang một port khác có thể giảm bớt log noise từ bot quét tự động, nhưng đây không phải là lớp bảo mật chính. Nếu server vẫn cho đăng nhập bằng mật khẩu yếu, vẫn cho root login, vẫn không giới hạn user được phép SSH, thì đổi port chỉ là “giấu cửa”, không phải khóa cửa.

SSH hardening đúng hơn nên bắt đầu từ policy:

  • Ai được phép SSH vào server?
  • Đăng nhập bằng phương thức nào?
  • Root có được SSH trực tiếp không?
  • User deploy có cần shell đầy đủ không?
  • Có cần SSH forwarding không?
  • Khi có login fail hoặc login thành công, xem log ở đâu?
  • Nếu cấu hình sai, rollback bằng cách nào?

Khi trả lời được các câu hỏi này, file cấu hình SSH sẽ ngắn hơn, dễ audit hơn và ít phụ thuộc vào mẹo vặt hơn.

1.2. Vì sao phải hardening SSH sau các bài nền tảng?

SSH là cánh cửa quản trị VPS. Nếu mất SSH, bạn có thể phải dùng rescue console, VNC, snapshot restore hoặc thậm chí reinstall server. Nếu SSH bị lộ, kẻ tấn công có thể đọc mã nguồn, lấy database credential, sửa Nginx config, cài backdoor, đào coin hoặc xóa dữ liệu.

Ở các bài trước, bạn đã có nền tảng: key-based login, user sudo, permission, UFW và cập nhật tự động. Bài C1 sẽ siết lại SSH theo hướng có kiểm soát hơn: chỉ cho đúng user hoặc đúng group đăng nhập, tắt root login, tắt password login, ghi log đủ để audit, và test bằng phiên SSH mới trước khi đóng phiên cũ.

1.3. Không nên copy một file sshd_config “hardened” từ internet

Nhiều cấu hình SSH trên internet có thể quá cũ, quá chặt hoặc không phù hợp với Ubuntu 24.04 LTS. Một số file tắt forwarding, tắt PAM, ép cipher/MAC/KexAlgorithms theo danh sách cũ, đổi port, đổi banner, giới hạn user, chặn group và chỉnh timeout cùng lúc. Nếu copy nguyên file như vậy lên VPS production, bạn rất dễ tự khóa hoặc làm hỏng workflow deploy.

Cách an toàn hơn là giữ cấu hình mặc định của Ubuntu càng nhiều càng tốt, chỉ thêm các directive thật sự cần vào một file riêng trong /etc/ssh/sshd_config.d/, rồi kiểm tra effective config bằng sshd -T.

2. Policy SSH nên có trước khi chỉnh cấu hình

2.1. Mô hình policy tối thiểu cho VPS cá nhân

Với một VPS cá nhân hoặc blog tự host, policy tối thiểu có thể là:

  • Không SSH trực tiếp bằng root.
  • Chỉ một hoặc hai user admin được phép SSH.
  • Chỉ cho đăng nhập bằng SSH key.
  • Tắt password login.
  • Tắt empty password.
  • Không bật forwarding nếu không cần.
  • Log đủ chi tiết để biết key nào vừa đăng nhập.
  • Luôn test bằng phiên SSH mới trước khi logout phiên cũ.

Policy này đã đủ tốt cho phần lớn VPS nhỏ nếu bạn kết hợp với UFW, cập nhật bảo mật tự động và backup.

2.2. Mô hình policy cho team nhỏ

Nếu VPS có nhiều người cùng quản trị, nên dùng group để quản lý thay vì ghi từng user rải rác trong nhiều file.

Ví dụ:

  • Group ssh-login: user được phép SSH.
  • Group sudo: user được phép dùng quyền admin.
  • Group deploy: user dùng cho deploy app, không nhất thiết có sudo.
  • Offboarding: khi một người rời team, xóa SSH key và remove khỏi group.

Với team, AllowGroups thường dễ vận hành hơn AllowUsers. Tuy nhiên, vì nhiều VPS cá nhân chỉ có một vài user, bài này sẽ hướng dẫn cả hai hướng: allowlist theo user và allowlist theo group. Bạn chỉ nên chọn một hướng chính để tránh tự làm rối cấu hình.

2.3. Những gì không nên chỉnh nếu chưa có lý do rõ

Không phải directive nào trong sshd_config cũng cần đụng đến. Với người tự host VPS, nên tránh chỉnh các nhóm sau nếu chưa thật sự hiểu:

  • Ciphers, MACs, KexAlgorithms: dễ copy danh sách cũ hoặc vô tình loại bỏ client hợp lệ.
  • UsePAM: tắt sai có thể ảnh hưởng login, session và policy hệ thống.
  • Subsystem sftp: sửa sai có thể làm hỏng SFTP/SCP workflow.
  • ChrootDirectory: mạnh nhưng dễ lỗi permission nếu chưa hiểu.
  • Đổi port SSH và bật firewall cùng lúc mà không có console dự phòng.

Tư duy đúng là hardening từng lớp, không tối ưu mù.

3. Chuẩn bị chống tự khóa trước khi hardening SSH

3.1. Mở ít nhất hai phiên SSH

Trước khi sửa SSH, hãy mở hai terminal SSH vào server. Một phiên dùng để chỉnh cấu hình, một phiên giữ nguyên để cứu nếu cấu hình mới lỗi.

ssh admin@SERVER_IP

Ở terminal thứ hai:

ssh admin@SERVER_IP

Không đóng phiên cũ cho đến khi bạn đã test đăng nhập thành công bằng phiên mới sau khi reload/restart SSH.

3.2. Kiểm tra quyền sudo của user hiện tại

whoami
id
sudo -v
sudo -l

Nếu user hiện tại không có sudo, bạn không nên tiếp tục. Một cấu hình SSH sai khi không có quyền sudo để sửa sẽ khiến rollback khó hơn rất nhiều.

3.3. Kiểm tra console/rescue từ nhà cung cấp VPS

Trước khi hardening, hãy chắc chắn bạn biết cách vào VPS bằng console của provider, VNC, rescue system hoặc snapshot restore. Không phải lúc nào SSH cũng là đường vào duy nhất, nhưng khi SSH lỗi, bạn phải biết đường dự phòng nằm ở đâu.

Nếu VPS đang chạy production thật, nên chụp snapshot trước khi chỉnh SSH, nhất là khi bạn chuẩn bị tắt password login hoặc thay đổi allowlist user.

3.4. Backup cấu hình SSH hiện tại

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M%S)
sudo tar czf "$HOME/ssh-config-backup-$(date +%F-%H%M%S).tar.gz" /etc/ssh

Kiểm tra:

ls -lh "$HOME"/ssh-config-backup-*.tar.gz
ls -lh /etc/ssh/sshd_config.bak.*

3.5. Kiểm tra config hiện tại trước khi chỉnh

sudo sshd -t
sudo sshd -T | sort | less

sshd -t kiểm tra cú pháp. sshd -T in ra effective configuration sau khi OpenSSH đọc file chính và các file include. Đây là cách tốt nhất để biết cấu hình thật sự đang có hiệu lực, thay vì chỉ nhìn một dòng trong file rồi đoán.

4. Audit hiện trạng SSH trước khi thay đổi

4.1. Kiểm tra SSH đang listen ở đâu

sudo ss -tulpn | grep -E ':22|sshd|ssh' || true
sudo systemctl status ssh --no-pager
sudo systemctl status ssh.socket --no-pager || true

Tùy image Ubuntu và provider, bạn có thể thấy SSH được quản lý bởi service ssh, socket ssh.socket, hoặc cả hai. Đừng quá phụ thuộc vào một lệnh duy nhất. Hãy kiểm tra cả service, socket và port đang listen.

4.2. Kiểm tra user có thể SSH

getent passwd | awk -F: '$7 ~ /(bash|sh|zsh)$/ {print $1 ":" $7}'
getent group sudo
getent group ssh-login || true

Lệnh này giúp bạn nhìn nhanh các user có shell đăng nhập. Không phải user có shell là chắc chắn được SSH, nhưng đây là điểm bắt đầu tốt để audit.

4.3. Kiểm tra root login và password login hiện tại

sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|authenticationmethods|permitemptypasswords'

Nếu thấy permitrootlogin yes hoặc passwordauthentication yes, bạn nên siết lại trước khi đưa server ra production. Tuy nhiên, đừng tắt password login cho đến khi key-based login đã được test thành công bằng một phiên SSH mới.

4.4. Kiểm tra log đăng nhập gần đây

sudo journalctl -u ssh --since "24 hours ago" --no-pager | tail -n 100

Nếu hệ thống có /var/log/auth.log, kiểm tra thêm:

sudo grep -E 'sshd.*(Accepted|Failed|Invalid user|Disconnected)' /var/log/auth.log | tail -n 100 || true

Đây là bước giúp bạn biết server có đang bị brute force, có user lạ đăng nhập thành công, hoặc có nhiều thử nghiệm vào root/admin hay không.

5. Tạo allowlist user hoặc group cho SSH

5.1. Cách 1: Dùng AllowUsers cho VPS ít user

Nếu server chỉ có một hoặc hai admin, AllowUsers rất dễ hiểu. Ví dụ chỉ cho user admindeploy SSH:

AllowUsers admin deploy

Có thể giới hạn theo IP hoặc hostname pattern:

AllowUsers [email protected].* deploy

Lưu ý: nếu bạn dùng IP động tại nhà, giới hạn theo IP có thể tự khóa bạn khi mạng đổi IP. Với VPS cá nhân, chỉ dùng allowlist IP khi bạn thật sự kiểm soát được IP nguồn hoặc có VPN cố định.

5.2. Cách 2: Dùng AllowGroups cho team

Tạo group:

sudo groupadd --force ssh-login

Thêm user hiện tại vào group:

sudo usermod -aG ssh-login "$USER"

Nếu có user khác:

sudo usermod -aG ssh-login deploy
sudo usermod -aG ssh-login admin

Kiểm tra:

getent group ssh-login
id "$USER"

Với group, cấu hình SSH sẽ dùng:

AllowGroups ssh-login

Cách này dễ offboarding hơn. Khi một user không còn được SSH, chỉ cần remove khỏi group hoặc khóa user.

5.3. Không nên dùng AllowUsers và AllowGroups lung tung cùng lúc

Có thể dùng cả AllowUsersAllowGroups, nhưng khi làm vậy, user phải thỏa điều kiện cấu hình tương ứng. Với người mới, điều này dễ gây nhầm: user nằm trong group nhưng vẫn không login được vì không nằm trong AllowUsers, hoặc ngược lại.

Khuyến nghị thực tế:

  • VPS cá nhân: dùng AllowUsers.
  • Team nhỏ: dùng AllowGroups.
  • Không dùng cả hai nếu chưa có lý do rõ ràng.

6. Tạo file SSH hardening riêng trong sshd_config.d

6.1. Vì sao nên dùng file riêng?

Thay vì sửa toàn bộ /etc/ssh/sshd_config, bạn nên tạo file riêng trong /etc/ssh/sshd_config.d/. Cách này giúp dễ đọc, dễ backup, dễ rollback và ít đụng vào file mặc định của package.

Tạo file:

sudo nano /etc/ssh/sshd_config.d/99-devnook-hardening.conf

6.2. Mẫu cấu hình cho VPS cá nhân dùng AllowUsers

Nếu bạn chọn allowlist theo user, dùng mẫu sau và thay admin, deploy theo user thật trên server:

# DevNook SSH hardening - personal VPS
# Test with: sudo sshd -t && sudo sshd -T

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey
PermitEmptyPasswords no

AllowUsers admin deploy

MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

X11Forwarding no
PermitUserEnvironment no
LogLevel VERBOSE

Nếu user của bạn không phải admin hoặc deploy, hãy sửa lại trước khi lưu. Sai AllowUsers là một trong những cách tự khóa phổ biến nhất.

6.3. Mẫu cấu hình cho team dùng AllowGroups

Nếu bạn chọn allowlist theo group:

# DevNook SSH hardening - team VPS
# Test with: sudo sshd -t && sudo sshd -T

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey
PermitEmptyPasswords no

AllowGroups ssh-login

MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

X11Forwarding no
PermitUserEnvironment no
LogLevel VERBOSE

Trước khi dùng mẫu này, chắc chắn user hiện tại đã nằm trong group ssh-login:

id "$USER"
getent group ssh-login

6.4. Có nên tắt AllowTcpForwarding và AllowAgentForwarding không?

Hai directive này liên quan đến SSH tunnel và agent forwarding. Nếu không dùng, bạn có thể tắt để giảm bề mặt rủi ro:

AllowTcpForwarding no
AllowAgentForwarding no

Tuy nhiên, đừng tắt mù quáng nếu workflow của bạn cần SSH tunnel để kết nối database qua localhost, hoặc cần agent forwarding cho deploy qua Git private repository. Với VPS cá nhân, bạn có thể bắt đầu chưa thêm hai dòng này, sau đó audit workflow thật rồi siết tiếp.

Một hướng an toàn hơn là tắt mặc định, rồi mở lại cho user/group cụ thể bằng Match. Phần đó sẽ được nói ở mục 8.

6.5. Kiểm tra cú pháp ngay sau khi lưu

sudo sshd -t

Nếu có lỗi, không reload SSH. Mở lại file vừa tạo và sửa đúng dòng lỗi.

7. Kiểm tra effective config trước khi reload SSH

7.1. Dùng sshd -T để xem cấu hình thật sự có hiệu lực

sudo sshd -T | grep -E 'permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|authenticationmethods|allowusers|allowgroups|maxauthtries|logingracetime|clientalive|x11forwarding|permituserenvironment|loglevel'

Kết quả mong đợi nếu dùng AllowUsers:

permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
authenticationmethods publickey
allowusers admin deploy
maxauthtries 3
logingracetime 30
x11forwarding no
permituserenvironment no
loglevel VERBOSE

Kết quả mong đợi nếu dùng AllowGroups:

allowgroups ssh-login

7.2. Kiểm tra theo user cụ thể bằng -C

Khi có Match hoặc nhiều điều kiện, có thể kiểm tra config theo user/host/address:

sudo sshd -T -C user=admin,host=example.com,addr=127.0.0.1 | grep -E 'allowusers|allowgroups|passwordauthentication|permitrootlogin|allowtcpforwarding|allowagentforwarding'

Lệnh này hữu ích khi bạn muốn biết user admin thật sự đang chịu policy nào sau tất cả include và match block.

7.3. Reload hoặc restart SSH đúng cách

Với thay đổi SSH, reload thường đủ nếu service hỗ trợ:

sudo systemctl reload ssh || sudo systemctl restart ssh

Kiểm tra trạng thái:

sudo systemctl status ssh --no-pager
sudo journalctl -u ssh --since "5 minutes ago" --no-pager

Nếu hệ thống có ssh.socket, kiểm tra thêm:

sudo systemctl status ssh.socket --no-pager || true

7.4. Test phiên SSH mới trước khi đóng phiên cũ

Mở terminal mới từ máy cá nhân và test key login:

ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no admin@SERVER_IP

Nếu login thành công, kiểm tra user:

whoami
id
sudo -v

Tiếp theo, test password login bị từ chối:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no admin@SERVER_IP

Kết quả mong đợi là không đăng nhập được bằng password. Chỉ sau khi test thành công bằng phiên mới, bạn mới nên đóng phiên SSH cũ.

8. Policy nâng cao bằng Match block

8.1. Khi nào cần Match block?

Match cho phép áp policy khác nhau theo user, group, host hoặc địa chỉ nguồn. Đây là phần nâng cao, chỉ nên dùng khi cấu hình global không đủ.

Ví dụ:

  • User admin được SSH đầy đủ.
  • User deploy không được forwarding.
  • Group ssh-restricted bị tắt X11 và agent forwarding.
  • Một user chỉ được login từ IP cố định.

8.2. Ví dụ Match User cho deploy

Thêm cuối file 99-devnook-hardening.conf:

Match User deploy
    X11Forwarding no
    AllowTcpForwarding no
    AllowAgentForwarding no
    PermitTTY yes

Kiểm tra:

sudo sshd -t
sudo sshd -T -C user=deploy,host=example.com,addr=127.0.0.1 | grep -E 'x11forwarding|allowtcpforwarding|allowagentforwarding|permittty'

8.3. Ví dụ Match Address cho IP quản trị cố định

Nếu bạn có VPN hoặc IP quản trị cố định, có thể dùng allowlist theo địa chỉ nguồn. Ví dụ chỉ cho user admin từ dải IP cụ thể:

AllowUsers [email protected].* deploy

Không nên dùng cách này nếu IP nhà mạng của bạn thay đổi thường xuyên. Nếu IP đổi, bạn có thể bị khóa khỏi server dù key vẫn đúng.

8.4. Không lạm dụng Match block

Match rất mạnh nhưng cũng làm file cấu hình khó đọc hơn. Với VPS cá nhân, hầu hết trường hợp chỉ cần policy global rõ ràng. Chỉ thêm Match khi bạn có nhu cầu thật, có test bằng sshd -T -C, và có ghi chú trong tài liệu vận hành.

9. Audit SSH sau hardening

9.1. Xem login thành công

sudo journalctl -u ssh --since "24 hours ago" --no-pager | grep -E 'Accepted|session opened' || true

Nếu có /var/log/auth.log:

sudo grep -E 'sshd.*Accepted' /var/log/auth.log | tail -n 50 || true

Với LogLevel VERBOSE, log có thể ghi thêm thông tin liên quan public key fingerprint khi đăng nhập. Điều này giúp audit key nào vừa được dùng, đặc biệt hữu ích khi nhiều người cùng có quyền SSH.

9.2. Xem login thất bại và user lạ

sudo journalctl -u ssh --since "24 hours ago" --no-pager | grep -E 'Failed|Invalid user|authentication failure|Connection closed' | tail -n 100 || true

Hoặc:

sudo grep -E 'sshd.*(Failed|Invalid user|authentication failure)' /var/log/auth.log | tail -n 100 || true

Nếu bạn thấy rất nhiều thử nghiệm vào root, admin, test, ubuntu, điều đó khá phổ biến với VPS public. Lúc này, tắt password login, tắt root login, allowlist user và dùng Fail2ban ở bài C2 sẽ giúp giảm rủi ro đáng kể.

9.3. Xem lịch sử đăng nhập bằng last

last -a | head -n 30

Lệnh này cho biết các phiên đăng nhập gần đây. Đây không thay thế log SSH chi tiết, nhưng rất hữu ích để rà nhanh thời điểm và IP đăng nhập.

9.4. Tạo alias audit nhanh

Có thể tạo một script nhỏ để đọc log SSH nhanh hơn:

sudo nano /usr/local/sbin/ssh-audit-quick.sh

Nội dung:

#!/usr/bin/env bash
set -euo pipefail

SINCE="${1:-24 hours ago}"

echo "== SSH service status =="
systemctl status ssh --no-pager || true

echo
echo "== Accepted logins =="
journalctl -u ssh --since "$SINCE" --no-pager | grep -E 'Accepted|session opened' || true

echo
echo "== Failed / invalid attempts =="
journalctl -u ssh --since "$SINCE" --no-pager | grep -E 'Failed|Invalid user|authentication failure' | tail -n 100 || true

echo
echo "== Recent sessions =="
last -a | head -n 20

Cấp quyền:

sudo chmod +x /usr/local/sbin/ssh-audit-quick.sh

Chạy:

sudo ssh-audit-quick.sh "24 hours ago"

10. Có nên đổi port SSH không?

10.1. Đổi port giúp giảm log noise, không phải lớp bảo mật chính

Đổi port SSH có thể làm log bớt dày vì nhiều bot chỉ quét port 22. Tuy nhiên, port mới vẫn có thể bị phát hiện bằng scan. Nếu password login vẫn bật hoặc user vẫn yếu, đổi port không giải quyết gốc rễ.

Thứ tự đúng nên là:

  • Key-based login hoạt động.
  • Root login bị tắt.
  • Password login bị tắt.
  • User/group allowlist rõ ràng.
  • UFW chỉ mở đúng port cần thiết.
  • Fail2ban hoặc lớp chống brute force được cấu hình nếu cần.
  • Sau đó mới cân nhắc đổi port để giảm noise.

10.2. Nếu đổi port, phải xử lý firewall trước

Ví dụ muốn đổi SSH sang port 2222, trước tiên mở firewall:

sudo ufw allow 2222/tcp
sudo ufw status verbose

Thêm vào file hardening:

Port 2222

Kiểm tra:

sudo sshd -t
sudo systemctl reload ssh || sudo systemctl restart ssh

Test phiên mới:

ssh -p 2222 admin@SERVER_IP

Chỉ khi port mới hoạt động, mới cân nhắc xóa rule port cũ. Không đóng port 22 trước khi port mới được test thành công từ máy ngoài.

10.3. Cập nhật SSH client config

Trên máy cá nhân, có thể thêm vào ~/.ssh/config:

Host my-vps
    HostName SERVER_IP
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Sau đó đăng nhập bằng:

ssh my-vps

11. Rollback khi SSH hardening lỗi

11.1. Nếu vẫn còn phiên SSH cũ

Nếu phiên cũ còn mở nhưng phiên mới login không được, rollback file hardening:

sudo mv /etc/ssh/sshd_config.d/99-devnook-hardening.conf /etc/ssh/sshd_config.d/99-devnook-hardening.conf.disabled
sudo sshd -t
sudo systemctl reload ssh || sudo systemctl restart ssh

Test lại bằng phiên mới:

ssh admin@SERVER_IP

11.2. Nếu lỗi do AllowUsers hoặc AllowGroups

Mở lại file:

sudo nano /etc/ssh/sshd_config.d/99-devnook-hardening.conf

Kiểm tra user hiện tại:

whoami
id
getent group ssh-login || true

Sửa AllowUsers hoặc thêm user vào group:

sudo usermod -aG ssh-login admin

Kiểm tra và reload:

sudo sshd -t
sudo systemctl reload ssh || sudo systemctl restart ssh

11.3. Nếu không còn phiên SSH nào

Lúc này cần dùng console/rescue của nhà cung cấp VPS. Quy trình thường là:

  • Mở VNC/console/rescue từ panel provider.
  • Đăng nhập bằng user local hoặc mount disk trong rescue mode.
  • Đổi tên file hardening bị lỗi trong /etc/ssh/sshd_config.d/.
  • Kiểm tra sshd -t.
  • Restart SSH hoặc reboot server.

Đây là lý do bài này nhấn mạnh: luôn giữ phiên SSH cũ và biết đường vào console trước khi chỉnh SSH.

12. Lỗi thường gặp khi SSH hardening nâng cao

12.1. Tắt password login khi key chưa hoạt động

Đây là lỗi phổ biến nhất. Trước khi đặt PasswordAuthentication no, hãy test:

ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no admin@SERVER_IP

Nếu lệnh này chưa login được, đừng tắt password.

12.2. Sai user trong AllowUsers

Nếu user thật là ubuntu nhưng bạn cấu hình:

AllowUsers admin

thì user ubuntu sẽ không login được nữa. Kiểm tra user hiện tại bằng:

whoami
getent passwd admin ubuntu deploy

12.3. Dùng AllowGroups nhưng quên thêm user vào group

Kiểm tra:

id admin
getent group ssh-login

Thêm user:

sudo usermod -aG ssh-login admin

Sau đó test phiên SSH mới. Lưu ý session hiện tại có thể chưa cập nhật group mới cho chính user đang đăng nhập, nhưng SSH login mới sẽ đọc group membership mới.

12.4. Chỉnh file xong restart ngay mà không chạy sshd -t

Luôn chạy:

sudo sshd -t

Nếu lệnh này báo lỗi, không reload/restart SSH. Sửa config trước.

12.5. Quên rằng cấu hình có thể bị ghi đè hoặc không có hiệu lực như bạn nghĩ

Đừng chỉ đọc file. Hãy xem effective config:

sudo sshd -T | grep -E 'passwordauthentication|permitrootlogin|allowusers|allowgroups'

Nếu output không giống kỳ vọng, hãy kiểm tra thứ tự include, file khác trong sshd_config.d hoặc directive trùng lặp.

12.6. Tắt forwarding làm hỏng workflow deploy

Nếu deploy đang cần SSH agent forwarding hoặc tunnel, tắt AllowAgentForwarding hoặc AllowTcpForwarding có thể làm workflow lỗi. Trước khi tắt, hãy kiểm tra pipeline deploy, Git access và cách bạn kết nối database qua SSH tunnel.

12.7. Tin rằng Fail2ban thay thế được SSH hardening

Fail2ban rất hữu ích, nhưng không thay thế được key-based login, tắt password, tắt root và allowlist user. Fail2ban là lớp phản ứng theo log; SSH hardening là lớp giảm bề mặt tấn công ngay từ đầu.

13. Checklist SSH hardening nâng cao

13.1. Checklist trước khi chỉnh

  • Đã có ít nhất hai phiên SSH đang mở.
  • Đã biết cách vào console/rescue của provider.
  • User hiện tại có sudo.
  • Key-based login đã hoạt động.
  • Đã backup /etc/ssh.
  • sudo sshd -t đang thành công trước khi chỉnh.

13.2. Checklist cấu hình

  • PermitRootLogin no.
  • PubkeyAuthentication yes.
  • PasswordAuthentication no.
  • KbdInteractiveAuthentication no.
  • AuthenticationMethods publickey.
  • AllowUsers hoặc AllowGroups rõ ràng.
  • PermitEmptyPasswords no.
  • MaxAuthTriesLoginGraceTime được giảm hợp lý.
  • LogLevel VERBOSE để hỗ trợ audit key login.

13.3. Checklist kiểm tra sau reload

  • sudo sshd -t thành công.
  • sudo sshd -T hiển thị đúng effective config.
  • Phiên SSH mới login bằng key thành công.
  • Login bằng password bị từ chối.
  • Root không SSH trực tiếp được.
  • journalctl -u ssh không có lỗi mới.
  • Đã đọc log Accepted/Failed sau khi test.

13.4. Checklist audit định kỳ

  • Rà user có shell login.
  • Rà group ssh-login hoặc danh sách AllowUsers.
  • Xóa SSH key của người không còn cần truy cập.
  • Kiểm tra login lạ trong journalctl hoặc auth.log.
  • Kiểm tra port SSH đang mở trong UFW.
  • Đảm bảo snapshot/backup vẫn còn khả dụng trước thay đổi lớn.

14. FAQ

14.1. Có nên tắt root SSH login không?

Có. Với VPS production, không nên SSH trực tiếp bằng root. Cách tốt hơn là dùng user admin riêng, đăng nhập bằng key, rồi dùng sudo khi cần quyền cao hơn. Điều này giúp giảm rủi ro và dễ audit hơn.

14.2. Có nên tắt password login không?

Có, sau khi key-based login đã được test thành công. Đừng tắt password login khi bạn chưa chắc SSH key hoạt động, chưa có phiên dự phòng hoặc chưa biết cách vào console provider.

14.3. Nên dùng AllowUsers hay AllowGroups?

VPS cá nhân ít user có thể dùng AllowUsers. Team nhỏ hoặc môi trường có nhiều người nên dùng AllowGroups để quản lý dễ hơn. Không nên dùng cả hai cùng lúc nếu bạn chưa hiểu rõ tác động.

14.4. Có nên đổi port SSH khỏi 22 không?

Có thể, nhưng đây không phải lớp bảo mật chính. Đổi port giúp giảm log noise, còn bảo mật thật vẫn nằm ở key-based login, tắt root/password login, allowlist user/group, firewall và audit log.

14.5. Có nên chỉnh Ciphers, MACs, KexAlgorithms không?

Không nên chỉnh nếu chưa có yêu cầu compliance hoặc lý do rõ ràng. OpenSSH hiện đại đã có mặc định tương đối tốt và liên tục loại bỏ thuật toán yếu. Copy danh sách cipher cũ từ internet có thể làm giảm bảo mật hoặc phá tương thích.

14.6. Log SSH nên xem ở đâu trên Ubuntu?

Ưu tiên dùng journalctl -u ssh. Nếu hệ thống có /var/log/auth.log, có thể grep thêm trong file này. Khi dùng LogLevel VERBOSE, log sẽ hữu ích hơn cho việc audit key đăng nhập.

14.7. Sau bài này nên học gì tiếp?

Sau SSH hardening nâng cao, bước tiếp theo hợp lý là cấu hình Fail2ban cho SSH và Nginx. SSH hardening giúp giảm bề mặt tấn công, còn Fail2ban giúp phản ứng tự động với các hành vi brute force dựa trên log thật.

15. Kết luận

SSH hardening nâng cao không phải là một file cấu hình càng dài càng tốt. Một cấu hình tốt cần có policy rõ ràng, ít thay đổi nhưng đúng trọng tâm: không root login, không password login, chỉ đúng user hoặc group được SSH, kiểm tra bằng sshd -t, xác nhận effective config bằng sshd -T, test phiên SSH mới trước khi đóng phiên cũ, và đọc log sau mỗi thay đổi.

Trong bài này, bạn đã có một workflow thực tế cho Ubuntu 24.04 LTS: backup cấu hình SSH, audit hiện trạng, chọn AllowUsers hoặc AllowGroups, tạo file hardening riêng trong sshd_config.d, reload an toàn, test public key login, xác nhận password/root login bị chặn, và đọc log bằng journalctl hoặc auth.log.

Khi SSH được hardening đúng cách, VPS của bạn có một lớp phòng thủ nền vững hơn rất nhiều. Đây là bước chuyển quan trọng từ “server chạy được” sang “server vận hành được”. Từ đây, bạn có thể tiếp tục với Fail2ban, backup, monitoring, logging và troubleshooting playbook để hoàn thiện nhóm Security + Ops cho toàn bộ series.

Đừng bỏ lỡ

Theo dõi bản tin mới nhất tại đây

Chào bạn 👋
Rất vui được làm quen.

Đăng ký để nhận nội dung hấp dẫn mỗi tháng qua email.

Bằng việc đăng ký, bạn đồng ý với Chính sách bảo mật của DevNook.

Tác giả

Tuấn Lê

Tại DevNook, mình chia sẻ kiến thức thực chiến, kinh nghiệm làm sản phẩm và những công cụ hữu ích giúp bạn làm việc hiệu quả hơn mỗi ngày.