Bối cảnh và tại sao phải tự động hóa hardening server?
Trong lĩnh vực IT, bảo mật luôn là yếu tố tối quan trọng. Tuy nhiên, thời gian đầu, tôi cũng từng khá chủ quan. Cho đến một đêm định mệnh, khoảng 2 giờ sáng, điện thoại bất ngờ reo liên tục. Mở log ra, tôi hoảng hốt nhận thấy server production đang bị tấn công brute-force SSH dồn dập. Với trái tim đập thình thịch, tôi vội vã gõ lệnh chặn IP, thay đổi port và reset cấu hình. Cả đêm đó tôi thức trắng, chỉ để xử lý một sự cố lẽ ra đã có thể phòng ngừa từ sớm.
Sau trải nghiệm đáng nhớ ấy, tôi nhận ra rằng việc cấu hình bảo mật thủ công trên từng server ẩn chứa rất nhiều rủi ro. Một lỗi nhỏ, dù là quên một bước, gõ nhầm lệnh, hay chỉ đơn giản là sự khác biệt nhỏ giữa các server, đều có thể gây hậu quả nghiêm trọng. Với hệ thống lên đến hàng chục, thậm chí hàng trăm server, việc duy trì sự đồng nhất và đảm bảo tất cả đều được hardening (làm cứng) đúng chuẩn gần như là bất khả thi.
Đó là lúc tôi bắt đầu tìm đến Ansible. Công cụ này không chỉ giúp tôi triển khai cấu hình nhanh chóng, mà còn đảm bảo mọi server – từ mới tinh đến đã hoạt động – đều có cùng một cấu hình bảo mật. Quá trình này diễn ra tự động và có khả năng lặp lại (idempotent), giúp tôi an tâm hơn với một hệ thống được bảo vệ vững chắc khỏi các lỗ hổng cơ bản, thay vì phải thức trắng đêm như trước.
Cài đặt Ansible: Bắt đầu hành trình tự động hóa
Để khởi đầu, bạn cần một máy tính đóng vai trò là Ansible Controller (máy điều khiển) và các Managed Nodes (các server cần được hardening). Điểm đặc biệt của Ansible là không yêu cầu cài đặt agent trên Managed Nodes; thay vào đó, nó sử dụng SSH để kết nối và thực thi lệnh, rất tiện lợi và an toàn.
1. Cài đặt Ansible Controller
Trên máy điều khiển, việc cài đặt Ansible khá đơn giản. Bạn chỉ cần cài đặt Python và pip, sau đó sử dụng pip để cài đặt Ansible. Ví dụ trên Ubuntu, bạn thực hiện các lệnh sau:
sudo apt update
sudo apt install python3 python3-pip -y
pip3 install ansible
Xác nhận Ansible đã cài đặt thành công:
ansible --version
2. Chuẩn bị Managed Nodes
Các server cần hardening chỉ yêu cầu Python (thường có sẵn) và SSH server đang hoạt động. Điều quan trọng nhất là bạn cần thiết lập xác thực SSH bằng khóa (key-based authentication) từ Controller đến các Managed Nodes. Điều này giúp Ansible kết nối mà không cần nhập mật khẩu thủ công.
ssh-keygen -t rsa -b 4096
ssh-copy-id user@your_server_ip
3. Tạo Inventory File
File inventory (hoặc hosts) là nơi bạn định nghĩa các server mà Ansible sẽ quản lý. Nên tổ chức các server thành nhóm để dễ dàng quản lý và áp dụng cấu hình.
[web_servers]
web1.example.com
web2.example.com
[db_servers]
db1.example.com
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_user=your_ssh_username
Trong đó, your_ssh_username là tên người dùng bạn sẽ dùng để SSH vào các server.
Cấu hình chi tiết: playbook hardening từng bước
Đây là phần quan trọng nhất: viết các playbook để tự động hóa quá trình hardening. Thông thường, tôi sẽ tạo một file hardening.yml và gọi các role hoặc task cụ thể bên trong.
1. Bảo mật SSH: Cửa ngõ đầu tiên
Sau sự cố đêm đó, bảo mật SSH trở thành ưu tiên hàng đầu của tôi. Playbook dưới đây sẽ cấu hình các cài đặt SSH cơ bản:
- Vô hiệu hóa đăng nhập bằng tài khoản
root. - Tắt xác thực bằng mật khẩu, chỉ cho phép dùng SSH key.
- Thay đổi port SSH mặc định (khuyến nghị dù là tùy chọn).
# roles/ssh_hardening/tasks/main.yml
- name: Cấu hình SSH Server
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^(PermitRootLogin|PasswordAuthentication|Port)'
line: '{{ item.line }}'
state: present
validate: '/usr/sbin/sshd -t'
loop:
- { regexp: '^PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^Port', line: 'Port 2222' } # Thay 2222 bằng port bạn muốn
notify: Restart sshd
- name: Đảm bảo chỉ user được phép mới có thể SSH
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^AllowUsers'
line: 'AllowUsers your_ssh_username another_user'
state: present
validate: '/usr/sbin/sshd -t'
notify: Restart sshd
# handlers/main.yml (cho role ssh_hardening)
- name: Restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
enabled: yes
Lưu ý quan trọng: Luôn đảm bảo bạn đã có SSH key và user hợp lệ để đăng nhập vào port mới trước khi thực thi playbook này. Nếu không, bạn có thể bị khóa khỏi server!
2. Cấu hình Firewall với UFW
Firewall là tuyến phòng thủ đầu tiên. Trên Ubuntu, tôi thường dùng UFW (Uncomplicated Firewall) vì tính dễ sử dụng của nó. Playbook này sẽ kích hoạt UFW, cho phép các port cần thiết và chặn toàn bộ lưu lượng không mong muốn.
# roles/firewall/tasks/main.yml
- name: Cài đặt UFW
ansible.builtin.apt:
name: ufw
state: present
- name: Cho phép SSH qua port tùy chỉnh (ví dụ 2222)
community.general.ufw:
rule: allow
port: '2222'
proto: tcp
- name: Cho phép HTTP (port 80)
community.general.ufw:
rule: allow
port: '80'
proto: tcp
- name: Cho phép HTTPS (port 443)
community.general.ufw:
rule: allow
port: '443'
proto: tcp
- name: Thiết lập chính sách mặc định là chặn tất cả (deny incoming)
community.general.ufw:
state: enabled
policy: deny
direction: incoming
- name: Bật UFW
community.general.ufw:
state: enabled
3. Quản lý cập nhật và gói phần mềm
Việc giữ cho hệ điều hành và các gói phần mềm luôn được cập nhật là một bước hardening cơ bản nhưng cực kỳ quan trọng. Điều này giúp ngăn chặn các lỗ hổng bảo mật đã được vá, mà nếu bỏ qua có thể trở thành mục tiêu tấn công.
# roles/system_updates/tasks/main.yml
- name: Cập nhật danh sách gói phần mềm
ansible.builtin.apt:
update_cache: yes
- name: Nâng cấp tất cả gói phần mềm lên phiên bản mới nhất
ansible.builtin.apt:
upgrade: dist
autoclean: yes
autoremove: yes
- name: Cài đặt và cấu hình cập nhật tự động (unattended-upgrades)
ansible.builtin.apt:
name: unattended-upgrades
state: present
- name: Bật cập nhật tự động
ansible.builtin.lineinfile:
path: /etc/apt/apt.conf.d/20auto-upgrades
regexp: 'APT::Periodic::Unattended-Upgrade "1"'
line: 'APT::Periodic::Unattended-Upgrade "1";'
state: present
4. Quản lý người dùng và quyền hạn
Nguyên tắc quyền hạn tối thiểu (Principle of Least Privilege) là kim chỉ nam ở đây. Tôi chỉ tạo những tài khoản cần thiết và cấp quyền sudo một cách cẩn trọng.
# roles/user_management/tasks/main.yml
- name: Tạo user mới nếu chưa tồn tại
ansible.builtin.user:
name: mynewadmin
comment: 'Admin User'
group: sudo
shell: /bin/bash
generate_ssh_key: yes
ssh_key_type: rsa
password: '{{ "my_strong_password" | password_hash("sha512") }}'
- name: Thêm SSH public key cho user mới
ansible.builtin.authorized_key:
user: mynewadmin
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- name: Đảm bảo user cũ không cần thiết bị xóa (thay the_old_user_to_remove)
ansible.builtin.user:
name: the_old_user_to_remove
state: absent
remove: yes
ignore_errors: yes # Bỏ qua lỗi nếu user không tồn tại
- name: Cấu hình sudoers cho nhóm sudo (không cần mật khẩu khi dùng sudo)
ansible.builtin.lineinfile:
path: /etc/sudoers.d/90-nopasswd-sudo
line: '%sudo ALL=(ALL) NOPASSWD:ALL'
state: present
create: yes
validate: '/usr/sbin/visudo -cf %s'
Lưu ý: Thay mynewadmin, my_strong_password và the_old_user_to_remove bằng thông tin cụ thể của bạn. Việc dùng password_hash giúp lưu trữ mật khẩu an toàn hơn trong playbook.
5. Tổng hợp Playbook chính (main.yml)
Cuối cùng, bạn sẽ tạo một file hardening.yml chính để gọi các role này lại:
# hardening.yml
---
- name: Thực thi hardening các server Linux
hosts: web_servers, db_servers # Hoặc hosts: all
become: yes # Chạy các lệnh với quyền sudo
roles:
- ssh_hardening
- firewall
- system_updates
- user_management
Kiểm tra và Monitoring: Luôn trong tầm kiểm soát
Triển khai xong không có nghĩa là công việc đã kết thúc. Bạn luôn phải kiểm tra và giám sát để đảm bảo mọi thứ vẫn hoạt động đúng như mong muốn.
1. Kiểm tra trước khi triển khai (Dry Run)
Trước khi chạy playbook thật, tôi luôn chạy thử với cờ --check để xem Ansible sẽ thực hiện những thay đổi nào mà không áp dụng chúng lên server. Đây là bước cứu tôi thoát khỏi nhiều sự cố không mong muốn.
ansible-playbook -i inventory hardening.yml --check
Sau khi xem xét output và thấy mọi thứ ổn, tôi mới chạy thật:
ansible-playbook -i inventory hardening.yml
2. Kiểm tra sau triển khai
Sau khi playbook chạy xong, tôi sẽ SSH vào server để xác nhận lại các thay đổi. Ví dụ:
- Kiểm tra cấu hình SSH:
sudo cat /etc/ssh/sshd_config | grep -E 'PermitRootLogin|PasswordAuthentication|Port|AllowUsers' - Kiểm tra trạng thái UFW:
sudo ufw status verbose - Kiểm tra user:
id mynewadmin
Khi server đã hoạt động, bạn có thể thử SSH vào bằng user và port mới. Hãy đảm bảo user cũ (hoặc root) không thể đăng nhập được nữa. Tôi từng mắc lỗi quên mở port SSH mới trên firewall trước khi đổi port SSH daemon, kết quả là phải dùng console để khắc phục sự cố.
3. Monitoring và Audit định kỳ
Hardening không phải là công việc chỉ làm một lần rồi thôi. Tình hình bảo mật luôn thay đổi, và bạn cần đảm bảo các cấu hình vẫn đúng chuẩn. Tôi thường lên lịch chạy lại playbook hardening định kỳ (ví dụ, hàng tháng) để duy trì tính đồng nhất. Ansible là idempotent nên việc chạy lại sẽ không gây lỗi mà chỉ áp dụng các thay đổi nếu có.
Ngoài ra, tôi cũng tích hợp các công cụ giám sát log (như ELK stack hay Prometheus với Grafana) để theo dõi các sự kiện bảo mật. Các sự kiện này bao gồm đăng nhập thất bại, truy cập bất thường, hay các hành động sudo. Việc này giúp tôi phát hiện sớm các dấu hiệu tấn công hoặc hoạt động đáng ngờ. Tôi cũng kết hợp sử dụng Lynis để audit hệ thống định kỳ, và đôi khi tôi còn tự động hóa việc chạy Lynis qua Ansible để tiện theo dõi các báo cáo.
# Ví dụ task chạy Lynis (thêm vào role system_auditing nếu có)
- name: Cài đặt Lynis
ansible.builtin.apt:
name: lynis
state: present
- name: Chạy Lynis audit và lưu kết quả
ansible.builtin.command: lynis audit system --quick --report-file /var/log/lynis_report.txt
args:
creates: /var/log/lynis_report.txt # Chỉ chạy nếu file report chưa có hoặc muốn chạy lại
Việc tự động hóa hardening server Linux với Ansible đã thay đổi cách tôi làm việc và mang lại sự yên tâm rất lớn. Từ những đêm mất ngủ vì server bị tấn công, giờ đây tôi có thể tự tin rằng các hệ thống của mình đã được bảo vệ một cách nhất quán và hiệu quả. Bạn cũng nên bắt đầu hành trình tự động hóa này càng sớm càng tốt!

