Игры админов — часть 1, Doom2

Posted: 2014-11-19 in IT
Метки:

Я очень давно не писал об играх. Времени собственно поиграть особо нет, да и просто гамать стало скучновато.
Поэтому я начну новую тему у себя в блоге — поднятие своих игровых серверов. Безусловно, в безднах интернетов много готовых руководств на эту тему, но всегда есть какие-то ньюансы, которые я постараюсь осветить. Таких статей я планирую несколько, а сама идея их написать появилась после поднятия нескольких таких серверов в локальной сети для наших абонентов, любимых и не очень.

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

  1. Аптайм и доступность. Выделенный сервер работает 24/7 и всегда готов принять подключения игроков. Домашнюю машину не всегда можно держать включенной 24/7, кроме того, выделенный сервер обычно обеспечен бесперебойным питанием
  2. Выделенная полоса в интернеты. На домашней машине параллельно качающийся торрент — плохой сосед, особенно, если у вас виндовс вместо операционной системы
  3. Можно прикручивать дополнительные сервисы, которые на домашней машине поднимать будет просто лениво
  4. Бэкапы

Несколько базовых принципов:

  1. Linux как основная ОС для таких дел. В идеале — внутри OpenVZ-контейнера. Это позволит очень легко динамически добавить ресурсов при необходимости, осуществлять живую миграцию виртуалки, и вообще сама система очень легковесна
  2. Принцип минимума привилегий. Запуски от отдельных пользователей, в MySQL — тоже своими пользователями. От рута ничего не запускаем. Это также позволит делегировать полномочия на полное управление игровым сервером выдачей доступа по SSH в соответствующие учётки.
  3. Не забываем о сильных паролях
  4. У нашего сервера есть постоянный внешний IP и доменное имя, чтобы при переносе сервера просто пофиксить DNS.
  5. установленная ОС должна быть обновлена, SSH должен быть надёжно настроен, то есть доступ только по ключам.
  6. Для игр с большими требованиями к памяти будем стараться использовать 64битные ОС и сборки серверов
  7. Игры, имеющие интерактивный шелл, мы будем запускать с помощью screen, чтобы иметь возможность управлять сервером после SSH-коннекта, а не всякими мутными и несекурными rcon-ами.

Итак, начнём.

Doom 2

Наша задача — поднять свои игровые сервера Doom2. Этот неимоверно древний шутер от первого лица (в этом году игра отметила 20-и летний юбилей) пережил множественные улучшения движка, обзавелся уймой плагинов и форков, и помирать совершенно не собирается, как бы удивительно это не звучало. Свыше 25 тысяч игровых серверов говорят о том, что у дедушки всех шутеров порох в пороховницах есть.

Сперва создаём пользователя doom2. При этом у нас будет создан каталог /home/doom2
В качестве исполняемого файла сервера мы будем использовать linux-версию Zandronum:
http://zandronum.com/download
Сами файлы сервера по-умолчанию размещают в /usr/games/doom2, поэтому создадим этот каталог и пропишем права доступа:

# ls -la /usr/games/doom2
drwxr-x--- 3 doom2 apache 4096 Фев 23 2014 doom2

При этом скрипты запуска мы разместим в /home/doom2. Таким образом, в /home/doom2 у нас будут файлы, требующиеся только игровому серверу, а в /usr/games/doom2 — файлы, используемые как игровым сервером, так и другими процессами.

То есть пользователь doom2 имеет полный доступ, веб-сервер — только чтение (о его роли расскажу позднее), а больше никому сюда ходить не надо. Распаковываем туда скачанный архив. В первую очередь в /usr/games/doom2 надо положить *.wad-файлы, содержащие основные ресурсы игры (карты. текстуры, скрипты, и прочее). Главный из них — doom2.wad (14 Мб):

# sha256sum /usr/games/doom2/doom2.wad
10d67824b11025ddd9198e8cfc87ca335ee6e2d3e63af4180fa9b8a471893255 doom2.wad

Этот wad-ресурс, в отличие от исходников движка, не является открытым, я я надеюсь, что вы хотя бы вспомните Джона Кармака добрым словом, а не просто тупо скачаете его с торрентов.

Всякие моды представляют собой дополнительные *.wad или *.pk3 файлы, размещенные в том же каталоге. Также там будут лежать наши конфиги. Если мы запускаем несколько серверов (например, для Deathmatch и для CTF), то каждый такой сервер — это отдельный процесс, и у него свой конфиг. Поскольку моды часто используют дополнительные ресурсы — то будет полезно отдавать их сво свеого же веб-сервера, чтобы не заставлять клиента искать их вручную. Для этого ставим апач (yum install httpd), и настраиваем наш виртуал-хост (я подразумеваю, что помимо дума-2 на этом же сервере будут и другие игровые сервера):

# cat /etc/httpd/conf/httpd.conf
...
<Directory /var/www/html_doom2>
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
...
<VirtualHost *:80>
ServerAdmin your_contact
DocumentRoot /var/www/html_doom2
ServerName doom2.your.domain
</VirtualHost>
...

Это позволит нам использовать возможности файла .htaccess при раздаче ресурсов, и вообще свой веб-сервер очень благоприятствует быстрому коннекту к серверу, когда у клиента отсутсвует необходимый wad-файл.
Теперь немного разграничим доступы для веб-сервера (обратите внимание, где лежит .htaccess !!):

### Manage access to WAD-files from internet
# Deny by file-extensions for configs/logs
<Files ~ "\.(cfg|CFG|conf|so|sh|log|LOG|txt|out)$">
Deny from all
</Files>

# Allow by file-extensions for wad/pk3 for anyone
<Files ~ "\.(wad|WAD|pk3|PK3|pk7|PK7)$">
Allow from all
</Files>

# Get access to certain files only from trusted-network
<Files ~ "^(doom2.wad)$">
Order deny,allow
deny from all
Allow from 10.0.0.0/8
</Files>

# Get access to certain files only from admins
<Files ~ "^(skulltag|skulltag-server|zandronum|zandronum-server)$">
Order deny,allow
deny from all
Allow from 10.44.45.56
</Files>

После чего в каталоге виртуал-хоста веб-сервера создаем файл-заглушку index.html с текстом «Doom2 Server», а рядом делаем симлинк такого вида:
/var/www/html_doom2/wad -> /usr/games/doom2
После запускаем веб-сервер, и обкрываем в браузере адрес нашего сервера. Должна появится страница-загршка с текстом «Doom2 Server». Дописав в адресную строку /wad, мы должны увидеть список наших wad-файлов на сервере.
Если вы не люьите апач — ничто не мешает перейти на NGiNX, для отдачи таких файлов будет самое оно. Но это в другой раз =)

Теперь напишем конфиг первого игрового сервера. Это будет DM-сервер с модом Ketchup (кровищща на весь экран, то бишь).

# cat /usr/games/doom2/ServerDM.cfg
echo " ### MAIN Config DM ### ";

set enable_rcon "1"
set fraglimit "40";
set sv_motd " *** Welcome to server from *** ";
set removebotswhenhumans "1";
set spam_window "10";
set spam_limit "3";
set sv_hostname "Super Skulltag + Ketchup Deathmatch Server";
set sv_maxclients "12";
set sv_maxplayers "12";
set sv_rconpassword "Put-RCON-Password-here"
set DmFlags "283784";
set DmFlags2 "8389378";
set DmFlags3 "0";
set CompatFlags "4096";
set CompatFlags2 "1";
set timelimit "0";
logfile "/usr/games/doom2/LOG/ServerDM.log";
set sv_website "http://doom2.your.domain/wad/";

echo " ### Config MAP-List ### ";
clearmaplist;
addmap "d2dm1";
addmap "d2dm2";
addmap "d2dm3";
addmap "d2dm4";
addmap "d2dm5";
addmap "d2dm6";
addmap "d2dm7";
addmap "d2dm8";
addmap "d2dm9";
addmap "d2dm10";
addmap "d2dmsec";
maplist;

map "d2dm1";
sv_maprotation true;

Самое главное тут — ротация карт, пароль rcon (если вы его всё-таки используете), название и приветствие для сервера и параметр sv_website — именно он говорит клиенту, откуда скачивать недостающие файлы модов.
Для CTF конфиг отличается в деталях:

echo " ### MAIN Config CTF-1 ### ";

set enable_rcon "1"
set pointlimit "5";
set sv_motd " *** Welcome to CTF server #1 *** ";
set removebotswhenhumans "1";
set ctf "1";
set spam_window "10";
set spam_limit "3";
set sv_hostname "CTF #1";
set sv_maxclients "10";
set sv_maxplayers "10;
set sv_rconpassword "Your-RCON_Pass_here"
set timelimit "0";
set DmFlags "20480";
set DmFlags2 "768";
set DmFlags3 "0";
set CompatFlags "0";
set CompatFlags2 "1";
logfile "/usr/games/doom2/LOG/ServerCTF_1.log";
set sv_website "http://doom2.your.domain/wad/";

clearmaplist;
addmap "map01";
addmap "map02";
addmap "map03";
...
addmap "map32";

maplist;
map "map01";
sv_maprotation true;

У каждого типа игры могут быть немного свои параметры в конфиге, детально описывать DmFlags и каждую опцию я не буду.
Теперь напишем скрипт для запуска и перезапуска серверов:

# cat /home/doom2/start_doom2_serv.sh
#!/bin/bash

runprefix='screen -dmS';
srvbin='./zandronum-server -port';
opts='+sv_updatemaster 1 +sv_adminlistfile "/usr/games/doom2/d2_admins.cfg"';

clear
echo "Stop Doom2 Servers..."
pkill zandronum
pkill doom2_
sleep 5
find /usr/games/doom2/LOG/ -type f -name "*.log" -mtime +7 -delete

echo "Start Doom2 Servers..."

cd /usr/games/doom2

echo " ... Zandronum Super Skulltag + Ketchup Deathmatch"
$runprefix doom2_dm $srvbin 10666 $opts -iwad doom2.wad -file skulltag_actors_old.pk3 -file skulltag_data.pk3 -file ketchuptest4.pk3 -file sst_v1.4rc6.pk3 -file sst_thingrandomizer_v2.pk3 +exec ServerDM.cfg

echo " ... Zandronum CTF Server #1"
$runprefix doom2_ctf1 $srvbin 10667 $opts -iwad doom2.wad -file idl2012-.wad +exec ServerCTF_1.cfg

sleep 1

И пропишем его в автозапуск:

# cat /etc/rc.d/rc.local | grep doom2
su - doom2 -c "/home/doom2/start_doom2_serv.sh"

Таким образом, при рестарте впс-ки наш скрипт start_doom2_serv.sh будет запущен под пользователем doom2 из домашнего каталога, после чего он запустит каждый из экземпляров сервера в своем screen-e с именами вида doom2_*.
На порту 10666 у нас будет DM-сервер, а на порту 10667 — CTF. При запуске каждый из серверов подгрузит свои моды, указанные в орпциях -file, и в конце выполнит doom2-скрипт, указанный в параметре +exec. Думаю, pk3-файлы вы сможете найти самостоятельно.
Чтобы посмотреть в консоль любого запущенного сервера, достаточно зайти по SSH и сперва посмотреть список консолей screen:

[doom2@game-server1 ~]$ screen -ls
There are screens on:
1649.doom2_dm (Detached)
1680.doom2_ctf1 (Detached)
2 Sockets in /var/run/screen/S-doom2.

Для коннекта к консоли пишем:

# screen -Rx doom2_dm

и оказываемся в консоли сервера:

 ###  Config MAP-List ###
Map rotation list cleared.
D2DM1 (Training Center) added to map rotation list at position 1.
D2DM2 (Testing Center) added to map rotation list at position 2.
D2DM3 (Combat Center) added to map rotation list at position 3.
D2DM4 (Containment Facility) added to map rotation list at position 4.
D2DM5 (The Volcano Installation) added to map rotation list at position 5.
D2DM6 (Last Bastion) added to map rotation list at position 6.
D2DM7 (Linguica's Lair) added to map rotation list at position 7.
D2DM8 (Power Mill) added to map rotation list at position 8.
D2DM9 (Infernal Chamber) added to map rotation list at position 9.
D2DM10 (Final Atonement) added to map rotation list at position 10.
D2DMSEC (Some Secret Level) added to map rotation list at position 11.
Map rotation list:
1. D2DM1 - Training Center
2. D2DM2 - Testing Center
3. D2DM3 - Combat Center
4. D2DM4 - Containment Facility
5. D2DM5 - The Volcano Installation
6. D2DM6 - Last Bastion
7. D2DM7 - Linguica's Lair
8. D2DM8 - Power Mill
9. D2DM9 - Infernal Chamber
10. D2DM10 - Final Atonement
11. D2DMSEC - Some Secret Level

*** D2DM1: Training Center ***

compatflags changed to: 4096
dmflags changed to: 2380940
dmflags2 changed to: 8389442

Для отключения нажимаем [Ctrl]-[A], потом [D]. При этом мы отсоединимся от консоли, но сервер не остановится, игроков не вышибет, и мы можем спокойно отключаться от SSH. Что ценно — screen позволяет нескольким админам работать в однйо общей консоли — иногда такое тоже может потребоваться. На моей памяти прямое вмешательство в консоль сервера Doom2 не потребовалось ни разу, но иногда это может быть очень полезным при диагностике неполадок.

Всё, можно запускать DoomSeeker из Zandronum, искать свой сервер и коннектиться.
Если у вас не будет какого-то файла — вы увидите в интерфейсе дум-сикера и логах веб-сервера закачку файлов с http://doom2.your.domain/wad/

Таким образом, мы подняли два сервера Doom2, работающих на разных портах, под обычным пользователем, и с возможностью автоматически отдавать клиентам недостающие файлы. В Doom2 много интересных модов. Из моих любимых — Master of Puppets (можно поиграть за монстров и исполнить давнюю мечту детства — поуправлять кибердемоном) и All Out War 2. Добавляются они совершенно аналогично — пишем конфиги, добавляем строчки в start_doom2_serv.sh.
Если у вас много игроков на серверах, то не обязательно перезапускать их все. Скрипт в конечном итоге собирает из частей и выполняет команды такого вида:

screen -dmS doom2_dm zandronum-server -port 10666 +sv_updatemaster 1 +sv_adminlistfile "/usr/games/doom2/d2_admins.cfg" -iwad doom2.wad -file skulltag_actors_old.pk3 -file skulltag_data.pk3 -file ketchuptest4.pk3 -file sst_v1.4rc6.pk3 -file sst_thingrandomizer_v2.pk3 +exec ServerDM.cfg

Вам ничто не мешает запустить только один сервер такой командой, не трогая остальные, главное — запускать его от пользователя doom2 — всё будет работать. Файл d2_admins.cfg содержит ip-адреса, с которых можно админить сервер. Если у вас постоянный внешний адрес, и вам требуется возможность управлять сервером прямо из игры — можете прописать.

При запуске могут возникнуть следующие сложности:
1). Отсутствуют требуемые либы. Поскольку игровой сервер у нас не из репозитория, то автоматического разруливания зависимостей не случится. На федоре 20 ставим две требуемые либы (на их отсутствие ругнётся сервер при попытке запуска):

# yum install libjpeg SDL

2). Версия Зандронума 1.3 хочет libssl 0.9.8, тогда как в 20-й федоре уже давно 1.0.1. Симлинк не прокатывает. Решение -скачать старый рпм-пакет (например, от древней мандривы ftp://rpmfind.net/linux/Mandriva/official/2011/i586/media/contrib/backports/libopenssl0.9.8-0.9.8x-0.1-mdv2011.0.i586.rpm), распаковать rpm-пакет:

# rpm2cpio libopenssl0.9.8-0.9.8x-0.1-mdv2011.0.i586.rpm | cpio -idmuv --no-absolute-filenames

и файл libssl.so.0.9.8 скопировать в /usr/games/doom2.
После чего сервер запустится. В основную систему, само собой, ставить старый пакет от другого дистриба ни в коем случае не надо — все дела делаем от пользователя doom2, чтобы ничего не сломать. Распаковали, библиотеку скопировали, исходный пакет и прочие распаковынные файлы от него удалили. Надеюсь, в будущих версиях зандронума это некро-зависимость уберут.

Можно также прописать в кронтаб пользователя doom2 автоматический рестарт серверов рано утром раз в месяц:
$ crontab -l
6 6 6 * * /home/doom2/start_d2_serv.sh
Игровые сервера — вещь далеко не безглючная, принудительный профилактический ребут не помешает.

Приятной игры!

Обсуждение закрыто.