Что делать, если в Xray (vless + reality) растёт количество соединений в состоянии CLOSE-WAIT и наблюдаются утечки TCP-сокетов?

На сервере с Xray v26.6.1 (VLESS + Reality) наблюдается стабильный рост TCP-состояний CLOSE-WAIT (и частично TIME-WAIT), из‑за чего со временем падает производительность прокси и часть обслуживания перестаёт работать.
  • 5 июня 2026 г. 16:01
Ответы на вопрос 1
Коротко — CLOSE‑WAIT означает, что удалённая сторона (клиент) закрыла соединение (отправила FIN), а приложение на сервере (Xray) не закрыло свой конец (не вызвало close()). Рост CLOSE‑WAIT = утечка сокетов в приложении (или зависшие горутины/блокировки), и это надо диагностировать и лечить на уровне Xray/конфигурации или обновления. Ниже — практический план действий: как диагностировать, временные обходные пути и долгосрочные решения.

1) Что означает CLOSE‑WAIT и почему это важно
- CLOSE‑WAIT = локальное приложение ещё держит сокет после того, как удалённый закрыл соединение. Это не работает на уровне ядра, это приложение должно закрыть. Накопление таких сокетов ведёт к исчерпанию FD/портов и падению производительности.
- TIME‑WAIT — уже нормальное состояние при закрытии активной стороны TCP; его можно уменьшить настройками ядра, но CLOSE‑WAIT лечится в приложении.

2) Быстрая проверка и сбор текущих метрик
Выполните на сервере:
- Посчитать и показать соединения:
  ss -tanp | grep CLOSE-WAIT
  ss -s
- Посмотреть, какие процессы держат их:
  ss -tanp state close-wait
- Список открытых сокетов/файлов процесса Xray:
  PID=$(pidof xray)
  lsof -nP -p $PID | grep TCP
  ls -l /proc/$PID/fd | grep socket
- Посмотреть /proc/net/tcp (inode у сокетов) и соотнести с /proc/$PID/fd:
  cat /proc/net/tcp
  # сопоставьте inode из /proc/net/tcp со ссылкой socket:[inode] в /proc/$PID/fd

3) Получение стеков goroutine (стек дампов Go) — важно для разработчиков
- Отправьте SIGQUIT процессу, чтобы Go напечатал goroutine dump в stderr / журнал:
  kill -QUIT $PID
  # затем проверьте вывод в journalctl -u xray -e или в файле лога Xray
- Соберите логи (journalctl / var/log) и файлы, полученные на шагах выше — это пригодится для отчёта о баге.

4) Временные смягчающие меры
- Перезапуск Xray как вынужденная мера (останавливает утечку, но не решает причину):
  systemctl restart xray
  # Можно настроить systemd timer для перезапуска в критической ситуации, но это временно.
- Увеличьте лимит открытых дескрипторов (но это лишь отсрочит проблему):
  ulimit -n 200000
  # лучше прописать в systemd Unit: LimitNOFILE=
- Блокируйте/ограничивайте источники, генерирующие много соединений (iptables/nftables, fail2ban), если причина — злостные клиенты.
- Ограничьте количество одновременно открытых соединений для пользователей через policy Xray (чтобы избежать перегрузки от клиентов):
  Пример (в конфиге):
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "downlinkOnly": 0,
        "uplinkOnly": 0
      }
    },
    "system": {
      "statsInboundDownlink": false
    }
  }
  (Адаптируйте под вашу версию и структуру конфига.)

5) Kernel tuning (для TIME‑WAIT и общих сетевых проблем — не исправит CLOSE‑WAIT):
- Для уменьшения эффекта TIME_WAIT (только при необходимости):
  sysctl -w net.ipv4.tcp_tw_reuse=1
  sysctl -w net.ipv4.tcp_fin_timeout=30
  sysctl -w net.ipv4.ip_local_port_range="1024 65000"
  sysctl -w net.core.somaxconn=1024
  # Не используйте tcp_tw_recycle на серверах за NAT — это ломает работу клиентов за NAT.

6) Обновление и проверка известных багов
- Проверьте релиз‑ноуты xray-core и issue tracker — возможно, это известная утечка в вашей версии (v26.6.1). Часто проблемы с конкретными transport/реализациями (Reality/QUIC/аттачменты) исправляются в новых релизах.
- Обновите Xray (или протестируйте свежую версию в тестовом окружении). Многие утечка‑проблемы исправляются в новых релизах.
- Если после обновления проблема остаётся — откройте issue в репозитории xray с собранными данными: ss/lsof, goroutine dump, конфиг (без секретов), версия. Это ускорит расследование.

7) Что собрать перед обращением за помощью (чтобы сократить время диагностики)
- Версия Xray (xray -version)
- Конфиг (обрезать ключи/сертификаты)
- Результаты:
  ss -tanp | grep CLOSE-WAIT > closewait.txt
  lsof -nP -p $PID > lsof.txt
  ls -l /proc/$PID/fd > fds.txt
  kill -QUIT $PID и лог с goroutine dump (journalctl -u xray)
  /proc/$PID/status (FDSize) и ulimit -n
  journalctl -u xray -b > journal.txt
- Количество открытых файлов: ls /proc/$PID/fd | wc -l

8) Дополнительные проверки
- Если Xray работает в контейнере — проверьте, не исчерпывается ли namespace FD/ресурсы контейнера.
- Проверьте наличие сторонних прокси/iptables конфликтов (например, TPROXY/REDIRECT), которые могут оставлять сокеты в состоянии полузакрытых.
- Посмотрите, не виснут ли горутины в чтении/записи (goroutine dump покажет блокировки).

Резюме / Практические шаги сейчас
1. Соберите данные (ss, lsof, goroutine dump).
2. Временно перезапустите Xray и/или ограничьте коннекты политиками и firewall.
3. Попробуйте обновить Xray до последней стабильной версии.
4. Если после обновления проблема остаётся — откройте issue с приложенными логами/дампами.

Если хотите, я могу помочь пошагово: подскажите вывод ss -tanp | grep CLOSE-WAIT и версию xray -version и (скрытый) конфиг inbound для VLESS+Reality — и я подскажу, какие именно сокеты забирать, как собрать goroutine dump и какие настройки policy/системные параметры рекомендовать.
Похожие вопросы