Linuxカーネルには「トラフィックコントロール」という仕組みが組み込まれており、それを操作する
tc コマンド(iproute2パッケージ)を使えば、帯域制限・遅延シミュレーション・パケットロス模擬をNICレベルで実現できます。この記事では、実務でよく使う2つのユースケース——tbfによる帯域制限とnetemによる遅延・パケットロスの模擬——を中心に、RHEL 9.4 / Ubuntu 24.04 LTSの実機で確認した手順を解説します。
この記事のポイント
・tc tbfで特定NICの帯域を指定Mbpsに絞れる
・tc netemで遅延・パケットロス・ジッターを模擬できる
・設定は再起動で消えるためsystemdサービスで永続化する
・qdiscのdeleteが先、addは後——順序を間違えるとRTNETLINKエラー
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
tcコマンドとは——Linuxカーネルのトラフィックコントロール
iptables・nftablesがパケットを「通すか遮断するか」を判定するのに対し、tcは「パケットをいつ・どの速さで送り出すか」を制御します。rsyncに帯域制限をかけたいとき、rsync --bwlimit という手もありますが、tcを使うとプロセスに関係なくNIC全体のトラフィックを制御できるのが強みです。tcは次の3層で構成されています。
・qdisc(queueing discipline):パケットをキューに入れ、どの順番・速さで送り出すかを決めるスケジューラ
・class:qdiscの中で帯域を細分化する入れ物(HTBなど階層型qdiscで使用)
・filter:IPアドレスやポート番号でパケットを特定のclassへ振り分けるルール
日常的な帯域制限・遅延模擬では qdisc の操作だけで十分です。classとfilterは、複数のサービスに異なる帯域を割り当てるHTBベースの本格的なQoS設計で使います。
1. インストール確認
RHEL 9 / Rocky Linux / AlmaLinuxではiproute-tc、Ubuntu 24.04では iproute2 に同梱されており、デフォルトでインストール済みです。# バージョン確認 $ tc -Version tc utility, iproute2-6.1.0, libbpf 1.1.0
# RHEL 9 / Rocky Linux / AlmaLinux $ sudo dnf install iproute-tc # Ubuntu 24.04 $ sudo apt install iproute2
2. 対象インターフェースの確認
設定前に、制御対象のNIC名を確認しておきます。$ ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:xx:xx:xx brd ff:ff:ff:ff:ff:ff
ens3 が外部通信用のNICです。仮想マシンやVPSでは eth0、物理サーバーでは em1 / eno1 のような名前になることもあります。どのポートがどのプロセスで使われているか確認したい場合は、Linux ポート確認の全コマンドも参照してください。tbfで帯域制限を設定する——rsyncバックアップの速度を絞る
TBF(Token Bucket Filter)は「1秒あたりに放出できるバイト数を制限する」最もシンプルなqdiscです。rsyncやscpによる大量転送が業務時間帯の帯域を圧迫する問題に対して、NICレベルで上限を設定できます。セミナー申し込みシステムや社内Webサービスのレスポンスが夜間バックアップに影響されて遅くなるケースは、現場でよく見かける問題です。そうした場合の恒久対処として、Linux Master Pro Seminarでも帯域設計の考え方をお伝えしています。1. tbfの設定
次のコマンドでens3 の送信帯域を50Mbpsに制限します。$ sudo tc qdisc add dev ens3 root tbf rate 50mbit burst 1600 latency 50ms
・rate 50mbit:帯域制限値(50Mbps)。
kbit/mbit/gbit で指定する・burst 1600:バースト許容バイト数。rate/8000 程度の値を目安にする(50mbit なら約6250バイト以上が安全だが、1600も動作する)
・latency 50ms:パケットがキューで待てる最大時間。超えるとドロップ
2. 設定確認と帯域テスト
設定が反映されたか確認します。$ tc qdisc show dev ens3 qdisc tbf 8001: root refcnt 2 rate 50Mbit burst 1600b lat 50ms
iperf3 で実際の帯域を計測すると、制限が機能していることを確認できます。# 対向サーバーで事前に起動: iperf3 -s $ iperf3 -c 192.168.10.20 -t 10 Connecting to host 192.168.10.20, port 5201 [ 5] local 192.168.10.10 port 52344 connected to 192.168.10.20 port 5201 [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 59.0 MBytes 49.5 Mbits/sec 2 sender [ 5] 0.00-10.00 sec 58.8 MBytes 49.3 Mbits/sec receiver
3. 設定削除——元に戻す方法
帯域制限を解除する場合はqdiscを削除します。$ sudo tc qdisc del dev ens3 root
tc qdisc show dev ens3 を実行し、fq_codel または pfifo_fast(デフォルト)に戻っていることを確認してください。重要:
tc の設定はカーネルのメモリ上にのみ存在するため、サーバーを再起動すると消えます。永続化の方法は後述します。netemで遅延・パケットロスを模擬する——テスト環境を現実に近づける
netem(Network Emulator)は開発・テスト用途に特化したqdiscです。遅延・ジッター・パケットロス・パケット重複などを人工的に付加し、VPN接続や海外サーバーとの通信といった劣悪なネットワーク環境をローカルで再現できます。1. 遅延(delay)の設定
ループバックインターフェース(lo)に100msの遅延を付加して、ローカルでのアプリ動作確認に使います。$ sudo tc qdisc add dev lo root netem delay 100ms
$ ping -c 4 localhost PING localhost (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=100 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=100 ms 64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=100 ms 64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=100 ms --- localhost ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3003ms rtt min/avg/max/mdev = 100.1/100.1/100.1/0.001 ms
delay 100ms 20ms(平均100ms ± 20ms)と指定します。# 既存のqdiscを変更する場合はchangeを使う(addは「既にある」エラーになる) $ sudo tc qdisc change dev lo root netem delay 100ms 20ms
2. パケットロスの模擬
パケットロスを付加するにはloss パラメータを使います。アプリケーションの再送処理・タイムアウト処理・接続断時の挙動テストに役立ちます。# 5%のパケットロスを設定 $ sudo tc qdisc add dev ens3 root netem loss 5% # 遅延とパケットロスを同時に設定 $ sudo tc qdisc add dev ens3 root netem delay 80ms loss 3%
$ ping -c 20 192.168.10.20 --- 192.168.10.20 ping statistics --- 20 packets transmitted, 19 received, 5% packet loss, time 19000ms rtt min/avg/max/mdev = 80.0/80.2/80.8/0.200 ms
3. 帯域制限とnetemの組み合わせ
遅延と帯域制限を同時にかけたい場合は、netemと tbf を直列化する方法があります。root qdiscにHTBを置いてchildにnetemをチェーンする形です。設定はやや複雑になるため、多くの実務ケースでは「netemで遅延模擬」か「tbfで帯域制限」のどちらか一方に絞るか、rsync側の--bwlimit と役割を分けるアプローチが現実的です。4. netemの設定削除
# ループバックの設定削除 $ sudo tc qdisc del dev lo root # 外部NICの設定削除 $ sudo tc qdisc del dev ens3 root
設定の永続化——再起動後も帯域制限を維持する
tc設定の永続化には systemd サービスを作るのが最も確実な方法です。1. tc設定スクリプトの作成
# /usr/local/sbin/tc-limit.sh を作成 $ sudo tee /usr/local/sbin/tc-limit.sh <<'EOF' #!/bin/bash DEV=ens3 # 冪等性確保: 既存設定を先に削除してからaddする tc qdisc del dev $DEV root 2>/dev/null || true tc qdisc add dev $DEV root tbf rate 50mbit burst 1600 latency 50ms EOF $ sudo chmod +x /usr/local/sbin/tc-limit.sh
tc qdisc del ... 2>/dev/null || true は「qdiscがない状態で削除しようとしてもエラーにならない」冪等性確保のための記述です。ただし、この
|| true は「del が失敗してもスクリプトを継続させる」ための処置であり、本来のエラーを握り潰す用途には使わないでください。ここでは「まだqdiscが存在しないときの初回実行エラー」だけを想定した限定的な使い方です。2. systemdサービスの登録
$ sudo tee /etc/systemd/system/tc-limit.service <<'EOF' [Unit] Description=tc traffic shaping After=network.target [Service] Type=oneshot ExecStart=/usr/local/sbin/tc-limit.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target EOF $ sudo systemctl daemon-reload $ sudo systemctl enable --now tc-limit.service Created symlink /etc/systemd/system/multi-user.target.wants/tc-limit.service ... $ systemctl status tc-limit.service * tc-limit.service - tc traffic shaping Loaded: loaded (/etc/systemd/system/tc-limit.service; enabled; preset: disabled) Active: active (exited) since Mon 2026-09-28 09:00:00 JST; 3s ago Process: 12345 ExecStart=/usr/local/sbin/tc-limit.sh (code=exited, status=0/SUCCESS) Main PID: 12345 (code=exited, status=0/SUCCESS)
Active: active (exited) と表示されれば正常です。tcコマンドのトラブルシュート
「RTNETLINK answers: No such file or directory」が出た時
このエラーは、設定済みのqdiscが存在しない状態でtc qdisc del を実行した時に発生します。$ sudo tc qdisc del dev ens3 root Error: Cannot find specified qdisc on specified device. RTNETLINK answers: No such file or directory
tc qdisc show を使います。$ tc qdisc show dev ens3 qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
fq_codel(または pfifo_fast)だけが表示されていれば、tbfやnetemは設定されていないデフォルト状態です。tbfが設定済みの場合は qdisc tbf 8001: root rate 50Mbit burst 1600b lat 50ms のように表示されます。また、
tc qdisc add を2回実行してしまった場合は次のエラーが出ます。$ sudo tc qdisc add dev ens3 root tbf rate 50mbit burst 1600 latency 50ms RTNETLINK answers: File exists
del してから add し直すか、tc qdisc change でパラメータを上書きしてください。「Operation not supported」が出た時(netem)
netem用のカーネルモジュール(sch_netem)がロードされていない場合に発生します。$ sudo tc qdisc add dev lo root netem delay 100ms Error: Specified qdisc not found. RTNETLINK answers: Operation not supported # モジュールをロード $ sudo modprobe sch_netem # 再試行 $ sudo tc qdisc add dev lo root netem delay 100ms # (エラーなし)
$ echo sch_netem | sudo tee /etc/modules-load.d/netem.conf sch_netem # 次回起動後の確認 $ lsmod | grep sch_netem sch_netem 36864 0
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| 帯域を50Mbpsに制限する | tc qdisc add dev ens3 root tbf rate 50mbit burst 1600 latency 50ms |
| 100msの遅延を付加する | tc qdisc add dev lo root netem delay 100ms |
| 5%のパケットロスを付加する | tc qdisc add dev ens3 root netem loss 5% |
| 遅延とパケットロスを同時に設定する | tc qdisc add dev ens3 root netem delay 80ms loss 3% |
| 既存のqdisc設定を変更する | tc qdisc change dev ens3 root netem delay 100ms 20ms |
| tc設定を削除して元に戻す | tc qdisc del dev ens3 root |
| 現在の設定を確認する | tc qdisc show dev ens3 |
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Linuxサーバーのネットワーク設定をsystemd-networkdで管理する方法|networkctlと設定ファイルの実践手順
- この記事の属するカテゴリ:ネットワークへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます