Оптимизация Minecraft сервера для устойчивости к атакам
Большинство администраторов Minecraft-серверов думают о DDoS-защите как о чем-то внешнем. Фильтр трафика, файрвол, анти-DDoS сервис. Всё это правильно и нужно. Но есть вещь, которую часто упускают: сам сервер должен быть оптимизирован так, чтобы выдерживать нагрузку.
Логика простая. Если ваш сервер в нормальном режиме работает на 90% ресурсов, достаточно небольшого всплеска, чтобы он лёг. Если же сервер использует 40-50% ресурсов, у него есть запас прочности. Этот запас (headroom) определяет, переживёт ли сервер атаку или упадёт при первых признаках нагрузки.
В этой статье разберём конкретные шаги оптимизации, которые дают максимальный запас производительности.
Почему производительность = устойчивость
Во время DDoS-атаки на Minecraft-сервер происходит несколько вещей одновременно:
- Растёт число TCP-подключений (SYN flood, bot join)
- Увеличивается потребление CPU на обработку пакетов
- GC-паузы становятся длиннее из-за роста объектов в памяти
- TPS проседает, tick loop замедляется
- Игроки начинают лагать, тайм-аутятся и реконнектятся, создавая ещё больше нагрузки
Это каскадный эффект. Сервер, который и так работал на пределе, входит в спираль деградации. А сервер с запасом производительности может переварить всплеск, пока внешняя защита отсекает ботов.
Подробнее о том, как отличить лаги от атаки, читайте в статье про диагностику лагов.
JVM-флаги: фундамент производительности
Java Virtual Machine - это среда, в которой работает Minecraft-сервер. Настройки JVM напрямую влияют на скорость работы, стабильность GC (сборки мусора) и поведение под нагрузкой.
Aikar's Flags
Стандарт индустрии для Minecraft-серверов. Эти флаги настраивают G1 Garbage Collector для паттернов нагрузки, специфичных для Minecraft:
java -Xms10G -Xmx10G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-XX:SurvivorRatio=32 \
-XX:+PerfDisableSharedMem \
-XX:MaxTenuringThreshold=1 \
-jar server.jar --nogui
Ключевые моменты:
-Xmsи-Xmxодинаковые: это убирает динамическое изменение размера хипа. JVM сразу выделяет всю память и не тратит время на расширение под нагрузкой. Критически важно при атаке, когда memory pressure резко растёт.G1NewSizePercent=30иG1MaxNewSizePercent=40: увеличенный young generation. Minecraft создаёт огромное количество короткоживущих объектов (chunk data, packet buffers, entity ticks). Большой young gen позволяет собирать их дёшево, без full GC.G1HeapRegionSize=8M: оптимальный размер региона для серверов с 8-12 ГБ. Для серверов с 4 ГБ и меньше лучше оставить дефолт.AlwaysPreTouch: JVM при старте "трогает" каждую страницу памяти, заставляя ОС реально выделить физическую память. Без этого флага во время атаки может случиться ситуация, когда JVM пытается получить память, а ОС уже отдала её другим процессам.
Сколько RAM выделять
Распространённая ошибка: "чем больше RAM, тем лучше". Это не так.
Для G1GC существует прямая зависимость: больше хипа = длиннее GC-паузы. Сервер с 32 ГБ хипа может получать GC-паузы в 500-800 мс, что превращается в заметные фризы.
Рекомендации:
- Vanilla/Paper до 30 игроков: 4-6 ГБ
- Paper/Purpur 30-100 игроков: 8-12 ГБ
- Крупные сети 100+ игроков: 12-16 ГБ на инстанс
- Прокси (Velocity/BungeeCord): 512 МБ - 2 ГБ
Не выделяйте больше 16 ГБ на один инстанс. Если нужно больше ресурсов, лучше горизонтальное масштабирование через несколько серверов за прокси.
Диагностика GC-проблем
Как понять, что GC мешает серверу? Включите логирование:
-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=10M
Или используйте Spark:
/spark gc
Признаки проблем:
- GC-паузы длиннее 100 мс появляются чаще раза в минуту
- Full GC происходит вообще (с G1GC быть не должно при правильной настройке)
- Heap occupancy постоянно выше 70%
Если видите эти симптомы, скорее всего проблема в одном из трёх: слишком мало RAM для количества плагинов и игроков, утечка памяти в каком-то плагине, или неправильные JVM-флаги.
GraalVM vs OpenJDK
Для Minecraft 1.17+ стоит рассмотреть GraalVM. Его JIT-компилятор генерирует более оптимальный нативный код, что даёт прирост 10-15% по MSPT (milliseconds per tick). При атаке эти 10-15% могут оказаться разницей между стабильными 20 TPS и просадкой до 15.
# Установка GraalVM
sdk install java 21.0.2-graalce
При выборе Java-версии обратите внимание: Paper 1.20.5+ требует Java 21. Используйте именно ту версию, которую рекомендует ядро вашего сервера. Установка слишком новой или слишком старой Java может привести к неожиданным проблемам с производительностью и совместимостью плагинов.
Настройки Paper/Purpur
Paper (и его форк Purpur) содержит десятки настроек, влияющих на производительность. Правильная конфигурация снижает базовую нагрузку и освобождает ресурсы для обработки всплесков.
paper-global.yml
chunk-loading:
autoconfig-send-distance: true
enable-frustum-priority: false
global-max-chunk-load-rate: 300.0
global-max-chunk-send-rate: 80.0
global-max-concurrent-loads: 6.0
max-concurrent-sends: 2
min-load-radius: 2
player-max-chunk-load-rate: 100.0
player-max-concurrent-loads: 4.0
target-player-chunk-send-rate: 40.0
global-max-chunk-load-rate: ограничивает скорость загрузки чанков. При bot flood на сервер заходят десятки ботов одновременно, каждый триггерит загрузку чанков. Без лимита это мгновенно съедает CPU и диск.global-max-concurrent-loads: критически важно. Ограничивает параллельную загрузку чанков. Дефолтное значение слишком высокое для серверов под атакой.
paper-world-defaults.yml
entities:
spawning:
spawn-limits:
monsters: 50
animals: 8
water-animals: 3
water-ambient: 2
water-underground-creature: 3
axolotls: 3
ambient: 1
tick-rates:
monsters: 2
animals: 4
water-animals: 4
water-ambient: 8
ambient: 8
entity-per-chunk-save-limit:
experience_orb: 16
arrow: 8
area_effect_cloud: 4
environment:
optimize-explosions: true
treasure-maps:
enabled: false
find-already-discovered:
loot-tables: true
villager-trade: true
chunks:
max-auto-save-chunks-per-tick: 6
delay-chunk-unloads-by: 10s
entity-per-chunk-save-limit:
area_effect_cloud: 8
arrow: 16
dragon_fireball: 3
egg: 8
ender_pearl: 8
experience_orb: 16
fireball: 8
small_fireball: 8
snowball: 8
tick-rates:
mob-spawner: 2
sensor:
villager:
secondarypoisensor: 80
behavior:
villager:
validatenearbypoi: 60
misc:
redstone-implementation: ALTERNATE_CURRENT
fix-curing-zombie-villager-discount-exploit: true
Ключевые изменения:
- Mob spawn limits снижены: меньше мобов = меньше тиков сущностей = больше запас CPU. Во время атаки каждый процент CPU на счету.
- Entity tick rates увеличены: мобы проверяются реже. Визуально разница незаметна, но CPU-нагрузка падает существенно.
optimize-explosions: использует оптимизированный алгоритм для расчёта взрывов. TNT-канноны не положат сервер.redstone-implementation: ALTERNATE_CURRENT: альтернативная реализация редстоуна от Earthcomputer. В 2-3 раза быстрее ванильной.- Treasure maps отключены: генерация карт сокровищ может вызвать колоссальную нагрузку на chunk generation.
server.properties
view-distance=8
simulation-distance=5
max-players=100
network-compression-threshold=256
rate-limit=0
view-distance=8: для большинства серверов 10 чанков излишне. 8 - хороший баланс. Каждый дополнительный чанк view distance увеличивает нагрузку квадратично.simulation-distance=5: отдельно от view distance. Сущности и редстоун тикают только в этом радиусе.network-compression-threshold=256: пакеты меньше 256 байт не сжимаются. Экономит CPU на компрессии мелких пакетов.
spigot.yml
settings:
save-user-cache-on-stop-only: true
moved-wrongly-threshold: 0.0625
moved-too-quickly-multiplier: 10.0
timeout-time: 60
restart-on-crash: true
world-settings:
default:
entity-activation-range:
animals: 16
monsters: 24
raiders: 48
misc: 8
water: 8
villagers: 16
flying-monsters: 48
merge-radius:
item: 4.0
exp: 6.0
mob-spawn-range: 6
nerf-spawner-mobs: true
arrow-despawn-rate: 300
trident-despawn-rate: 300
Больше настроек безопасности для Paper и Spigot описано в отдельной статье.
Настройки ядра Linux (sysctl)
Если Minecraft-сервер работает на выделенном сервере или VPS с Linux, настройки ядра могут кардинально повлиять на устойчивость к сетевым атакам.
Сетевые буферы
# /etc/sysctl.d/99-minecraft.conf
# Увеличиваем буферы сокетов
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_default = 1048576
# TCP буферы (min, default, max)
net.ipv4.tcp_rmem = 4096 1048576 16777216
net.ipv4.tcp_wmem = 4096 1048576 16777216
Зачем это нужно: дефолтные буферы в Linux рассчитаны на обычные серверные задачи. Minecraft-сервер с 50+ игроками генерирует значительный сетевой трафик. Увеличенные буферы предотвращают потерю пакетов при всплесках.
Backlog и очереди подключений
# Размер очереди входящих подключений
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# Размер очереди сетевого устройства
net.core.netdev_max_backlog = 65535
Это критически важно при DDoS. Когда на сервер идёт поток SYN-пакетов, очередь подключений заполняется. С дефолтным somaxconn=128 легитимные игроки не могут подключиться, даже если сервер вполне способен их обслужить. Увеличение backlog до 65535 даёт серверу время обработать очередь.
TCP tuning
# Переиспользование TIME_WAIT сокетов
net.ipv4.tcp_tw_reuse = 1
# Быстрая переработка TIME_WAIT
net.ipv4.tcp_fin_timeout = 15
# Keepalive для обнаружения мёртвых соединений
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
# SYN flood protection
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 2000000
tcp_tw_reuse: позволяет переиспользовать сокеты в состоянии TIME_WAIT для новых подключений. При атаке, когда боты подключаются и отключаются, без этой настройки сокеты TIME_WAIT могут исчерпать доступные порты.tcp_syncookies: обязательно включить. Это встроенная в ядро Linux защита от SYN flood. Когда очередь SYN переполняется, ядро начинает использовать SYN cookies вместо выделения ресурсов на каждый SYN.tcp_fin_timeout=15: по умолчанию 60 секунд. При атаке тысячи полуоткрытых соединений висят в FIN_WAIT, занимая память ядра.
Лимиты файловых дескрипторов
# /etc/security/limits.conf
minecraft soft nofile 1048576
minecraft hard nofile 1048576
# Или в systemd unit
[Service]
LimitNOFILE=1048576
Каждое TCP-подключение к серверу = один файловый дескриптор. Дефолтный лимит в 1024 или 4096 закончится моментально при атаке. Увеличивайте до 1 миллиона.
Применение настроек
sudo sysctl -p /etc/sysctl.d/99-minecraft.conf
Оптимизация плагинов
Плагины - главный потребитель ресурсов после самого ядра сервера. Один плохо написанный плагин может съедать больше CPU, чем все остальные вместе взятые.
Диагностика тяжёлых плагинов
/timings on
# Подождать 5-10 минут
/timings paste
Spark - более продвинутая альтернатива:
/spark profiler start
# Подождать 5-10 минут
/spark profiler stop
Смотрите на два параметра:
- Tick time contribution - сколько миллисекунд каждый плагин добавляет к тику
- Thread activity - не блокирует ли плагин основной поток синхронными операциями
Типичные проблемы
Dynmap: генерация карты мира вызывает колоссальную нагрузку на CPU и диск. Если используете, ограничьте скорость рендера:
# configuration.txt
renderacceleratethreshold: 10
parallelrendercnt: 2
updaterate: 5000
Плагины экономики с MySQL: синхронные запросы к БД блокируют основной поток. Каждый тик, пока идёт SQL-запрос, сервер стоит. Убедитесь, что плагин поддерживает async-запросы или используйте HikariCP connection pool.
WorldEdit/WorldGuard: массовые операции WorldEdit могут вызывать фризы. Используйте FAWE (FastAsyncWorldEdit) вместо стандартного WorldEdit.
Плагины, сканирующие чанки: некоторые плагины (Ore Obfuscator, определённые анти-читы) перебирают блоки в чанках. Это дорогая операция. Проверьте, можно ли ограничить радиус или частоту сканирования.
Общие правила
- Каждый плагин должен быть обоснован. "На всякий случай" - плохая причина.
- Проверяйте плагины на тестовом сервере под нагрузкой перед установкой на прод.
- Обновляйте плагины. Разработчики часто исправляют утечки памяти и оптимизируют производительность в обновлениях.
- Не используйте больше одного плагина для одной задачи.
Планировщик задач плагинов
Многие плагины используют Bukkit scheduler для выполнения периодических задач. Проблема в том, что по умолчанию задачи запускаются каждый тик (50 мс). Если у вас 30 плагинов, и каждый из них запускает 2-3 задачи каждый тик, это уже 60-90 дополнительных обработок на тик.
Проверьте через Spark, какие scheduled tasks запускаются чаще всего. Некоторые плагины позволяют настроить частоту через конфигурацию. Для тех, что не позволяют, рассмотрите альтернативы или форк с исправлением.
Folia (экспериментальный форк Paper) решает эту проблему через многопоточность, но поддержка плагинов там пока ограничена. Для большинства серверов Paper/Purpur остаётся лучшим выбором.
Пре-генерация чанков
Генерация новых чанков - одна из самых тяжёлых операций для Minecraft-сервера. Каждый новый чанк требует генерации ландшафта, структур, биомов, освещения. Один тик генерации может занять 50-200 мс.
Во время атаки, если на сервер заходят боты и разлетаются в разные стороны, каждый из них триггерит генерацию новых чанков. Это мгновенно убивает TPS.
Решение: Chunky
/chunky radius 5000
/chunky start
Chunky пре-генерирует чанки в указанном радиусе. После генерации эти чанки загружаются с диска, что в 10-100 раз быстрее генерации с нуля.
Рекомендации:
- Пре-генерируйте как минимум зону spawn + основные маршруты игроков
- Для survival серверов: радиус 5000-10000 блоков от спавна
- Генерацию лучше делать ночью или при минимальном онлайне, потому что сам процесс генерации нагружает сервер
- Установите мировую границу (world border) чтобы ограничить карту. Это и экономит диск, и предотвращает нагрузку от исследования далёких территорий
/worldborder set 20000
Оптимизация диска
NVMe vs HDD
Для Minecraft-сервера скорость диска играет огромную роль. Чанки загружаются с диска, сохраняются на диск, данные игроков записываются на диск. При атаке, когда десятки ботов генерируют I/O-операции, медленный диск становится узким местом.
- NVMe SSD: 3000-7000 МБ/с чтение. Чанки загружаются мгновенно.
- SATA SSD: 500-550 МБ/с. Приемлемо для небольших серверов.
- HDD: 100-150 МБ/с. Недопустимо для серверов с 20+ игроками или серверов, подвергающихся атакам.
tmpfs для временных файлов
# Монтирование tmpfs для логов
mount -t tmpfs -o size=512M tmpfs /home/minecraft/server/logs
# Или в fstab
tmpfs /home/minecraft/server/logs tmpfs size=512M,nodev,nosuid 0 0
Логи Minecraft могут генерировать значительный I/O. Перенос логов в tmpfs (RAM-диск) освобождает дисковый I/O для более важных задач: загрузки чанков и сохранения данных.
I/O scheduler
Для NVMe-дисков:
echo "none" > /sys/block/nvme0n1/queue/scheduler
Для SATA SSD:
echo "mq-deadline" > /sys/block/sda/queue/scheduler
NVMe-диски не нуждаются в планировщике I/O, потому что они обрабатывают запросы параллельно. Scheduler none убирает overhead.
Файловая система
Для Minecraft-серверов рекомендуется ext4 с параметрами noatime,nodiratime:
# /etc/fstab
/dev/nvme0n1p1 /home/minecraft ext4 defaults,noatime,nodiratime 0 2
Параметр noatime отключает обновление метки времени последнего доступа при чтении файла. При загрузке тысяч файлов чанков (region files) это снижает количество записей на диск. Это особенно заметно под атакой, когда боты триггерят массовую загрузку чанков.
Если сервер использует ZFS, настройте recordsize=128k для датасетов с миром. Minecraft region файлы хорошо ложатся на этот размер блока. Также включите compression=lz4 для экономии места без заметного влияния на производительность.
Лимиты подключений на уровне сервера
server.properties
max-players=100
Установите реалистичный лимит. Если ваш сервер стабильно обслуживает 50 игроков, не ставьте max-players=1000 "на вырост". При атаке боты заполнят все 1000 слотов.
Rate limiting
Velocity (рекомендуемый прокси) имеет встроенный rate limiter:
# velocity.toml
[advanced]
login-ratelimit = 3000
connection-timeout = 5000
read-timeout = 30000
login-ratelimit = 3000 означает минимум 3 секунды между попытками логина с одного IP. Это не остановит распределённую атаку с тысяч IP, но отсечёт простейшие bot floods с одного источника.
Для сервера без прокси используйте плагины типа LoginSecurity или AuthMe с настроенными лимитами.
Как TPS-стабильность помогает при атаках
TPS (Ticks Per Second) = 20 означает, что сервер обрабатывает 20 игровых тиков в секунду. Каждый тик занимает до 50 мс. Если тик занимает больше 50 мс, TPS падает ниже 20.
MSPT (Milliseconds Per Tick) - более точная метрика. Сервер с MSPT 30 мс имеет 20 мс запаса. Сервер с MSPT 48 мс имеет всего 2 мс запаса.
При DDoS-атаке каждая дополнительная нагрузка увеличивает MSPT:
- Обработка пакетов ботов: +5-15 мс
- Загрузка чанков для новых подключений: +10-50 мс
- Увеличение GC pressure: +5-20 мс
Сервер с MSPT 30 мс выдержит дополнительные 20 мс нагрузки и останется на 20 TPS. Сервер с MSPT 48 мс просядет до 10-15 TPS, игроки начнут лагать и отключаться.
Мониторинг MSPT
/spark tps
/spark tickmonitor
Цель: держать MSPT ниже 35 мс в нормальном режиме, чтобы оставался запас для всплесков.
Уменьшение поверхности атаки
Оптимизация - это не только скорость. Это ещё и уменьшение того, что атакующий может использовать.
Отключите Query
# server.properties
enable-query=false
Query протокол (UDP порт 25565) позволяет получить информацию о сервере. Атакующие используют его для разведки и amplification-атак.
Отключите RCON, если не используете
enable-rcon=false
RCON - это удалённая консоль. Если она открыта в интернет, это прямой вектор для брутфорса и эксплуатации.
Ограничьте broadcast
# paper-global.yml
proxies:
bungee-cord:
online-mode: true
velocity:
enabled: true
online-mode: true
secret: 'ваш-секретный-ключ'
Если используете прокси, включите его через secret key. Это предотвращает подключение напрямую к backend-серверу, минуя прокси.
Whitelist при экстренных ситуациях
/whitelist on
Если атака слишком сильная и фильтрация не справляется, временный whitelist позволит играть только зарегистрированным игрокам. Не идеальное решение, но лучше, чем полный даунтайм.
Комплексный чеклист оптимизации
Вот краткий чеклист, который можно пройти за один вечер:
JVM:
- Aikar's flags установлены
-
-Xms=-Xmx - RAM не больше 12-16 ГБ на инстанс
- GraalVM рассмотрен как альтернатива
Paper/Purpur:
- Mob spawn limits снижены
- Entity tick rates увеличены
- Chunk loading rate ограничена
- View distance = 8 или меньше
- Simulation distance = 5
-
optimize-explosions: true -
redstone-implementation: ALTERNATE_CURRENT
Linux kernel:
-
somaxconn = 65535 -
tcp_max_syn_backlog = 65535 -
tcp_syncookies = 1 -
rmem_maxиwmem_maxувеличены -
nofileлимит увеличен -
tcp_fin_timeoutуменьшен
Плагины:
- Spark profiling проведён
- Тяжёлые плагины заменены или оптимизированы
- Sync SQL-запросы заменены на async
- Неиспользуемые плагины удалены
Диск и сеть:
- NVMe/SSD используется
- Чанки пре-генерированы (Chunky)
- World border установлен
- Query и RCON отключены
Мониторинг:
- Spark установлен
- MSPT мониторится
- Алерты на TPS < 18 настроены
Оптимизация + внешняя защита = максимальная устойчивость
Важно понимать: оптимизация сервера не заменяет DDoS-защиту. Она дополняет её. Никакие настройки sysctl не спасут от 10 Гбит/с UDP flood. Для этого нужна фильтрация трафика на уровне сети.
Но связка "оптимизированный сервер + качественная фильтрация" (например, через MineGuard) даёт максимальную устойчивость. Фильтр отсекает 99% мусорного трафика, а оптимизированный сервер спокойно переваривает оставшийся 1%, который просочился.
Выбор хостинга тоже играет роль. Подробнее о том, на что обращать внимание при выборе хостинга с DDoS-защитой, читайте здесь.
Заключение
Оптимизация Minecraft-сервера - это не разовое действие, а непрерывный процесс. Каждое обновление ядра, каждый новый плагин, каждое изменение нагрузки может сместить баланс. Регулярно проводите профилирование через Spark, следите за MSPT, проверяйте sysctl-настройки после обновления ядра Linux.
Запас производительности - это ваша страховка. Чем больше headroom у сервера в нормальном режиме, тем больше шансов, что он переживёт атаку и ваши игроки даже не заметят, что что-то произошло.
Sunucunuzu DDoS Saldırılarından Koruyun
5 dakikada kurulumla ücretsiz koruma. 1 TB bant genişliği dahil.
Ücretsiz Deneyinİlgili Makaleler
Почему бесплатной DDoS защиты недостаточно для растущего сервера
Бесплатный план отлично работает на старте. Но когда сервер растет, атаки становятся мощнее, а бесплатного трафика и функций уже не хватает. Разбираемся, когда пора переходить на платный тариф.
Правила и модерация Minecraft-сервера: полное руководство
Как составить правила для Minecraft-сервера, выстроить иерархию модераторов, настроить плагины наказаний и античит. Практический опыт и готовые шаблоны.
Как создать Minecraft сервер с нуля
Пошаговое руководство по созданию Minecraft сервера: выбор версии Java, скачивание серверного jar, настройка server.properties, проброс портов, принятие EULA, первый запуск, установка плагинов и базовая оптимизация.