Выберите продукт

Учёт и контроль трафика на VDS: vnStat, nload, tc и базовые лимиты

Как следить за трафиком на VDS и не вылетать за лимиты? Разбираем практику: vnStat для истории, nload для онлайна, tc/HTB для ограничения полосы, ingress через ifb и базовые лимиты в сервисах. Чёткие команды, типовые сценарии, отладка и лайфхаки.
Учёт и контроль трафика на VDS: vnStat, nload, tc и базовые лимиты

Когда речь про VDS заходит в плоскость расходов, «трафик» оказывается одним из самых непрозрачных пунктов. В одном месяце — тишина, в другом — скачивания обновлений, бэкапы, отладка, внезапные импорты и потоковые выгрузки. Без мониторинга и простых ограничений скорость легко уходит в сотни мегабит в секунду, а месячный объём — в сотни гигабайт. В этой статье соберём минимально необходимый набор практик и утилит: vnStat для учёта, nload для живого графика и tc для шейпинга. Плюс покажем «базовые лимиты» на уровне сервисов, чтобы не превращать ваш сервер в CDN. Если вам нужен отдельный стенд для тестов — поднимите недорогой VDS и отладьте шейпинг без влияния на прод.

О чём мы считаем и что контролируем

Прежде чем ставить инструменты, договоримся о терминах:

  • Трафик — объём переданных данных, как правило, в байтах/гигабайтах (но скорость чаще в битах: Мбит/с).
  • Направления: egress (исходящий) и ingress (входящий). Провайдеры тарифицируют по-разному, но следить нужно за обоими.
  • PPS (packets per second) важен для сетевой нагрузки на ядро и виртуальный свитч: высокая PPS при слабом CPU убивает латентность.
  • Учет по интерфейсам: для VM это обычно eth0, ens3, ens18 — смотрите вывод ip -br link.
  • 95‑й перцентиль — популярная схема биллинга в датацентрах, но большинству достаточно помесячных сумм по интерфейсу.

Цель — видеть историю, понимать текущую нагрузку и иметь «рубильник» на случай утечки или всплеска.

Инструменты: что и для чего

  • vnStat — лёгкий сборщик помесячной/по-дневной статистики по интерфейсу. Работает без сниффинга, берёт счетчики ядра, почти не грузит систему.
  • nload — живой график скорости RX/TX в терминале. Удобно для оперативной диагностики.
  • tc — ядровой инструмент управления очередями. Позволяет ограничивать скорость, задавать приоритеты, шейпить ingress через ifb.

Схема шейпинга трафика через tc: HTB и ifb для ingress/egress

vnStat: установка и первичная настройка

Установка

# Debian/Ubuntu
sudo apt update
sudo apt install vnstat

# RHEL/CentOS/Rocky/Alma
sudo dnf install vnstat

# Alpine
sudo apk add vnstat

После установки убедитесь, что демон запустился и знает о вашем интерфейсе:

sudo systemctl enable --now vnstat
sudo systemctl status vnstat
vnstat --iflist

Если нужного интерфейса нет в базе, добавьте его и перезапустите службу:

sudo vnstat -u -i ens18
sudo systemctl restart vnstat

База данных и ретеншн

vnStat хранит агрегированную статистику. Сразу после установки графики будут пустыми — нужен хотя бы час-другой для накопления. В конфиге /etc/vnstat.conf можно задать хранение по дням/месяцам, часовую зону и поведение при переименовании интерфейсов.

Полезные команды

# Суммарно по интерфейсу
vnstat -i ens18

# По дням
vnstat -i ens18 -d

# По часам
vnstat -i ens18 -h

# По месяцам
vnstat -i ens18 -m

# Короткий «замер секундомером» (текущая скорость за интервал)
vnstat -i ens18 -tr 5

# Непрерывный режим (почти как top)
vnstat -i ens18 -l

# JSON-вывод — удобно для автоматизации
vnstat -i ens18 --json

Практический приём: заведите еженедельную сверку трафика с бюджетом. Например, если ваш лимит 2 ТБ/месяц, то после первой недели смотрите, не ушли ли выше ~25% по vnstat -m. В случае отклонений — включайте шейпинг и проверяйте источники нагрузки. Полезно начать с харденинга базовых настроек — пригодится чек-лист из статьи Безопасность VDS: SSH и firewall.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

nload: оперативный график в терминале

nload не хранит историю, зато отлично показывает «здесь и сейчас». Он полезен в момент происшествия: бьётся ли канал в потолок, симметричны ли RX/TX, какие пики и средние.

# Установка
sudo apt install nload

# Запуск по интерфейсу
nload ens18

Горячие клавиши внутри nload позволят переключать интервал усреднения и масштаб. Если интерфейсов несколько, без параметров утилита покажет список для выбора.

tc: основы шейпинга и очередей

tc работает с очередями (qdisc) на интерфейсе. Для ограничений скорости удобно использовать htb (иерархические токены) с листовой очередью fq_codel для борьбы с буферблоатом. Важно различать направления: исходящий (egress) можно ограничить прямо на интерфейсе, входящий (ingress) — через виртуальный интерфейс ifb, на который трафик перекачивается и уже там шейпится.

Ограничение исходящего (egress) через HTB

Пример: ограничим исходящий канал интерфейса ens18 до 50 Мбит/с.

#!/usr/bin/env bash
set -e
IF=ens18
RATE=50mbit

# Сброс старых очередей
sudo tc qdisc del dev "$IF" root 2>/dev/null || true

# Корневая HTB и класс
sudo tc qdisc add dev "$IF" root handle 1: htb default 10
sudo tc class add dev "$IF" parent 1: classid 1:10 htb rate "$RATE" ceil "$RATE"

# Листовая очередь fq_codel
sudo tc qdisc add dev "$IF" parent 1:10 handle 10: fq_codel

# Проверка
sudo tc -s qdisc show dev "$IF"
sudo tc -s class show dev "$IF"

Ключи rate и ceil задают гарантированную и максимальную скорость, обычно их держат равными. Единицы измерения: kbit, mbit, gbit.

Ограничение входящего (ingress) через ifb

Входящий трафик невозможно «притормозить» на реальном интерфейсе до приёма пакетов, поэтому используется ifb: пакеты перехватываются в ingress и перенаправляются в ifb0, где и шейпятся как исходящие.

#!/usr/bin/env bash
set -e
IF=ens18
IFB=ifb0
RATE=30mbit

# Модуль ifb и поднятие интерфейса
sudo modprobe ifb numifbs=1 || true
sudo ip link add "$IFB" type ifb 2>/dev/null || true
sudo ip link set dev "$IFB" up

# Сброс очередей
sudo tc qdisc del dev "$IF" ingress 2>/dev/null || true
sudo tc qdisc del dev "$IFB" root 2>/dev/null || true

# Перехват ingress и редирект в ifb
sudo tc qdisc add dev "$IF" handle ffff: ingress
sudo tc filter add dev "$IF" parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev "$IFB"

# Шейпинг на ifb
sudo tc qdisc add dev "$IFB" root handle 1: htb default 10
sudo tc class add dev "$IFB" parent 1: classid 1:10 htb rate "$RATE" ceil "$RATE"
sudo tc qdisc add dev "$IFB" parent 1:10 handle 10: fq_codel

# Проверка
sudo tc -s qdisc show dev "$IFB"

Если ядро не знает об ifb, команда modprobe ifb и параметр numifbs решат вопрос. Уточняйте имя интерфейса на вашей системе.

Пример вывода vnStat с дневной и месячной статистикой

Шейпинг по портам/сервисам

Бывает, что нужно ограничить только определённый сервис, например загрузки по HTTP. Можно повесить фильтр по порту на класс с меньшим лимитом. Пример: не более 10 Мбит/с для TCP-порта 80 исходящего трафика.

#!/usr/bin/env bash
set -e
IF=ens18

# Базовая HTB
sudo tc qdisc del dev "$IF" root 2>/dev/null || true
sudo tc qdisc add dev "$IF" root handle 1: htb default 20
sudo tc class add dev "$IF" parent 1: classid 1:10 htb rate 10mbit ceil 10mbit
sudo tc class add dev "$IF" parent 1: classid 1:20 htb rate 100mbit ceil 100mbit

# fq_codel для листьев
sudo tc qdisc add dev "$IF" parent 1:10 handle 10: fq_codel
sudo tc qdisc add dev "$IF" parent 1:20 handle 20: fq_codel

# Фильтр u32: TCP dport 80 - в класс 1:10
sudo tc filter add dev "$IF" protocol ip parent 1: prio 1 u32 match ip sport 0 0 flowid 1:20
sudo tc filter add dev "$IF" protocol ip parent 1: prio 1 u32 match ip dport 80 0xffff flowid 1:10

# Остальное - по умолчанию в 1:20
sudo tc -s class show dev "$IF"

Для современных ядер удобно использовать фильтр flower или BPF, но u32 по-прежнему работает везде.

Проверка фактической скорости

Для теста заведите пару хостов и запустите замер. Простейший способ — поднять на одной машине сервер iperf3, на другой — клиент. Следите за nload и отчетом iperf3, чтобы убедиться, что шейпер держит потолок без больших очередей и потерь.

# На сервере
iperf3 -s

# На клиенте
iperf3 -c SERVER_IP -t 30

Как сделать шейпер постоянным после перезагрузки

Решений несколько, универсальный вариант — unit для systemd. Он гарантирует порядок запуска/остановки и логирование.

# /etc/systemd/system/tc-shaper.service
[Unit]
Description=TC shaper for ens18
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/tc-shaper up
ExecStop=/usr/local/sbin/tc-shaper down

[Install]
WantedBy=multi-user.target
# /usr/local/sbin/tc-shaper
#!/usr/bin/env bash
set -e
CMD=${1:-up}
IF=ens18
IFB=ifb0
UPRATE=50mbit
DOWNRATE=30mbit

case "$CMD" in
  up)
    # Egress
    tc qdisc del dev "$IF" root 2>/dev/null || true
    tc qdisc add dev "$IF" root handle 1: htb default 10
    tc class add dev "$IF" parent 1: classid 1:10 htb rate "$UPRATE" ceil "$UPRATE"
    tc qdisc add dev "$IF" parent 1:10 handle 10: fq_codel

    # Ingress via ifb
    modprobe ifb numifbs=1 || true
    ip link add "$IFB" type ifb 2>/dev/null || true
    ip link set dev "$IFB" up
    tc qdisc del dev "$IF" ingress 2>/dev/null || true
    tc qdisc del dev "$IFB" root 2>/dev/null || true
    tc qdisc add dev "$IF" handle ffff: ingress
    tc filter add dev "$IF" parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev "$IFB"
    tc qdisc add dev "$IFB" root handle 1: htb default 10
    tc class add dev "$IFB" parent 1: classid 1:10 htb rate "$DOWNRATE" ceil "$DOWNRATE"
    tc qdisc add dev "$IFB" parent 1:10 handle 10: fq_codel
    ;;
  down)
    tc qdisc del dev "$IF" root 2>/dev/null || true
    tc qdisc del dev "$IF" ingress 2>/dev/null || true
    tc qdisc del dev "$IFB" root 2>/dev/null || true
    ip link set dev "$IFB" down 2>/dev/null || true
    ip link del "$IFB" 2>/dev/null || true
    ;;
  *)
    echo "Usage: $0 up|down"
    exit 1
    ;;
esac
sudo chmod +x /usr/local/sbin/tc-shaper
sudo systemctl enable --now tc-shaper

Если вы используете systemd-networkd, также подойдёт скрипт ExecStartPost в unitе сети или директивы PostUp/PreDown в классических конфигурациях сети. Главное — запускать шейпер после поднятия интерфейса.

Базовые лимиты в сервисах: не всегда нужен tc

Не каждый кейс требует ядрового шейпинга. Иногда достаточно ограничить скорость на уровне HTTP‑сервера или утилит.

Nginx: ограничение скорости отдачи

Для больших файлов полезно сэкономить полосу на каждого клиента, не просаживая весь интерфейс. Пример минимальной настройки:

# http-секция
limit_rate_after 1m;
limit_rate 512k;

# location для раздачи
location /downloads/ {
    # можно варьировать лимиты через map или по типам файлов
}

limit_rate_after позволяет сначала отдавать быстро первые мегабайты (ускоряет начало загрузки), а затем включать ограничение. Для лимитов по количеству запросов см. подборку пресетов: Готовые пресеты лимитов в Nginx.

rsync, wget и утилиты

Для фоновых задач часто удобнее не трогать сетевой стек, а ограничить конкретный процесс:

  • rsync --bwlimit=20000 — ограничение примерно до 20 МБ/с.
  • wget --limit-rate=2m — до ~2 МБ/с.

Так вы снижаете пики от бэкапов и обновлений без глобальных ограничений для всех сервисов.

Алёрты и отчёты без сложного мониторинга

Если полноценная система мониторинга ещё не развернута, выручит простая проверка бюджета через vnstat и почтовое уведомление. Идея: раз в день смотреть текущий расход месяца и прогноз.

#!/usr/bin/env bash
IF=ens18
LIMIT_GB=2000
NOW_GB=$(vnstat -m -i "$IF" | awk '/^*[0-9]+\/[0-9]+/ {print $(NF-1)}' | head -n1)
# Примерная оценка: берём среднесуточный расход и экстраполируем
DAYS_PASSED=$(date +%d | sed 's/^0*//')
AVG_PER_DAY=$(echo "scale=2; $NOW_GB / ($DAYS_PASSED)" | bc 2>/dev/null || echo 0)
DAYS_IN_MONTH=$(cal | awk 'NF {D=$NF}; END {print D}')
ESTIMATE=$(echo "scale=0; $AVG_PER_DAY * $DAYS_IN_MONTH" | bc 2>/dev/null || echo 0)

msg="iface=$IF used=${NOW_GB}GiB estimate=${ESTIMATE}GiB limit=${LIMIT_GB}GiB"
[ "$ESTIMATE" -gt "$LIMIT_GB" ] && echo "$msg" | mail -s "Traffic budget warning" root || true

Скрипт грубый, но для первых недель эксплуатации хватит. В проде лучше перейти на метрики и алёрты по порогам скорости и по накоплению трафика.

Частые проблемы и отладка

  • Не тот интерфейс. В виртуалках имена меняются: ens3, ens18, eth0. Проверяйте ip -br link и назначайте корректный интерфейс в vnStat/tc.
  • ifb отсутствует. Модуль ядра не загружен — используйте modprobe ifb и поднимайте ifb0 вручную, как в примере.
  • Очереди накладываются. Если уже есть qdisc на интерфейсе, сначала удалите его: tc qdisc del dev IF root, затем ставьте свой.
  • Единицы измерения. mbit — мегабиты в секунду; не путайте с мегабайтами. 100mbit — это примерно 12.5 МБ/с.
  • Контейнеры и veth. Если шейпите конкретный контейнер, вешайте tc на его vethX, а не только на основной интерфейс.
  • «Не вижу» трафик в vnStat. vnStat читает системные счетчики. Если вы используете бридж/бондинг, учитывайте на каком интерфейсе растёт трафик: br0, bond0 или нижележащие.
  • Пики при скачиваниях. Локальные лимиты в Nginx/rsync помогают сгладить всплески без глобального tc.

Режим эксплуатации: минимальный чек-лист

  • Поставить vnStat, добавить целевой интерфейс, проверить дневные и месячные отчёты.
  • Держать под рукой nload для онлайна.
  • Завести tc-шейпер с HTB+fq_codel и ifb на базовые верхние границы egress/ingress.
  • Сделать автозапуск шейпера unitом systemd.
  • Повесить простую проверку бюджета трафика и алёрт на превышение прогноза.
  • При необходимости ограничить «тяжёлые» сервисы на уровне приложения (Nginx, rsync).

Итоги

Комбинация vnStat + nload даёт прозрачность: вы видите историю и текущую картину. tc с HTB и ifb — это надёжный способ держать канал под контролем, чтобы случайный импорт или бэкап не застрелили ваш бюджет и не ухудшили доступность сервисов. Начните с базовых верхних границ на egress/ingress, добавьте точечные ограничения для «тяжёлых» сервисов и не забывайте проверять отчёты хотя бы раз в неделю. Так вы превратите трафик из зоны риска в управляемый ресурс.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: как подружить /var/log, logrotate и journald и не забить диск OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как подружить /var/log, logrotate и journald и не забить диск

Разбираем, как в Debian/Ubuntu уживаются /var/log, logrotate и systemd-journald. Настроим ограничения SystemMaxUse/MaxRetentionSec ...
MySQL: Got an error reading communication packets — причины, MTU и max_allowed_packet OpenAI Статья написана AI (GPT 5)

MySQL: Got an error reading communication packets — причины, MTU и max_allowed_packet

Ошибка MySQL Got an error reading communication packets обычно связана с сетью, таймаутами или крупными пакетами. В статье — быстр ...
Kubernetes PV/PVC: StorageClass и online resize томов без простоя OpenAI Статья написана AI (GPT 5)

Kubernetes PV/PVC: StorageClass и online resize томов без простоя

Пошагово разбираем безопасное увеличение PVC в Kubernetes без простоя: какие условия нужны в StorageClass (allowVolumeExpansion), ...