Trong hướng dẫn này, bạn sẽ học cách bảo mật SSH bằng Fail2Ban trên Ubuntu 20.04.

SSH là phương thức kết nối mặc định với máy chủ đám mây. Nó bền vững và có khả năng mở rộng, khi các tiêu chuẩn mã hóa mới được phát triển, chúng có thể được sử dụng để tạo SSH key mới, đảm bảo rằng giao thức cốt lõi vẫn an toàn.
Tuy nhiên, không có giao thức hay hệ thống phần mềm nào hoàn toàn không có lỗ hổng, và việc SSH được triển khai rộng rãi trên internet đồng nghĩa với việc nó trở thành một bề mặt tấn công hoặc vector tấn công rất dễ đoán, nơi mà kẻ xấu có thể tìm cách xâm nhập.
Bất kỳ dịch vụ nào được mở ra trên mạng đều có thể trở thành mục tiêu tấn công theo cách này. Nếu bạn xem lại log của dịch vụ SSH đang chạy trên một máy chủ có nhiều lưu lượng truy cập, bạn sẽ thấy các nỗ lực đăng nhập lặp đi lặp lại, có hệ thống, thể hiện các đợt tấn công brute force do cả người dùng lẫn bot thực hiện.
Mặc dù bạn có thể tối ưu dịch vụ SSH để giảm khả năng thành công của các cuộc tấn công này xuống gần như bằng 0, chẳng hạn như vô hiệu hóa xác thực bằng mật khẩu để thay thế bằng SSH key thì chúng vẫn có thể gây ra rủi ro nhỏ và liên tục.
Trong các hệ thống triển khai sản xuất quy mô lớn, nơi mà rủi ro này hoàn toàn không thể chấp nhận được, người ta thường triển khai một VPN như WireGuard trước dịch vụ SSH, để ngăn việc kết nối trực tiếp vào cổng SSH mặc định 22 từ internet bên ngoài nếu không có lớp trừu tượng hoặc cổng kết nối bổ sung. Những giải pháp VPN này được sử dụng rộng rãi, nhưng sẽ làm tăng độ phức tạp và có thể phá vỡ một số chức năng tự động hóa hoặc các hook phần mềm nhỏ khác.
Trước khi triển khai đầy đủ VPN hoặc kết hợp song song với nó, bạn có thể sử dụng một công cụ có tên là Fail2ban. Fail2ban có thể giảm thiểu đáng kể các cuộc tấn công brute force bằng cách tạo ra các quy tắc tự động thay đổi cấu hình tường lửa để chặn các địa chỉ IP cụ thể sau một số lần đăng nhập thất bại. Điều này cho phép máy chủ của bạn tự tăng cường bảo mật chống lại những nỗ lực truy cập này mà không cần bạn phải can thiệp.
Điều kiện tiên quyết
Để hoàn tất hướng dẫn này, bạn sẽ cần:
- Một máy chủ Ubuntu 20.04 và một người dùng không phải
rootcó quyềnsudo. Bạn có thể tìm hiểu thêm về cách thiết lập người dùng với các quyền này trong hướng dẫn Cài đặt máy chủ ban đầu với Ubuntu 20.04. - (Tùy chọn) Một máy chủ thứ hai để bạn có thể kết nối tới máy chủ đầu tiên, dùng để kiểm tra chức năng chặn.
Bước 1: Cài đặt Fail2ban
Fail2ban có sẵn trong kho phần mềm của Ubuntu. Bắt đầu bằng cách chạy các lệnh sau với tư cách người dùng không phải root để cập nhật danh sách gói và cài đặt Fail2ban:
sudo apt update
sudo apt install fail2ban
Sau khi cài đặt, Fail2ban sẽ tự động thiết lập một dịch vụ chạy nền. Tuy nhiên, dịch vụ này bị vô hiệu hóa theo mặc định, vì một số thiết lập mặc định của nó có thể gây ra những tác động không mong muốn. Bạn có thể kiểm tra bằng cách sử dụng lệnh systemctl:
systemctl status fail2ban.service
Output
○ fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; disabled; vendor preset: enabled
Active: inactive (dead)
Docs: man:fail2ban(1)
Bạn có thể kích hoạt Fail2ban ngay lập tức, nhưng trước hết, bạn sẽ cần xem lại một số tính năng của nó.
Bước 2: Cấu hình Fail2ban
Dịch vụ Fail2ban lưu các tệp cấu hình trong thư mục /etc/fail2ban. Có một tệp mặc định có tên là jail.conf. Chuyển tới thư mục đó và in ra 20 dòng đầu tiên của tệp này bằng head -20:
cd /etc/fail2ban
head -20 jail.conf
Output
#
# WARNING: heavily refactored in 0.9.0 release. Please review and
# customize settings for your setup.
#
# Changes: in most of the cases you should not modify this
# file, but provide customizations in jail.local file,
# or separate .conf files under jail.d/ directory, e.g.:
#
# HOW TO ACTIVATE JAILS:
#
# YOU SHOULD NOT MODIFY THIS FILE.
#
# It will probably be overwritten or improved in a distribution update.
#
# Provide customizations in a jail.local file or a jail.d/customisation.local.
# For example to change the default bantime for all jails and to enable the
# ssh-iptables jail the following (uncommented) would appear in the .local file.
# See man 5 jail.conf for details.
#
# [DEFAULT]
Như bạn thấy, một số dòng đầu tiên của tệp này bị chú thích, chúng bắt đầu bằng ký tự #, cho biết đây là phần tài liệu tham khảo chứ không phải thiết lập. Bạn cũng thấy các chú thích này hướng dẫn không chỉnh sửa trực tiếp tệp này. Thay vào đó, bạn có hai lựa chọn: hoặc là tạo các cấu hình riêng lẻ cho Fail2ban trong nhiều tệp trong thư mục jail.d/, hoặc là tạo và tập hợp tất cả thiết lập cục bộ của bạn trong tệp jail.local. Tệp jail.conf sẽ được cập nhật định kỳ khi Fail2ban được cập nhật, và sẽ được dùng làm nguồn cho các thiết lập mặc định mà bạn chưa ghi đè.
Trong hướng dẫn này, bạn sẽ tạo jail.local. Bạn có thể thực hiện bằng cách sao chép jail.conf:
sudo cp jail.conf jail.local
Bây giờ bạn có thể bắt đầu thực hiện thay đổi cấu hình. Mở tệp trong nano hoặc trình soạn thảo văn bản ưa thích của bạn:
sudo nano jail.local
Khi bạn cuộn qua tệp, hướng dẫn này sẽ xem xét một số tùy chọn mà bạn có thể muốn cập nhật. Các thiết lập nằm trong phần [DEFAULT] gần đầu tệp sẽ được áp dụng cho tất cả dịch vụ mà Fail2ban hỗ trợ. Ở các phần khác trong tệp có các tiêu đề như [sshd] và các dịch vụ khác, chứa các thiết lập cụ thể sẽ ghi đè lên mặc định.
/etc/fail2ban/jail.local
[DEFAULT]
. . .
bantime = 10m
. . .
Tham số bantime đặt khoảng thời gian mà một client bị cấm khi họ xác thực thất bại. Giá trị này được tính bằng giây. Theo mặc định, nó được đặt là 10 phút.
/etc/fail2ban/jail.local
[DEFAULT]
. . .
findtime = 10m
maxretry = 5
. . .
Hai tham số tiếp theo là findtime và maxretry. Chúng phối hợp với nhau để xác định điều kiện mà một client bị coi là người dùng không hợp lệ cần bị cấm.
Biến maxretry đặt số lần thử mà một client có thể xác thực trong một khoảng thời gian do findtime định nghĩa trước khi bị cấm. Với thiết lập mặc định, dịch vụ Fail2ban sẽ cấm một client nếu họ đăng nhập thất bại 5 lần trong vòng 10 phút.
/etc/fail2ban/jail.local
[DEFAULT]
. . .
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
. . .
Nếu bạn cần nhận email cảnh báo khi Fail2ban thực hiện hành động, bạn nên xem xét các thiết lập destemail, sender và mta. Tham số destemail chỉ định địa chỉ email sẽ nhận thông báo cấm. Tham số sender đặt giá trị cho trường “From” trong email. Tham số mta cấu hình dịch vụ mail nào sẽ dùng để gửi thư. Theo mặc định, đây là sendmail, nhưng bạn cũng có thể sử dụng Postfix hoặc một giải pháp khác (nếu muốn).
/etc/fail2ban/jail.local
[DEFAULT]
. . .
action = $(action_)s
. . .
Tham số này cấu hình hành động mà Fail2ban thực hiện khi muốn ban. Giá trị action_ được định nghĩa ngay trước đó trong tệp. Hành động mặc định là cập nhật cấu hình tường lửa để từ chối lưu lượng từ host vi phạm cho tới khi hết thời gian cấm.
Có một số script action_ khác được cung cấp sẵn mà bạn có thể thay thế $(action_) bằng:
/etc/fail2ban/jail.local
…
# ban & send an e-mail with whois report to the destemail.
action_mw = %(action_)s
%(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(action_)s
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(action_)s
xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
%(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
…
Ví dụ, action_mw thực hiện hành động và gửi email, action_mwl thực hiện hành động, gửi email và bao gồm log, còn action_cf_mwl làm tất cả những việc trên, đồng thời gửi cập nhật tới API Cloudflare liên kết với tài khoản của bạn để chặn kẻ tấn công ở đó.
Thiết lập Jail riêng lẻ
Tiếp theo là phần trong tệp cấu hình liên quan tới từng dịch vụ riêng biệt. Chúng được xác định bằng các tiêu đề như [sshd].
Mỗi phần cần được bật riêng bằng cách thêm dòng enabled = true dưới tiêu đề, cùng với các thiết lập khác.
/etc/fail2ban/jail.local
[jail_to_enable]
. . .
enabled = true
. . .
Theo mặc định, dịch vụ SSH được bật còn các dịch vụ khác bị tắt. Một số thiết lập khác trong phần này là:
filter: được dùng để quyết định xem một dòng trong log có phải là xác thực thất bại khônglogpath: cho Fail2ban biết log của dịch vụ đó nằm ở đâu.
Giá trị filter thực tế tham chiếu tới một tệp trong thư mục /etc/fail2ban/filter.d, với phần mở rộng .conf đã bị loại bỏ. Các tệp này chứa các biểu thức chính quy (regular expressions, một cách viết tắt phổ biến để phân tích văn bản) để xác định xem một dòng log có phải là lần xác thực thất bại không. Trong hướng dẫn này, chúng ta sẽ không đi sâu vào các tệp đó, vì chúng khá phức tạp và thiết lập sẵn đã khớp tốt với các dòng log thích hợp.
Tuy nhiên, bạn có thể xem có những filter nào sẵn có bằng cách liệt kê thư mục đó:
ls /etc/fail2ban/filter.d
Nếu bạn thấy một tệp liên quan tới dịch vụ bạn đang dùng, bạn nên mở nó bằng trình soạn thảo. Hầu hết các tệp đều được chú thích đầy đủ và bạn có thể ít nhất hiểu được điều kiện mà script được thiết kế để bảo vệ là gì. Hầu hết các filter này đều có phần tương ứng (tắt mặc định) trong tệp jail.conf, và bạn có thể bật chúng trong jail.local nếu muốn.
Ví dụ, giả sử bạn đang chạy một website bằng Nginx và phát hiện một phần được bảo vệ bằng mật khẩu trên site đang bị tấn công đăng nhập dồn dập. Bạn có thể yêu cầu Fail2ban sử dụng tệp nginx-http-auth.conf để kiểm tra tình trạng này trong tệp /var/log/nginx/error.log.
Phần này thực tế đã được cấu hình sẵn trong một section tên là [nginx-http-auth] trong tệp /etc/fail2ban/jail.conf. Bạn chỉ cần thêm tham số enabled:
/etc/fail2ban/jail.local
. . .
[nginx-http-auth]
enabled = true
. . .
Khi đã chỉnh sửa xong, lưu và đóng tệp. Tại thời điểm này, bạn có thể bật dịch vụ Fail2ban để nó tự động chạy từ bây giờ. Trước tiên, chạy systemctl enable:
sudo systemctl enable fail2ban
Sau đó, khởi động nó thủ công lần đầu bằng systemctl start:
sudo systemctl start fail2ban
Bạn có thể xác minh rằng nó đang chạy bằng systemctl status:
sudo systemctl status fail2ban
Output
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enab>
Active: active (running) since Tue 2022-06-28 19:29:15 UTC; 3s ago
Docs: man:fail2ban(1)
Main PID: 39396 (fail2ban-server)
Tasks: 5 (limit: 1119)
Memory: 12.9M
CPU: 278ms
CGroup: /system.slice/fail2ban.service
└─39396 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
Jun 28 19:29:15 fail2ban20 systemd[1]: Started Fail2Ban Service.
Jun 28 19:29:15 fail2ban20 fail2ban-server[39396]: Server ready
Trong bước tiếp theo, bạn sẽ thực hành kiểm chứng Fail2ban trong thực tế.
Bước 3: Kiểm thử các chính sách chặn (Tùy chọn)
Từ một máy chủ khác, máy này về sau sẽ không cần đăng nhập vào máy chủ Fail2ban, bạn có thể kiểm thử các quy tắc bằng cách để máy chủ thứ hai đó bị chặn. Sau khi đăng nhập vào máy chủ thứ hai, thử SSH vào máy chủ Fail2ban. Bạn có thể thử kết nối bằng một tên không tồn tại:
ssh blah@your_server
Nhập các ký tự ngẫu nhiên vào phần yêu cầu mật khẩu. Lặp lại vài lần. Đến một lúc nào đó, lỗi mà bạn nhận được sẽ thay đổi từ Permission denied sang Connection refused. Dấu hiệu này cho thấy máy chủ thứ hai của bạn đã bị chặn khỏi máy chủ Fail2ban.
Trên máy chủ Fail2ban, bạn có thể xem quy tắc mới bằng cách kiểm tra output của iptables. iptables là một lệnh dùng để tương tác với các quy tắc cổng và tường lửa ở mức thấp trên máy chủ của bạn. Nếu bạn đã làm theo hướng dẫn thiết lập ban đầu của DigitalOcean, bạn sẽ dùng ufw để quản lý quy tắc tường lửa ở mức cao hơn. Chạy iptables -S sẽ hiển thị tất cả các quy tắc tường lửa mà ufw đã tạo:
sudo iptables -S
Output
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N f2b-sshd
-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
…
Nếu bạn chuyển output của iptables -S sang grep để tìm kiếm chuỗi f2b trong các quy tắc đó, bạn sẽ thấy những quy tắc đã được Fail2ban thêm vào:
sudo iptables -S | grep f2b
Output
-N f2b-sshd
-A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd
-A f2b-sshd -s 134.209.165.184/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-sshd -j RETURN
Dòng chứa REJECT --reject-with icmp-port-unreachable đã được Fail2ban thêm vào và sẽ phản ánh đúng địa chỉ IP của máy chủ thứ hai của bạn.
Kết luận
Giờ đây bạn đã có thể cấu hình một số chính sách chặn cho các dịch vụ của mình. Fail2ban là một giải pháp hữu ích để bảo vệ bất kỳ dịch vụ nào sử dụng xác thực. Nếu bạn muốn tìm hiểu thêm về cách Fail2ban hoạt động, bạn có thể tham khảo hướng dẫn của chúng tôi về cách hoạt động của các quy tắc và tệp Fail2ban.