Reading Time: 12 minutes

FTP (viết tắt của File Transfer Protocol) là một giao thức mạng từng được sử dụng nhiều để copy file giữa client và server. Nhưng nó đã được thay thế bằng những phương thức phân phối file nhanh hơn, an toàn hơn và tiện lợi hơn. Nhiều người dùng internet thông thường mong muốn tải file trực tiếp từ trình duyệt web của họ, còn người dùng dòng lệnh thì có xu hướng sử dụng các giao thức bảo mật hơn như SCP hoặc SFTP.

cài đặt vsftpd trên Ubuntu

Tuy vậy, FTP vẫn được sử dụng để hỗ trợ các ứng dụng và quy trình làm việc cũ với những nhu cầu riêng. Nếu được lựa chọn giao thức, bạn nên cân nhắc các lựa chọn hiện đại hơn. Tuy nhiên, khi bạn thực sự cần FTP, vsftpd là một giải pháp tuyệt vời.

Công cụ này được tối ưu hóa về bảo mật, hiệu năng và sự ổn định. vsftpd cung cấp khả năng bảo vệ mạnh mẽ trước nhiều vấn đề bảo mật thường thấy ở các FTP server khác và đã trở thành lựa chọn mặc định cho nhiều bản phân phối Linux.

Trong hướng dẫn này, bạn sẽ cấu hình vsftpd để cho phép một user tải file lên thư mục home của họ bằng FTP với thông tin đăng nhập được bảo mật bằng SSL/TLS.

Hướng dẫn cài đặt vsftpd cho thư mục của user trên Ubuntu

Điều kiện tiên quyết

Để thực hiện theo hướng dẫn này, bạn sẽ cần có sẵn một server Ubuntu với một user thường có quyền sudo.

Bước 1: Cài đặt vsftpd

Ta sẽ bắt đầu bằng cách cập nhật danh sách package và cài đặt vsftpd daemon:

sudo apt update
sudo apt install vsftpd

Sau khi cài đặt hoàn tất, sao chép file cấu hình mặc định để thể bắt đầu với một bản sạch, đồng thời giữ lại file gốc làm backup:

sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig

Khi đã có bản cấu hình backup, chúng ta đã có thể cấu hình firewall.

Bước 2: Mở firewall

Hãy kiểm tra trạng thái firewall để xem nó đã được bật hay chưa. Nếu có, phải đảm bảo rằng lưu lượng FTP được cho đi qua để firewall không chặn việc kiểm thử của chúng ta.

Kiểm tra trạng thái firewall:

sudo ufw status

Trong trường hợp này, chỉ có SSH được cho phép đi qua:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Bạn có thể có các rule khác hoặc không có rule nào cả. Vì trong trường hợp này chỉ có lưu lượng SSH được phép, ta sẽ cần thêm các rule cho lưu lượng FTP.

Hãy mở các port 2021 cho FTP, port 990 để dùng khi bật TLS, và dải port passive (chỉ mở khi client yêu cầu) 40000-50000 mà ta dự định thiết lập trong file cấu hình:

sudo ufw allow 20/tcp
sudo ufw allow 21/tcp
sudo ufw allow 990/tcp
sudo ufw allow 40000:50000/tcp
sudo ufw status

Các rule firewall của chúng ta bây giờ sẽ trông như sau:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
990/tcp                    ALLOW       Anywhere
20/tcp                     ALLOW       Anywhere
21/tcp                     ALLOW       Anywhere
40000:50000/tcp            ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
20/tcp (v6)                ALLOW       Anywhere (v6)
21/tcp (v6)                ALLOW       Anywhere (v6)
990/tcp (v6)               ALLOW       Anywhere (v6)
40000:50000/tcp (v6)       ALLOW       Anywhere (v6)

Khi vsftpd đã được cài đặt và các port cần thiết đã được mở, hãy bắt đầu tạo một user FTP chuyên dụng.

Bước 3: Chuẩn bị thư mục của user

Ta sẽ tạo một user FTP chuyên dụng mới, nhưng có thể bạn đã có sẵn một user cần quyền truy cập FTP. Trong các hướng dẫn sau, chúng ta sẽ cẩn thận để bảo toàn quyền truy cập của một user hiện có vào dữ liệu của họ. Mặc dù vậy, chúng tôi vẫn khuyên bạn nên bắt đầu với một user mới cho đến khi bạn đã cấu hình và kiểm thử xong thiết lập của mình.

Đầu tiên, thêm một user thử nghiệm:

sudo adduser sammy

Gán mật khẩu khi được nhắc. Bạn có thể nhấn ENTER để bỏ qua các lời nhắc khác.

FTP an toàn hơn khi user bị giới hạn trong một thư mục cụ thể. vsftpd thực hiện điều này thông qua chroot jail (cơ chế cô lập tiến trình ứng dụng). Khi chroot được bật cho các user cục bộ, chúng sẽ bị giới hạn trong thư mục home của mình theo mặc định. Tuy nhiên, do cách vsftpd bảo vệ thư mục, thư mục đó không được có quyền ghi bởi user. Điều này phù hợp với một user mới chỉ cần kết nối qua FTP. Nhưng một user có sẵn có thể cần ghi vào thư mục home của họ nếu họ cũng có quyền truy cập shell.

Trong ví dụ này, thay vì xóa quyền ghi khỏi thư mục home, ta sẽ tạo một thư mục ftp cho chroot và thư mục files có quyền ghi để chứa các file thực tế cần dùng.

Tạo thư mục ftp:

sudo mkdir /home/sammy/ftp

Thiết lập quyền sở hữu cho nó:

sudo chown nobody:nogroup /home/sammy/ftp

Xóa quyền ghi:

sudo chmod a-w /home/sammy/ftp

Xác minh các quyền:

sudo ls -la /home/sammy/ftp
total 8
4 dr-xr-xr-x  2 nobody nogroup 4096 Aug 24 21:29 .
4 drwxr-xr-x  3 sammy  sammy   4096 Aug 24 21:29 ..

Tiếp theo, hãy tạo thư mục để tải file lên và gán quyền sở hữu cho user:

sudo mkdir /home/sammy/ftp/files
sudo chown sammy:sammy /home/sammy/ftp/files

Kiểm tra quyền trên thư mục ftp sẽ trả về kết quả sau:

sudo ls -la /home/sammy/ftp
total 12
dr-xr-xr-x 3 nobody nogroup 4096 Aug 26 14:01 .
drwxr-xr-x 3 sammy  sammy   4096 Aug 26 13:59 ..
drwxr-xr-x 2 sammy  sammy   4096 Aug 26 14:01 files

Cuối cùng, hãy thêm một file test.txt cho việc kiểm thử:

echo "vsftpd test file" | sudo tee /home/sammy/ftp/files/test.txt

Khi đã bảo vệ thư mục ftp và cho phép user truy cập vào thư mục files, hãy tiếp tục với việc sửa đổi cấu hình của bạn.

Bước 4: Cấu hình truy cập FTP

Chúng ta dự định cho phép một user duy nhất có tài khoản shell cục bộ kết nối bằng FTP. Hai thiết lập quan trọng cho việc này đã có trong vsftpd.conf. Hãy mở file cấu hình để xác minh rằng các thiết lập trong cấu hình của bạn khớp với những nội dung dưới đây:

sudo nano /etc/vsftpd.conf
. . .
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
. . .

Tiếp theo, hãy cho phép user tải file lên bằng cách bỏ comment (dấu #) ở thiết lập write_enable:

. . .
write_enable=YES
. . .

Chúng ta cũng sẽ bỏ comment chroot_local_user để ngăn user kết nối qua FTP truy cập bất kỳ file hoặc lệnh nào bên ngoài cây thư mục của họ:

. . .
chroot_local_user=YES
. . .

Ta sẽ thêm một user_sub_token để chèn tên người dùng vào đường dẫn local_root của chúng ta để cấu hình này hoạt động cho user này và bất kỳ user nào khác trong tương lai. Thêm các cài đặt này vào bất kỳ vị trí nào trong file:

. . .
user_sub_token=$USER
local_root=/home/$USER/ftp

Giới hạn phạm vi các port có thể được sử dụng cho kết nối FTP thụ động để đảm bảo có đủ kết nối:

. . .
pasv_min_port=40000
pasv_max_port=50000

Lưu ý: Ở bước 2, chúng ta đã mở các port mà ta đã thiết lập ở đây cho dải port passive. Nếu bạn thay đổi các giá trị này, hãy đảm bảo cập nhật cài đặt firewall tương ứng của bạn.

Để cho phép truy cập FTP theo từng trường hợp cụ thể, ta hãy thiết lập để user chỉ có quyền truy cập khi họ đã được thêm vào danh sách cho phép một cách tường minh, thay vì mặc định có quyền:

. . .
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

userlist_deny có tính đảo ngược logic: Khi nó được đặt thành YES, các user trong danh sách sẽ bị từ chối truy cập FTP. Khi nó được đặt thành NO, chỉ những user trong danh sách mới được phép truy cập.

Khi đã thực hiện xong các thay đổi, hãy lưu file và thoát khỏi editor.

Cuối cùng, hãy thêm user của chúng ta vào /etc/vsftpd.userlist. Sử dụng cờ -a để chèn nội dung vào file:

echo "sammy" | sudo tee -a /etc/vsftpd.userlist

Kiểm tra xem nó đã được thêm vào như bạn mong đợi chưa:

cat /etc/vsftpd.userlist
sammy

Khởi động lại daemon để nạp các cấu hình mới:

sudo systemctl restart vsftpd

Sau khi đã thay đổi cấu hình, hãy chuyển sang bước kiểm thử truy cập FTP.

Bước 5: Kiểm thử truy cập FTP

Chúng ta đã cấu hình server để chỉ cho phép user sammy kết nối qua FTP. Bây giờ hãy kiểm tra để đảm bảo rằng thiết lập đó hoạt động đúng như mong đợi.

User ẩn danh sẽ không thể kết nối được: Chúng ta đã vô hiệu hóa quyền truy cập ẩn danh. Hãy kiểm tra điều đó bằng cách thử kết nối ẩn danh. Nếu cấu hình của chúng ta được thiết lập đúng, user ẩn danh sẽ bị từ chối quyền.

Mở một cửa sổ terminal khác và chạy lệnh sau. Nhớ thay thế your_server_ip bằng địa chỉ IP công khai của server của bạn:

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): anonymous
530 Permission denied.
ftp: Login failed.
ftp>

Sau đó đóng kết nối:

ftp> bye

Các user không phải sammy sẽ không thể kết nối được: Tiếp theo, hãy thử kết nối với tư cách là user sudo của chúng ta. Họ cũng sẽ bị từ chối truy cập, và điều này sẽ xảy ra trước khi họ được phép nhập mật khẩu:

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sudo_user
530 Permission denied.
ftp: Login failed.
ftp>

Đóng kết nối:

ftp> bye

User sammy sẽ có quyền kết nối, đọc và ghi file: Hãy đảm bảo rằng user được chỉ định của chúng ta có thể kết nối:

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
331 Please specify the password.
Password: your_user's_password
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

Sau đó di chuyển vào thư mục files và sử dụng lệnh get để chuyển file test mà chúng ta đã tạo trước đó về máy cục bộ:

ftp> cd files
ftp> get test.txt
227 Entering Passive Mode (203,0,113,0,169,12).
150 Opening BINARY mode data connection for test.txt (16 bytes).
226 Transfer complete.
16 bytes received in 0.0101 seconds (1588 bytes/s)
ftp>

Tiếp theo, hãy tải lên file với một tên mới để kiểm tra quyền ghi:

ftp> put test.txt upload.txt
227 Entering Passive Mode (203,0,113,0,164,71).
150 Ok to send data.
226 Transfer complete.
16 bytes sent in 0.000894 seconds (17897 bytes/s)

Đóng kết nối:

ftp> bye

Sau khi đã kiểm thử cấu hình, hãy thực hiện các bước để bảo mật server hơn nữa.

Bước 6: Bảo mật giao dịch

Vì FTP không mã hóa bất kỳ dữ liệu nào trong quá trình truyền tải, bao gồm cả thông tin đăng nhập của user, chúng ta sẽ bật TLS/SSL để mã hóa chúng. Bước đầu tiên là tạo chứng chỉ SSL để sử dụng với vsftpd.

Ta sẽ sử dụng openssl để tạo một chứng chỉ mới và sử dụng cờ -days để cho nó hiệu lực trong một năm. Trong cùng lệnh đó, ta cũng sẽ thêm một khóa RSA 2048-bit riêng tư. Bằng cách đặt cả cờ -keyout-out với cùng một giá trị, khóa riêng và chứng chỉ sẽ được đặt trong chung một file:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

Bạn sẽ được yêu cầu cung cấp thông tin địa chỉ cho chứng chỉ của mình. Thay thế thông tin của bạn cho các giá trị ví dụ bên dưới:

Generating a 2048 bit RSA private key
............................................................................+++
...........+++
writing new private key to '/etc/ssl/private/vsftpd.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:NY
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: your_server_ip
Email Address []:

Sau khi bạn đã tạo chứng chỉ, hãy mở lại file cấu hình vsftpd.conf:

sudo nano /etc/vsftpd.conf

Gần cuối file, bạn sẽ thấy hai dòng bắt đầu bằng rsa_. Hãy comment chúng đi để chúng trông như thế này:

. . .
# rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
# rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
. . .

Bên dưới chúng, thêm các dòng sau đây để trỏ đến chứng chỉ và khóa riêng tư mà chúng ta vừa tạo:

. . .
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
. . .

Sau đó, chúng ta sẽ bắt buộc việc sử dụng SSL để chặn các client không hỗ trợ TLS. Điều này đảm bảo rằng tất cả kết nối được mã hóa, tuy nó có thể buộc user FTP của bạn phải dùng client khác.

Thay đổi ssl_enable thành YES:

. . .
ssl_enable=YES
. . .

Sau đó, thêm các dòng sau để từ chối một cách tường minh các kết nối ẩn danh qua SSL và bắt buộc dùng SSL cho cả việc truyền dữ liệu và đăng nhập:

. . .
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
. . .

Sau đó, cấu hình server để sử dụng TLS (giao thức kế nhiệm được ưu tiên của SSL) bằng cách thêm các dòng sau:

. . .
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
. . .

Cuối cùng, chúng ta sẽ thêm hai cấu hình nữa. Thứ nhất, chúng ta sẽ không yêu cầu tái sử dụng SSL vì nó có thể làm nhiều client FTP không hoạt động được. Chúng ta sẽ yêu cầu các bộ mật mã hóa “cao” (“high”), hiện có nghĩa là độ dài khóa bằng hoặc lớn hơn 128 bit:

. . .
require_ssl_reuse=NO
ssl_ciphers=HIGH
. . .

Phần file hoàn chỉnh sẽ trông như thế này:

# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH

Khi hoàn tất, hãy lưu và đóng file, sau đó khởi động lại server để các thay đổi có hiệu lực:

sudo systemctl restart vsftpd

Tại thời điểm này, chúng ta sẽ không thể kết nối bằng một client dòng lệnh không an toàn nữa. Nếu chúng ta cố làm thế, lỗi sau sẽ hiện ra:

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
530 Non-anonymous sessions must use encryption.
ftp: Login failed.
421 Service not available, remote server has closed connection
ftp>

Ở bước tiếp theo, ta sẽ xác minh rằng ta có thể kết nối bằng một client hỗ trợ TLS.

Bước 7: Kiểm thử TLS với FileZilla

Hầu hết các client FTP hiện đại có thể được cấu hình để sử dụng mã hóa TLS. Hướng dẫn này sử dụng FileZilla vì đây là một chương trình miễn phí và hỗ trợ đa nền tảng. Hãy tham khảo các tài liệu chính thức nếu bạn sử dụng các client khác.

Khi bạn mở FileZilla lần đầu, hãy tìm và nhấp vào biểu tượng Site Manager, ngay phía trên chữ Host và ở phía ngoài cùng bên trái trên hàng trên cùng.

Giao diện đăng nhập FTP trên FileZilla

Một cửa sổ mới sẽ mở ra. Nhấp vào nút New Site ở góc dưới cùng bên phải:

Giao diện đăng nhập trên FileZilla

Trong phần My Sites, sẽ có một biểu tượng mới với chữ New site. Bạn có thể đặt tên cho nó ngay bây giờ hoặc để tên mặc định và quay lại sau để chỉnh sửa với nút Rename.

Điền vào trường Host với tên hoặc địa chỉ IP. Dưới menu thả xuống Encryption, chọn Require explicit FTP over TLS.

Đối với Logon Type, chọn Ask for password. Điền user FTP của bạn vào trường User:

Giao diện đăng nhập vsftpd trên FileZilla

Nhấp vào Connect ở cuối giao diện. Bạn sẽ được hỏi mật khẩu của user:

Giao diện kết nối FTP trên FileZilla

Nhấp vào OK để kết nối. Bây giờ bạn sẽ được kết nối với server của mình với mã hóa TLS/SSL.

Khi thành công, chương trình sẽ hiển thị một chứng chỉ server trông như thế này:

Giao diện báo kết nối thành công trên FileZilla

Sau khi đã chấp nhận chứng chỉ, nhấp đúp vào thư mục files và kéo file upload.txt sang bên trái để xác nhận rằng chương trình cho phép bạn tải xuống các file:

Giao diện quản lý file trên FileZilla

Sau đó, nhấp chuột phải vào bản sao cục bộ, đổi tên nó thành upload-tls.txt và kéo nó trở lại bên server để xác nhận rằng bạn có thể tải lên các file:

Giao diện quản lý file trên FileZilla

Bây giờ bạn đã xác nhận rằng bạn có thể chuyển file một cách an toàn và thành công khi SSL/TLS được bật.

Bước 8: Vô hiệu hóa truy cập shell (không bắt buộc)

Nếu bạn không thể sử dụng TLS do yêu cầu của client, bạn có thể tăng cường bảo mật bằng cách vô hiệu hóa khả năng đăng nhập của user FTP bằng các cách khác.

Một phương thức tương đối đơn giản là tạo một shell tùy chỉnh. Cách này sẽ không cung cấp bất kỳ cơ chế mã hóa nào, nhưng nó sẽ giới hạn quyền truy cập của một tài khoản bị xâm phạm vào các file có thể truy cập bằng FTP.

Đầu tiên, mở một file có tên ftponly trong thư mục /bin:

sudo nano /bin/ftponly

Thêm một thông báo cho người dùng biết tại sao họ không thể đăng nhập:

#!/bin/sh
echo "This account is limited to FTP access only."

Lưu file và thoát khỏi editor của bạn. Thay đổi quyền để làm cho file có thể chạy được:

sudo chmod a+x /bin/ftponly

Mở danh sách các shell hợp lệ:

sudo nano /etc/shells

Thêm vào dòng này ở cuối file:

. . .
/bin/ftponly

Cập nhật shell của user bằng lệnh sau:

sudo usermod sammy -s /bin/ftponly

Bây giờ hãy thử đăng nhập vào server của bạn với tư cách là sammy:

ssh sammy@your_server_ip

Bạn sẽ thấy một thông báo như sau:

This account is limited to FTP access only.
Connection to 203.0.113.0 closed.

Điều này xác nhận rằng user đã không còn có thể dùng ssh để kết nối vào server và chỉ có thể truy cập bằng FTP.

Tổng kết

Trong hướng dẫn này, chúng ta đã tìm hiểu cách thiết lập FTP cho người dùng với tài khoản cục bộ. Nếu cần sử dụng một nguồn xác thực bên ngoài, bạn nên tìm hiểu về tính năng hỗ trợ người dùng ảo (virtual user) của vsftpd. Tính năng này mang lại nhiều tùy chọn phong phú thông qua việc sử dụng PAM (Pluggable Authentication Module), một lựa chọn lý tưởng nếu bạn quản lý người dùng trong một hệ thống khác như LDAP hoặc Kerberos.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất