Kiểm soát lưu lượng Linux (tc): Hướng dẫn thực hành

12 phút đọc - 5 tháng 6, 2026

hero section cover
Mục lục
  • Kiểm soát lưu lượng Linux (tc): Hướng dẫn thực hành
  • Cách tc hoạt động
  • Cài đặt tc trên máy chủ Linux
  • Điều chỉnh lưu lượng đi ra bằng HTB
  • Điều chỉnh lưu lượng truy cập đến bằng IFB
  • Ưu tiên lưu lượng với DSCP
  • Giám sát và khắc phục sự cố
Chia sẻ

Kiểm soát băng thông, ưu tiên lưu lượng và định hình lưu lượng vào và ra trên Linux bằng tc. Cấu hình HTB, IFB, DSCP và fq_codel hoạt động cho các máy chủ thực tế.

Kiểm soát lưu lượng Linux (tc): Hướng dẫn thực hành

Lệnh tc cho phép bạn kiểm soát trực tiếp cách máy chủ xử lý lưu lượng mạng. Bạn có thể giới hạn băng thông cho từng dịch vụ, duy trì phản hồi của các phiên tương tác như SSH khi lưu lượng truyền tải hàng loạt tăng đột biến, và định hình cả lưu lượng đi và đến từ một công cụ duy nhất. Hướng dẫn này bao gồm các khái niệm cốt lõi, thiết lập HTB hoạt động, định hình lưu lượng vào bằng IFB, ưu tiên dựa trên DSCP, và cách gỡ lỗi khi có sự cố.


 

Cách tc hoạt động

Mỗi tc cấu hình được xây dựng từ bốn thành phần chính:

  • qdisc (kỷ luật xếp hàng). Bộ lập lịch được gắn với giao diện mạng. Nó quyết định cách các gói tin được xếp vào hàng đợi và lấy ra khỏi hàng đợi.
  • Class. Một phân nhóm bên trong qdisc có phân lớp. Hãy nghĩ về nó như một làn đường có giới hạn tốc độ riêng.
  • Filter. Kiểm tra tiêu đề gói tin (địa chỉ IP, cổng, dấu hiệu) và gán mỗi gói tin vào một lớp.
  • Hành động. Điều gì xảy ra với một gói tin khi nó khớp: chuyển tiếp, loại bỏ, chuyển hướng.

Các thành phần này tạo thành một cây. Các gói tin đi vào tại qdisc gốc, đi qua các bộ lọc, được phân loại vào các lớp bằng một major:minor handle, và cuối cùng được xếp hàng tại qdisc lá để truyền tải.

Đối với bất kỳ điều gì phức tạp hơn so với việc khớp dựa trên cổng, hãy đánh dấu các gói tin bằng iptables hoặc nftables trong bảng mangle, sau đó sử dụng fw bộ lọc trong tc để phân loại theo dấu. Cách này mở rộng quy mô tốt hơn nhiều so với việc xâu chuỗi các quy tắc thô u32 cho từng loại lưu lượng.

Lưu lượng đi so với lưu lượng đến

Hướng đi rất quan trọng. Kernel có thể đệm và trì hoãn các gói tin đi, đây chính là yếu tố cho phép định hình lưu lượng thực sự. Các gói tin đến đã đi qua đường truyền khi bạn nhìn thấy chúng, vì vậy bạn chỉ có thể kiểm soát chúng (bỏ qua khi vượt ngưỡng) trừ khi bạn chuyển hướng chúng đến một thiết bị IFB trước.

Tính năngRaIngress
HướngRaĐến
Điều chỉnhBản địaYêu cầu IFB
Kiểm soátĐược hỗ trợĐược hỗ trợ
Ứng dụng điển hìnhQoS, chia sẻ băng thông, điều tiếtGiới hạn tốc độ, giảm thiểu DDoS cơ bản

Các qdisc bạn sẽ thực sự sử dụng

  • HTB (Hierarchical Token Bucket). Có phân lớp. Sử dụng khi bạn muốn đảm bảo băng thông tối thiểu cho mỗi dịch vụ với khả năng mượn dung lượng chưa sử dụng từ các lớp khác.
  • TBF (Token Bucket Filter). Không phân lớp. Sử dụng khi bạn chỉ cần giới hạn toàn bộ giao diện ở một tốc độ duy nhất.
  • fq_codel (Fair Queuing Controlled Delay). Kết hợp tính công bằng theo luồng với quản lý hàng đợi chủ động để loại bỏ hiện tượng bufferbloat. Đây là qdisc mặc định trong hầu hết các bản phân phối Linux kể từ systemd 217 và được cài đặt mặc định trên RHEL 9. Luôn gắn nó làm qdisc lá dưới các lớp HTB, nếu không một luồng tham lam duy nhất có thể chiếm dụng toàn bộ lớp.

Cài đặt tc trên máy chủ Linux

tc được cung cấp cùng với gói iproute2. Trên Debian và Ubuntu, hãy cài đặt nó bằng apt-get install iproute2. Trên RHEL và các phiên bản phái sinh, yum install iproute. Bạn sẽ cần quyền root hoặc sudo.

Trước tiên, hãy xác định tên giao diện chính xác. Đặt tên giao diện sai là lý do phổ biến nhất khiến cấu hình không hoạt động mà không có thông báo lỗi:

ip link show

Kiểm tra những gì đã có trên giao diện, bao gồm các bộ đếm thời gian thực:

tc -s qdisc show dev eth0

Xóa bất kỳ qdisc gốc nào hiện có trước khi áp dụng cấu hình mới, để tránh RTNETLINK answers: File exists lỗi:

tc qdisc del dev eth0 root 2>/dev/null || true

Nếu bạn đang cập nhật một quy tắc hiện có thay vì bắt đầu từ đầu, hãy sử dụng replace thay vì add để thực hiện hoán đổi nguyên tử.

Các tính năng giảm tải phần cứng như TSO và GSO gộp các gói tin theo cách gây cản trở cho việc định hình lưu lượng. Hãy tắt chúng trên giao diện được định hình:

sudo ethtool -K eth0 tso off gso off

Đặt fq_codel làm qdisc mặc định trên toàn hệ thống cho các giao diện mới:

sysctl -w net.core.default_qdisc=fq_codel

Đối với các máy chủ bận rộn, hãy kết hợp nó với thuật toán kiểm soát tắc nghẽn BBR (kernel 4.9+). BBR duy trì thông lượng cao mà không làm tăng hàng đợi:

sysctl -w net.ipv4.tcp_congestion_control=bbr

Một thói quen an toàn nếu bạn đang cấu hình một máy chủ từ xa qua SSH: mở một phiên thứ hai và chuẩn bị sẵn tc qdisc del dev eth0 root sẵn sàng để dán. Một quy tắc lọc sai có thể khiến bạn bị khóa ngay lập tức.

Điều chỉnh lưu lượng đi ra bằng HTB

HTB cho phép bạn đặt mức tối thiểu được đảm bảo (rate) và mức tối đa (ceil). Băng thông chưa sử dụng sẽ được phân bổ cho những ai cần, theo thứ tự ưu tiên. Dưới đây là cấu hình ba tầng hoạt động cho kết nối uplink 1 Gbps.

Tạo qdisc HTB gốc. default 30 sẽ gửi bất kỳ gói tin nào chưa được phân loại vào lớp 1:30 thay vì để nó bỏ qua các quy tắc của bạn:

tc qdisc add dev eth0 root handle 1: htb default 30

Giới hạn tổng thông lượng ở mức 900 Mbps. Luôn định hình ở mức thấp hơn một chút so với dung lượng liên kết thực tế, nếu không, hàng đợi sẽ hình thành trên bộ định tuyến hoặc modem ngược dòng mà bạn không kiểm soát được:

tc class add dev eth0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbit

Xác định các cấp dịch vụ. Các giá trị prio sẽ được ưu tiên sử dụng băng thông chưa sử dụng trước:

# High priority: web and API traffic
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 500mbit ceil 900mbit prio 1
 
# Medium priority: database replication
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 300mbit ceil 900mbit prio 2
 
# Low priority: bulk and backup traffic
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 100mbit ceil 900mbit prio 3

Gắn fq_codel làm qdisc lá trên mỗi lớp để một luồng duy nhất không thể chi phối cấp độ của nó:

tc qdisc add dev eth0 parent 1:10 handle 10: fq_codel
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel
tc qdisc add dev eth0 parent 1:30 handle 30: fq_codel

Bây giờ hãy phân loại lưu lượng. Đối với việc khớp cổng đơn giản, u32 là nhanh nhất:

tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
  match ip dport 443 0xffff flowid 1:10

Đối với bất kỳ trường hợp nào có trạng thái, hãy đánh dấu trong iptables và khớp dấu đó với fw:

iptables -t mangle -A OUTPUT -p tcp --dport 5432 -j MARK --set-mark 2
tc filter add dev eth0 protocol ip parent 1:0 prio 2 handle 2 fw flowid 1:20

Điều chỉnh lưu lượng truy cập đến bằng IFB

Bạn không thể định hình lưu lượng vào một cách nguyên bản vì khi gói tin đến, nó đã sử dụng băng thông của bạn. Giải pháp là chuyển hướng lưu lượng vào sang giao diện ảo Intermediate Functional Block (IFB), nơi kernel xử lý nó như lưu lượng ra và cho phép bạn áp dụng qdiscs theo lớp.

Tải mô-đun và khởi động giao diện:

modprobe ifb numifbs=1
ip link set dev ifb0 up

Thêm một qdisc vào giao diện vật lý và chuyển hướng mọi thứ đến ifb0:

tc qdisc add dev eth0 ingress handle ffff:
tc filter add dev eth0 parent ffff: protocol all u32 \
  match u32 0 0 action mirred egress redirect dev ifb0

Từ đây, ifb0 nó hoạt động giống như bất kỳ giao diện nào khác. Áp dụng cây HTB của bạn vào nó chính xác như cách bạn làm với lưu lượng ra:

tc qdisc add dev ifb0 root handle 1: htb default 30
tc class add dev ifb0 parent 1: classid 1:1 htb rate 900mbit ceil 900mbit
tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 500mbit ceil 900mbit prio 1

Ưu tiên lưu lượng với DSCP

DSCP (Differentiated Services Code Point) gắn thẻ các gói tin với giá trị 6 bit trong byte TOS, do đó tc có thể phân loại theo thẻ thay vì phải tìm kiếm các cổng trong bộ quy tắc. Khi so khớp DSCP trong tc, hãy dịch giá trị sang trái 2 bit. DSCP EF (46) sẽ trở thành 0xb8. Mặt nạ 0xfc tách 6 bit DSCP khỏi 2 bit ECN.

Một bản đồ mặc định hợp lý cho các tải công việc máy chủ:

Loại lưu lượngDSCPTOS hexVí dụ
Tương tácEF0xb8SSH, DNS, VoIP
Doanh nghiệpAF410x88HTTP, HTTPS, API
Đồng loạtCS10x20Sao lưu, FTP, cập nhật gói phần mềm
Nỗ lực tối đaCS00x00Mọi thứ khác

Đánh dấu các gói tin đi trong iptables trước khi chúng chạm đến tc bộ lọc:

iptables -t mangle -A OUTPUT -p tcp --dport 22 -j DSCP --set-dscp 46

Sau đó, so khớp thẻ trong tc và định tuyến nó đến lớp HTB phù hợp:

# EF (SSH, VoIP) goes to the high-priority class
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
  match ip tos 0xb8 0xfc flowid 1:10
 
# AF41 (web traffic) goes to the medium class
tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 \
  match ip tos 0x88 0xfc flowid 1:20
 
# CS1 (bulk) goes to the low-priority class
tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 \
  match ip tos 0x20 0xfc flowid 1:30

Giám sát và khắc phục sự cố

Ba lệnh bạn sẽ sử dụng thường xuyên:

tc -s qdisc show dev eth0
tc -s class show dev eth0
tc -s filter show dev eth0

Theo dõi droppedoverlimits các bộ đếm. Các gói tin bị bỏ qua có nghĩa là hàng đợi đã bão hòa; các giá trị vượt ngưỡng có nghĩa là bạn đã đạt đến giới hạn của lớp và nhân hệ thống phải trì hoãn hoặc loại bỏ lưu lượng. Để xem trực tiếp:

watch -n 1 'tc -s class show dev eth0'

Thêm -d cho các tham số nội bộ (target, interval, quantum) và -j cho đầu ra JSON nếu bạn đang chuyển dữ liệu vào hệ thống theo dõi chỉ số. Kết hợp với ss -tin để xem ước tính RTT và các lần truyền lại ở lớp TCP.

Hầu hết các lỗi đều thuộc một danh sách ngắn:

Triệu chứngNguyên nhân có thểCách khắc phục
RTNETLINK answers: File existsqdisc gốc đã được cấu hìnhtc qdisc del dev eth0 root đầu tiên
Các quy tắc được áp dụng nhưng lưu lượng không bị giới hạnGiao diện sai, hoặc TSO/GSO vẫn đang hoạt độngXác nhận bằng ip link show, vô hiệu hóa các chức năng offload bằng ethtool -K
Bộ lọc không bao giờ khớpCú pháp cổng/IP hoặc sự căn chỉnh mặt nạ không đúngThêm một hành động phản hồi và kiểm tra số lần trúng trong tc -s filter show
Quy tắc biến mất sau khi khởi động lạiCấu hình chỉ tồn tại trong bộ nhớĐóng gói trong một tập lệnh và gọi từ systemd hoặc bộ điều phối NetworkManager
Độ trễ cao trên lưu lượng ưu tiênKhông có qdisc lá, hoặc độ bùng nổ quá thấpGắn fq_codel vào các lớp leaf, tăng burst

Nếu bạn vô tình bị khóa ngoài do cấu hình sai, việc khôi phục rất đơn giản:

tc qdisc del dev eth0 root

tc không thể tạo ra băng thông mà bạn không có, nhưng trên một đường truyền lên được cung cấp đầy đủ, điều này tạo ra sự khác biệt giữa hiệu suất có thể dự đoán được và một máy chủ bị sập ngay khi một khách hàng bắt đầu một quá trình truyền tải dữ liệu lớn. Nếu bạn cần băng thông thô và sự tự do để định hình nó theo ý muốn, hãy xem xét các máy chủ chuyên dụng của FDC.

Blog

Nổi bật trong tuần

Các bài viết khác
Kiểm soát lưu lượng Linux (tc): Hướng dẫn thực hành

Kiểm soát lưu lượng Linux (tc): Hướng dẫn thực hành

Kiểm soát băng thông, ưu tiên lưu lượng và định hình lưu lượng vào và ra trên Linux bằng tc. Cấu hình HTB, IFB, DSCP và fq_codel hoạt động cho các máy chủ thực tế.

12 phút đọc - 5 tháng 6, 2026

Tại sao việc sở hữu một VPS mạnh mẽ và không giới hạn băng thông lại quan trọng

7 phút đọc - 9 tháng 5, 2025

Các bài viết khác
background image

Bạn có thắc mắc hoặc cần giải pháp tùy chỉnh?

icon

Các tùy chọn linh hoạt

icon

Phạm vi toàn cầu

icon

Triển khai ngay lập tức

icon

Các tùy chọn linh hoạt

icon

Phạm vi toàn cầu

icon

Triển khai ngay lập tức