Bảo mật truyền tải tập tin: Tại sao SFTP Chroot Jail lại thiết yếu
Việc cấp quyền truy cập máy chủ cho các đối tác bên ngoài hoặc lập trình viên mới thường giống như việc đưa chìa khóa nhà cho ai đó chỉ để họ sơn lại phòng ngủ phụ. Quyền truy cập SSH tiêu chuẩn quá rộng rãi. Theo mặc định, một người dùng mới có thể xem qua /etc, đọc lén /var/log/auth.log, hoặc thậm chí dò quét các dịch vụ mạng nội bộ. Hình thức di chuyển ngang (lateral movement) này là một rủi ro bảo mật lớn cần phải được ngăn chặn ngay lập tức.
Tôi đã triển khai cấu hình Chroot Jail cụ thể này trên 14 nút (node) sản xuất cho một công ty truyền thông có lưu lượng truy cập cao. Trong sáu tháng, hệ thống đã xử lý hơn 50.000 lượt tải lên tự động mà không gặp một lỗi bảo mật hay phân quyền nào. Nguyên lý rất đơn giản: bạn nhốt người dùng vào một thư mục “jail” (nhà tù). Đối với họ, thư mục đó trông giống như gốc (root) của toàn bộ hệ thống. Họ có các công cụ cần thiết để di chuyển tập tin, nhưng không thể nhìn thấy dù chỉ một byte dữ liệu bên ngoài không gian được chỉ định.
Với hơn ba năm quản lý các hệ thống Linux, tôi đã thấy một lỗi đánh máy nhỏ trong sshd_config có thể khiến quản trị viên bị khóa khỏi chính máy chủ của mình. Luôn giữ một phiên SSH phụ đang mở trong khi bạn thực hiện các thay đổi này. Nếu có vấn đề xảy ra, bạn sẽ cần kết nối đang hoạt động đó để sửa lại cấu hình.
Bước 1: Chuẩn bị môi trường
Dù bạn đang chạy Ubuntu 22.04, Debian 12 hay AlmaLinux 9, quy trình đều bắt đầu bằng việc quản lý nhóm. Quản lý người dùng riêng lẻ là cách nhanh nhất dẫn đến sai lệch cấu hình. Thay vào đó, chúng ta sẽ tạo một nhóm riêng biệt. Điều này cho phép áp dụng một bộ quy tắc bảo mật duy nhất cho mọi người dùng SFTP mà chúng ta tạo ra.
# Tạo một nhóm riêng cho người dùng SFTP
sudo groupadd sftp_users
Bây giờ, hãy thêm một người dùng tên là upload_user. Chúng ta sẽ cố tình loại bỏ quyền truy cập shell của họ. Bằng cách đặt shell thành /bin/false, chúng ta đảm bảo họ không bao giờ có thể khởi tạo một phiên SSH tương tác, ngay cả khi họ vượt qua được các hạn chế khác.
# Tạo người dùng không có shell đăng nhập
sudo useradd -m -g sftp_users -s /bin/false upload_user
# Gán một mật khẩu phức tạp
sudo passwd upload_user
Bước 2: Thiết lập Jail (Bẫy phân quyền)
Phân quyền là nơi hầu hết các quản trị viên hệ thống gặp rắc rối. OpenSSH có một quy tắc không thể thương lượng: thư mục Chroot phải được sở hữu bởi root, và không người dùng hay nhóm nào khác có quyền ghi vào đó. Nếu upload_user sở hữu thư mục home của chính họ, kết nối sẽ bị ngắt ngay lập tức với lỗi “broken pipe”.
Để cung cấp cho người dùng một nơi làm việc thực sự, chúng ta tạo một thư mục con. Hãy coi thư mục home là “sảnh chờ” (chỉ đọc) và thư mục con là “văn phòng” (có quyền đọc-ghi).
# Bảo mật sảnh chờ: phải được sở hữu bởi root
sudo chown root:root /home/upload_user
sudo chmod 755 /home/upload_user
# Tạo không gian làm việc: sở hữu bởi người dùng
sudo mkdir /home/upload_user/uploads
sudo chown upload_user:sftp_users /home/upload_user/uploads
Với thiết lập này, khi người dùng đăng nhập, họ sẽ thấy thư mục /uploads. Họ có thể tải lên, xóa và đổi tên tập tin tại đó, nhưng về mặt vật lý, họ không thể cd .. để vào thư mục gốc thực sự của hệ thống.
Bước 3: Thắt chặt cấu hình OpenSSH
Chúng ta cần yêu cầu dịch vụ SSH (sshd) xử lý nhóm sftp_users theo cách khác. Hãy chỉnh sửa tệp cấu hình của bạn:
sudo nano /etc/ssh/sshd_config
Di chuyển xuống cuối tệp. Chỉ thị Match có tính kế thừa; nó áp dụng cho mọi dòng bên dưới nó. Đặt nó ở cuối giúp ngăn các quy tắc hạn chế này vô tình áp dụng cho tài khoản root hoặc admin của bạn.
# Cấu hình SFTP Chroot
Match Group sftp_users
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PasswordAuthentication yes
Các thiết lập này đóng vai trò quan trọng. ForceCommand internal-sftp bỏ qua mọi yêu cầu về shell và sử dụng bộ máy SFTP tích hợp sẵn. Chúng ta cũng vô hiệu hóa chuyển tiếp TCP và X11 để ngăn người dùng sử dụng máy chủ của bạn làm proxy để tấn công các máy khác trong mạng nội bộ.
Đừng bao giờ bỏ qua việc kiểm tra cú pháp. Một khoảng trắng bị thiếu có thể làm hỏng dịch vụ SSH khi khởi động lại.
sudo sshd -t
Nếu terminal không trả về gì, bạn có thể an tâm khởi động lại:
sudo systemctl restart ssh
Bước 4: Kiểm tra và xử lý sự cố
Xác nhận việc cô lập bằng cách kết nối từ máy cục bộ của bạn. Bạn sẽ có thể vào thư mục uploads nhưng sẽ bị chặn khi cố gắng khám phá các thư mục cấp cao hơn.
sftp upload_user@your_server_ip
# Sau khi kết nối:
pwd
# Kết quả phải là /
cd /etc
# Kết quả phải là "permission denied" hoặc "not found"
Giám sát thực tế
Nếu người dùng báo cáo họ không thể kết nối, đừng đoán mò. Tệp auth.log (hoặc journalctl trên các hệ thống dựa trên RHEL) sẽ cho bạn biết chính xác lý do. Trong một đợt kiểm tra gần đây, tôi thấy rằng 90% lỗi kết nối là do thư mục cha vô tình có quyền 775 thay vì 755.
# Theo dõi các nỗ lực xác thực trong thời gian thực
sudo tail -f /var/log/auth.log | grep sshd
Mẹo chuyên sâu cho quy mô sản xuất
Sau nhiều năm quản lý các môi trường này, tôi khuyên bạn nên thực hiện ba bước thắt chặt cuối cùng:
- Tự động hóa thiết lập: Sử dụng Ansible playbook hoặc Bash script để tạo người dùng. Việc tạo các thư mục này thủ công mỗi lần cuối cùng sẽ dẫn đến sai sót về phân quyền, để lại lỗ hổng bảo mật.
- Bắt buộc sử dụng SSH Key: Mặc dù mật khẩu dễ sử dụng, nhưng chúng dễ bị tấn công brute force. Trong môi trường sản xuất, hãy đặt tệp
.ssh/authorized_keysbên trong thư mục home do root sở hữu. Đặt quyền thành 400 để người dùng không thể tự sửa đổi key của chính họ. - Thiết lập hạn mức đĩa (Disk Quotas): Một người dùng bị cô lập vẫn có thể làm hỏng máy chủ bằng cách làm đầy ổ đĩa. Sử dụng
quotahoặcedquotađể giới hạn thư mụcuploadsở một kích thước hợp lý, chẳng hạn như 5GB hoặc 10GB, tùy thuộc vào nhu cầu dự án.
Thiết lập này cung cấp một môi trường chuyên nghiệp, biệt lập, bảo vệ các tệp hệ thống cốt lõi của bạn trong khi vẫn cung cấp cho người dùng chính xác những gì họ cần. Đây là tiêu chuẩn vàng để xử lý tệp an toàn trong quản trị Linux hiện đại.

