Новинка Виртуальный VDS сервер в Финляндии от 390р
Выберите продукт

Учёт и контроль трафика на 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-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

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, добавьте точечные ограничения для «тяжёлых» сервисов и не забывайте проверять отчёты хотя бы раз в неделю. Так вы превратите трафик из зоны риска в управляемый ресурс.

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

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

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...