Cách định cấu hình Suricata làm Hệ thống ngăn chặn xâm nhập (IPS) trên Ubuntu 20.04

Giới thiệu

Trong hướng dẫn này, bạn sẽ học cách định cấu hình chế độ Hệ thống Ngăn chặn Xâm nhập (IPS) tích hợp sẵn của Suricata. Theo mặc định, Suricata được định cấu hình để chạy như một Hệ thống phát hiện xâm nhập (IDS), hệ thống này chỉ tạo cảnh báo và ghi lại lưu lượng truy cập đáng ngờ. Khi bạn bật chế độ IPS, Suricata có thể chủ động loại bỏ lưu lượng mạng đáng ngờ ngoài việc tạo cảnh báo để phân tích thêm.

Trước khi bật chế độ IPS, điều quan trọng là phải kiểm tra xem bạn đã bật chữ ký nào và các hành động mặc định của chúng. Chữ ký được định cấu hình không chính xác hoặc chữ ký quá rộng có thể dẫn đến giảm lưu lượng truy cập hợp pháp vào mạng của bạn hoặc thậm chí chặn bạn truy cập vào máy chủ của mình qua và các giao thức quản lý khác.

Trong phần đầu tiên của hướng dẫn này, bạn sẽ kiểm tra các chữ ký mà bạn đã cài đặt và kích hoạt. Bạn cũng sẽ học cách bao gồm chữ ký của riêng bạn. Khi bạn biết mình muốn sử dụng chữ ký nào trong chế độ IPS, bạn sẽ chuyển đổi hành động mặc định của chúng để giảm hoặc từ chối lưu lượng truy cập. Với chữ ký của bạn, bạn sẽ học cách gửi lưu lượng mạng qua Suricata bằng cách sử dụng mục tiêu iptables netfilter NFQUEUE, sau đó tạo một số lưu lượng mạng không hợp lệ để đảm bảo rằng Suricata giảm nó như mong đợi.

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

Nếu bạn đang theo dõi loạt bài hướng dẫn này thì bạn đã có Suricata đang chạy trên máy chủ .

  • Nếu bạn vẫn cần cài đặt Suricata thì bạn có thể làm theo Cách cài đặt Suricata trên Ubuntu 20.04

  • Bạn cũng nên tải xuống ET Open Ruleset bằng cách sử dụng suricata-update và có trong chữ ký Suricata của bạn.

  • Các jq xử lý JSON dòng lệnh. Nếu bạn chưa cài đặt nó từ hướng dẫn trước, bạn có thể làm như vậy bằng cách sử dụng apt yêu cầu:

    • sudo apt update
    • sudo apt install jq

Bạn cũng có thể có các chữ ký tùy chỉnh mà bạn muốn sử dụng từ hướng dẫn Hiểu về Chữ ký Suricata trước đó.

Bước 1 – Bao gồm chữ ký tùy chỉnh

Các hướng dẫn trước trong loạt bài này đã khám phá cách cài đặt và cấu hình Suricata, cũng như cách hiểu chữ ký. Nếu bạn muốn tạo và bao gồm các quy tắc của riêng mình thì bạn cần chỉnh sửa /etc/suricata/suricata.yaml tệp để bao gồm một đường dẫn tùy chỉnh đến chữ ký của bạn.

Trước tiên, hãy tìm các IP công cộng của máy chủ của bạn để bạn có thể sử dụng chúng trong các chữ ký tùy chỉnh của mình. Để tìm các IP của bạn, bạn có thể sử dụng ip yêu cầu:

You should receive output like the following:

Output

lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 203.0.113.0.5/20 10.20.0.5/16 2001:DB8::1/32 fe80::94ad:d4ff:fef9:cee0/64 eth1 UP 10.137.0.2/16 fe80::44a2:ebff:fe91:5187/64

(Các) địa chỉ IP công cộng của bạn sẽ giống với địa chỉ được đánh dấu 203.0.113.0.52001:DB8::1/32 IP trong đầu ra.

Bây giờ, hãy tạo chữ ký tùy chỉnh sau để quét lưu lượng SSH đến các cổng không phải SSH và đưa nó vào một tệp có tên /var/lib/suricata/rules/local.rules. Mở tệp bằng nano hoặc trình soạn thảo ưa thích của bạn:

  • sudo nano /var/lib/suricata/rules/local.rules

Sao chép và dán chữ ký sau:

Chữ ký lưu lượng truy cập SSH không hợp lệ

alert ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000000;)
alert ssh any any -> 2001:DB8::1/32 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000001;)

Thay thế địa chỉ IP công cộng của máy chủ của bạn thay cho 203.0.113.52001:DB8::1/32 địa chỉ trong quy tắc. Nếu bạn không sử dụng IPv6 thì bạn có thể bỏ qua việc thêm chữ ký đó trong phần này và các quy tắc sau.

Bạn có thể tiếp tục thêm chữ ký tùy chỉnh vào cái này local.rules tùy thuộc vào mạng và ứng dụng của bạn. Ví dụ: nếu bạn muốn cảnh báo về lưu lượng HTTP đến các cổng không chuẩn, bạn có thể sử dụng các chữ ký sau:

Lưu lượng HTTP trên chữ ký cổng không chuẩn

alert http any any -> 203.0.113.0.5 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000002;)
alert http any any -> 2001:DB8::1/32 !80 (msg:"HTTP REQUEST on non-HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000003;)

Để thêm chữ ký kiểm tra lưu lượng TLS đến các cổng khác với cổng mặc định 443 đối với máy chủ web, hãy thêm phần sau:

Xem tiếp:   Cách tự động khởi động lại ứng dụng Node.js của bạn với gật gù

Lưu lượng TLS trên chữ ký cổng không chuẩn

alert tls any any -> 203.0.113.0.5 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000004;)
alert tls any any -> 2001:DB8::1/32 !443 (msg:"TLS TRAFFIC on non-TLS HTTP port"; flow:to_client, not_established; classtype:misc-activity; sid:1000005;)

Khi bạn hoàn tất việc thêm chữ ký, hãy lưu và đóng tệp. Nếu bạn đang sử dụng nano, bạn có thể làm như vậy với CTRL+X, sau đó YENTER xác nhận. Nếu bạn đang sử dụng vi, nhấn ESC và sau đó :x sau đó ENTER để lưu và thoát.

Bây giờ bạn đã xác định một số chữ ký tùy chỉnh, hãy chỉnh sửa Suricata's /etc/suricata/suricata.yaml sử dụng tệp cấu hình nano hoặc trình soạn thảo ưa thích của bạn để bao gồm chúng:

  • sudo nano /etc/suricata/suricata.yaml

Tìm rule-files: một phần của cấu hình. Nếu bạn đang sử dụng nano sử dụng CTRL+_ và sau đó nhập số dòng 1879. Nếu bạn đang sử dụng vi đi vào 1879gg để đi đến dòng. Vị trí chính xác trong tệp của bạn có thể khác, nhưng bạn phải ở đúng khu vực chung của tệp.

Chỉnh sửa phần và thêm phần sau được đánh dấu - local.rules hàng:

/etc/suricata/suricata.yaml

. . .
rule-files:
  - suricata.rules
  - local.rules
. . .

Lưu và thoát khỏi tệp. Đảm bảo xác thực cấu hình của Suricata sau khi thêm các quy tắc của bạn. Để làm như vậy, hãy chạy lệnh sau:

  • sudo suricata -T -c /etc/suricata/suricata.yaml -v

Quá trình kiểm tra có thể mất một chút thời gian tùy thuộc vào số lượng quy tắc bạn đã tải ở chế độ mặc định suricata.rules tập tin. Nếu bạn thấy quá trình kiểm tra mất quá nhiều thời gian, bạn có thể nhận xét - suricata.rules trong cấu hình bằng cách thêm một # đến đầu dòng và sau đó chạy lại kiểm tra cấu hình của bạn. Hãy chắc chắn để loại bỏ # bình luận nếu bạn định sử dụng suricata.rules chữ ký trong cấu hình đang chạy cuối cùng của bạn.

Khi bạn hài lòng với các chữ ký mà bạn đã tạo hoặc đưa vào bằng cách sử dụng suricata-update công cụ này, bạn có thể tiến hành bước tiếp theo, nơi bạn sẽ chuyển hành động mặc định cho chữ ký của mình từ alert hoặc là log để chủ động giảm lưu lượng truy cập.

Bước 2 - Định cấu hình hành động chữ ký

Bây giờ bạn đã thử nghiệm chữ ký tùy chỉnh và hoạt động với Suricata, bạn có thể thay đổi hành động thành drop hoặc là reject. Khi Suricata đang hoạt động ở chế độ IPS, những hành động này sẽ chủ động chặn lưu lượng truy cập không hợp lệ cho bất kỳ chữ ký phù hợp nào.

Hai thao tác này được mô tả trong phần hướng dẫn trước của loạt bài này, Hiểu về Chữ ký Suricata. Việc lựa chọn sử dụng hành động nào là tùy thuộc vào bạn. MỘT drop hành động sẽ ngay lập tức loại bỏ một gói và bất kỳ gói nào tiếp theo thuộc luồng mạng. MỘT reject action sẽ gửi cho cả máy khách và máy chủ một gói đặt lại nếu lưu lượng dựa trên TCP và một gói lỗi ICMP cho bất kỳ giao thức nào khác.

Hãy sử dụng các quy tắc tùy chỉnh từ phần trước và chuyển đổi chúng để sử dụng drop hành động, vì lưu lượng mà chúng phù hợp có thể là quá trình quét mạng hoặc một số kết nối không hợp lệ khác.

Mở của bạn /var/lib/suricata/rules/local.rules sử dụng tập tin nano hoặc trình soạn thảo ưa thích của bạn và thay đổi alert hành động ở đầu mỗi dòng trong tệp để drop:

  • sudo nano /var/lib/suricata/rules/local.rules

/var/lib/suricata/rules/local.rules

drop ssh any any -> 203.0.113.0.5 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000000;)
drop ssh any any -> 2001:DB8::1/32 !22 (msg:"SSH TRAFFIC on non-SSH port"; classtype: misc-attack; target: dest_ip; sid:1000001;)
. . .

Lặp lại bước trên cho bất kỳ chữ ký nào trong /var/lib/suricata/rules/suricata.rules mà bạn muốn chuyển đổi thành drop hoặc là reject chế độ.

Ghi chú: Nếu bạn đã chạy suricata-update trong hướng dẫn điều kiện tiên quyết, bạn có thể có hơn 30.000 chữ ký được bao gồm trong suricata.rules file.

Nếu bạn chuyển đổi mọi chữ ký thành drop hoặc là reject bạn có nguy cơ chặn truy cập hợp pháp vào mạng hoặc máy chủ của mình. Thay vào đó, hãy để các quy tắc trong suricata.rules trong lúc này và thêm chữ ký tùy chỉnh của bạn vào local.rules. Suricata sẽ tiếp tục tạo cảnh báo cho lưu lượng truy cập đáng ngờ được mô tả bằng các chữ ký trong suricata.rules trong khi nó đang chạy ở chế độ IPS.

Sau khi thu thập được một vài ngày hoặc vài tuần các cảnh báo, bạn có thể phân tích chúng và chọn các chữ ký có liên quan để chuyển đổi sang drop hoặc là reject dựa trên họ sid.

Khi bạn đã định cấu hình tất cả các chữ ký với hành động mà bạn muốn họ thực hiện, bước tiếp theo là định cấu hình lại và sau đó khởi động lại Suricata ở chế độ IPS.

Xem tiếp:   Cách tạo ứng dụng blog Django và kết nối nó với MySQL

Bước 3 - Bật nfqueue Chế độ

Suricata chạy ở chế độ IDS theo mặc định, có nghĩa là nó sẽ không chủ động chặn lưu lượng mạng. Để chuyển sang chế độ IPS, bạn sẽ cần chỉnh sửa /etc/default/suricata tập tin cấu hình.

Mở tệp trong nano hoặc trình soạn thảo ưa thích của bạn:

  • sudo nano /etc/default/suricata

Tìm LISTENMODE=af-packet dòng và nhận xét nó ra bằng cách thêm một # đến đầu dòng. Sau đó, thêm một dòng mới LISTENMODE=nfqueue dòng cho biết Suricata chạy ở chế độ IPS.

Tệp của bạn phải có các dòng được đánh dấu sau khi bạn chỉnh sửa xong:

/ etc / default / suricata

. . .
# LISTENMODE=af-packet
LISTENMODE=nfqueue
. . .

Lưu và đóng tập tin. Bây giờ bạn có thể khởi động lại Suricata bằng cách sử dụng systemctl:

  • sudo systemctl restart suricata.service

Kiểm tra trạng thái của Suricata bằng cách sử dụng systemctl:

  • sudo systemctl status suricata.service

Bạn sẽ nhận được đầu ra như sau:

Output

● suricata.service - LSB: Next Generation IDS/IPS Loaded: loaded (/etc/init.d/suricata; generated) Active: active (running) since Wed 2021-12-01 15:54:28 UTC; 2s ago Docs: man:systemd-sysv-generator(8) Process: 1452 ExecStart=/etc/init.d/suricata start (code=exited, status=0/SUCCESS) Tasks: 12 (limit: 9513) Memory: 63.6M CGroup: /system.slice/suricata.service └─1472 /usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata.pid -q 0 -D -vvv Dec 01 15:54:28 suricata systemd[1]: Starting LSB: Next Generation IDS/IPS... Dec 01 15:54:28 suricata suricata[1452]: Starting suricata in IPS (nfqueue) mode... done. Dec 01 15:54:28 suricata systemd[1]: Started LSB: Next Generation IDS/IPS.

Lưu ý đánh dấu active (running) dòng cho biết Suricata đã khởi động lại thành công. Cũng lưu ý Starting suricata in IPS (nfqueue) mode... done. , xác nhận Suricata hiện đang chạy ở chế độ IPS.

Với thay đổi này, bây giờ bạn đã sẵn sàng để gửi lưu lượng truy cập đến Suricata bằng cách sử dụng tường lửa UFW trong bước tiếp theo.

Bước 4 - Định cấu hình UFW để gửi lưu lượng truy cập đến Suricata

Bây giờ bạn đã cấu hình Suricata để xử lý lưu lượng ở chế độ IPS, bước tiếp theo là chuyển hướng các gói đến Suricata. Nếu bạn đã làm theo các hướng dẫn tiên quyết cho loạt bài này và đang sử dụng hệ thống Ubuntu 20.04, bạn nên cài đặt và bật Tường lửa không phức tạp (UFW).

Để thêm các quy tắc bắt buộc cho Suricata vào UFW, bạn sẽ cần chỉnh sửa các tệp tường lửa trong /etc/ufw/before.rules (Quy tắc IPv4) và /etc/ufw/before6.rules (IPv6) trực tiếp.

Mở tệp đầu tiên cho các quy tắc IPv4 bằng cách sử dụng nano hoặc trình soạn thảo ưa thích của bạn:

  • sudo nano /etc/ufw/before.rules

Gần đầu tệp, hãy chèn các dòng được đánh dấu sau:

/etc/ufw/before.rules

. . .
# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines

## Start Suricata NFQUEUE rules
-I INPUT 1 -p tcp --dport 22 -j NFQUEUE --queue-bypass
-I OUTPUT 1 -p tcp --sport 22 -j NFQUEUE --queue-bypass
-I FORWARD -j NFQUEUE
-I INPUT 2 -j NFQUEUE
-I OUTPUT 2 -j NFQUEUE
## End Suricata NFQUEUE rules

# allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT
. . .

Lưu và thoát khỏi tệp khi bạn chỉnh sửa xong. Bây giờ, hãy thêm các dòng được đánh dấu giống nhau vào cùng một phần trong /etc/ufw/before6.rules tập tin:

  • sudo nano /etc/ufw/before.rules

Đảm bảo rằng cả hai tệp đều có nội dung giống nhau. Lưu và thoát khỏi tệp khi bạn chỉnh sửa xong.

Hai cái đầu tiên INPUTOUTPUT các quy tắc được sử dụng để bỏ qua Suricata để bạn có thể kết nối với máy chủ của mình bằng SSH, ngay cả khi Suricata không chạy. Nếu không có các quy tắc này, chữ ký không chính xác hoặc quá rộng có thể chặn quyền truy cập SSH của bạn. Ngoài ra, nếu Suricata bị dừng, tất cả lưu lượng truy cập sẽ được chuyển đến NFQUEUE mục tiêu và sau đó giảm xuống vì Suricata không chạy.

Tiếp theo FORWARD quy tắc đảm bảo rằng nếu máy chủ của bạn đang hoạt động như một cổng cho các hệ thống khác, tất cả lưu lượng truy cập đó cũng sẽ được chuyển đến Suricata để xử lý.

Cuối cùng hai INPUTOUTPUT quy tắc gửi tất cả lưu lượng còn lại không phải là lưu lượng SSH đến Suricata để xử lý.

Khởi động lại UFW để tải các quy tắc mới:

  • sudo systemctl restart ufw.service

Ghi chú: Nếu bạn đang sử dụng tường lửa khác, bạn sẽ cần phải sửa đổi các quy tắc này để phù hợp với định dạng tường lửa của bạn mong đợi.

Xem tiếp:   Cách cài đặt ngăn xếp Linux, Apache, MySQL, PHP (LAMP) trên Ubuntu 16.04

Nếu bạn đang sử dụng iptables, thì bạn có thể chèn các quy tắc này trực tiếp bằng cách sử dụng iptablesip6tables các lệnh. Tuy nhiên, bạn sẽ cần phải đảm bảo rằng các quy tắc luôn ổn định qua các lần khởi động lại bằng một công cụ như iptables-persistent.

Nếu bạn đang sử dụng firewalld, thì các quy tắc sau sẽ hướng lưu lượng truy cập đến Suricata:

  • firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
  • firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -j NFQUEUE
  • firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p tcp --dport 22 -j NFQUEUE --queue-bypass
  • firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -j NFQUEUE
  • firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -j NFQUEUE
  • firewall-cmd --permanent --direct --add-rule ipv6 filter FORWARD 0 -j NFQUEUE
  • firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass
  • firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 1 -j NFQUEUE
  • firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 0 -p tcp --sport 22 -j NFQUEUE --queue-bypass
  • firewall-cmd --permanent --direct --add-rule ipv6 filter OUTPUT 1 -j NFQUEUE

Tại thời điểm này trong hướng dẫn, bạn đã cấu hình Suricata để chạy ở chế độ IPS và lưu lượng mạng của bạn đang được gửi đến Suricata theo mặc định. Bạn sẽ có thể khởi động lại máy chủ của mình bất kỳ lúc nào và các quy tắc Suricata và tường lửa của bạn sẽ được duy trì.

Bước cuối cùng trong hướng dẫn này là xác minh Suricata đang giảm lưu lượng truy cập một cách chính xác.

Bước 5 - Kiểm tra lưu lượng truy cập không hợp lệ

Bây giờ bạn đã có Suricata và tường lửa của mình được định cấu hình để xử lý lưu lượng mạng, bạn có thể kiểm tra xem Suricata có thả các gói phù hợp với chữ ký tùy chỉnh và các chữ ký đi kèm khác của bạn hay không.

Nhớ lại chữ ký sid:2100498 từ hướng dẫn trước, được sửa đổi trong ví dụ này thành drop các gói phù hợp:

sid: 2100498

drop ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)

Tìm và chỉnh sửa quy tắc trong /var/lib/suricata/rules/suricata.rules tập tin để sử dụng drop hành động nếu bạn có chữ ký bao gồm ở đó. Nếu không, hãy thêm quy tắc vào /var/lib/suricata/rules/local.rules tập tin.

Gửi cho Suricata SIGUSR2 ra hiệu để yêu cầu nó tải lại chữ ký của nó:

  • sudo kill -usr2 $(pidof suricata)

Bây giờ hãy kiểm tra quy tắc bằng cách sử dụng curl:

  • curl --max-time 5 http://testmynids.org/uid/index.html

Bạn sẽ nhận được lỗi cho biết rằng yêu cầu đã hết thời gian chờ, điều này cho thấy Suricata đã chặn phản hồi HTTP:

Output

curl: (28) Operation timed out after 5000 milliseconds with 0 out of 39 bytes received

Bạn có thể xác nhận rằng Suricata đã bỏ phản hồi HTTP bằng cách sử dụng jq để kiểm tra eve.log tập tin:

  • jq 'select(.alert .signature_id==2100498)' /var/log/suricata/eve.json

Bạn sẽ nhận được đầu ra như sau:

Output

{ . . . "community_id": "1:tw19kjR2LeWacglA094gRfEEuDU=", "alert": { "action": "blocked", "gid": 1, "signature_id": 2100498, "rev": 7, "signature": "GPL ATTACK_RESPONSE id check returned root", "category": "Potentially Bad Traffic", "severity": 2, "metadata": { "created_at": [ "2010_09_23" ], "updated_at": [ "2010_09_23" ] } }, "http": { "hostname": "testmynids.org", "url": "/uid/index.html", "http_user_agent": "curl/7.68.0", "http_content_type": "text/html", "http_method": "GET", "protocol": "HTTP/1.1", "status": 200, "length": 39 }, . . .

Đánh dấu "action": "blocked" dòng xác nhận rằng chữ ký khớp và Suricata đã bỏ hoặc từ chối yêu cầu HTTP thử nghiệm.

Sự kết luận

Trong hướng dẫn này, bạn đã định cấu hình Suricata để chặn lưu lượng mạng đáng ngờ bằng cách sử dụng chế độ IPS tích hợp của nó. Bạn cũng đã thêm chữ ký tùy chỉnh để kiểm tra và chặn lưu lượng SSH, HTTP và TLS trên các cổng không chuẩn. Để gắn kết mọi thứ với nhau, bạn cũng đã thêm các quy tắc tường lửa để hướng lưu lượng truy cập qua Suricata để xử lý.

Bây giờ bạn đã cài đặt và định cấu hình Suricata ở chế độ IPS và có thể viết chữ ký của riêng mình để cảnh báo hoặc giảm lưu lượng đáng ngờ, bạn có thể tiếp tục theo dõi máy chủ và mạng của mình cũng như tinh chỉnh chữ ký của mình.

Khi bạn hài lòng với chữ ký và cấu hình Suricata của mình, bạn có thể tiếp tục với hướng dẫn cuối cùng trong loạt bài này, hướng dẫn này sẽ hướng dẫn bạn cách gửi nhật ký từ Suricata đến hệ thống Quản lý sự kiện thông tin và bảo mật (SIEM) được xây dựng bằng Elastic Stack.

.

Check Also

Cách cung cấp các ứng dụng Flask với Gunicorn và Nginx trên Ubuntu

Giới thiệu Trong hướng dẫn này, bạn sẽ xây dựng một ứng dụng Python bằng …