Игры админов — часть 3, UT 2004

Posted: 2014-12-10 in IT
Метки:

Как и обещал, продолжаю знакомить читателей со своими изысканиями по поднятию игровых серверов. В прошлых двух заметках я рассказал, как настроить серверы для старых игр от iD Software — Doom2, Quake2 и Quake3.

Теперь пора настроить чуть более сложный сервер — Unreal Tournament 2004.

Поднимать мы будем его на выделенной ВПС-ке, возможно — даже той же самой, где уже крутятся сервера дума и кваки. В любом случае, мы заранее создаём обычного linux-пользователя ut2004, под которым и будем создавать, конфигурировать и запускать наш сервер.
Запускать под рутом игровые сервера категорически нельзя, если кто забыл. Турмач содержит гораздо больше возможностей, и мы постараемся их использовать. Поэтому заранее поставим на сервер привычные на любом веб-хостинге программы — Apache, PHP, MySQL и программу screen. Они понадобятся нам, когда мы будет прикручивать онлайн-статистику сыгранных матчей. На федоре это делается одной командой:
yum install httpd php-mysql php-mysqli php mysql-server mysql screen
В разных версиях названия, форки и под-версии могут несколько разниться (apache2, apache, maria-db и прочее и прочее, но это не суть). Нам в итоге нужен веб-сервер апач, умеющий php, и чтобы этот php умел коннеткиться к базам данных.

Под рутом создаём каталог /usr/games/ut2004, права ставим такие: ut2004:apache (750) /* владелец — ut2004, полный доступ, группа — апач, доступ только на чтение, всем остальным доступ закрыт вообще */. Теперь переключимся в пользователя ut2004 и распакуем скачанную игру. Должно получится что-то подобное:

$ ls /usr/games/ut2004
Animations  Help       License.txt  Manual  Maps_Bad  Readme.txt  Speech        System    UserLogs
Demos       KarmaData  Logs         Maps    Music     Sounds      StaticMeshes  Textures  Web

Поскольку каталог игры нам понадобиться большей частью отдавать веб-сервером для автоматического скачивания карт, заранее разместим .htaccess-файлы, правильно управляющие доступом:

** /usr/games/ut2004/.htaccess

<Files ~ "\.(cfg|CFG|so|ini|INI)$">
Deny from all
</Files>

** /usr/games/ut2004/Demos/.htaccess

<Files ~ "\.(demo4|DEMO4)$">
Allow from all
</Files>

** /usr/games/ut2004/UserLogs/.htaccess
** /usr/games/ut2004/Help/.htaccess
** /usr/games/ut2004/Logs/.htaccess
** /usr/games/ut2004/Web/.htaccess
** /usr/games/ut2004/Manual/.htaccess

order deny,allow
deny from all
allow from 127.0.0.0/8 10.44.1.2 # Доверенные сети

** /usr/games/ut2004/System/.htaccess

<Files ~ "\.(cfg|CFG|so|ini|INI|log)$">
Deny from all
</Files>

<Files "cdkey">
Deny from all
</Files>

Теперь нам надо найти линуксовые бинарники. Самый главный — ucc-bin (для х64-систем — ucc-bin-linux-amd64), взять можно из линуксовой версии турнамента. Для того, чтобы наш сервер был виден в общем списке серверов, нужно получить так называемый cdkey на http://www.unrealtournament.com/ut2004server/cdkey.php . Ключи выдаются бесплатно, дял регистрации нужна почта. Лучше всего найти готовую минимальную сборку, содержащую только серверную часть, например, вот такую: http://www.ausgamers.com/files/download/13962/unreal-tournament-2004-dedicated-server-v3323
Теперь надо написать конфиги серверов — ini-файлы, лежащие в ./System. Я советую взять готовый шаблон ut2004.ini, скопировать его рядом в отдельный файл и внести требуемые правки. Настроек там совершенно безумное количество, вот пример ключевых настроек для DeathMatch-сервера, которые я правил:

...
[Engine.GameStats]
bLocalLog=True

[IpDrv.TcpNetDriver]
AllowDownloads=true
ConnectionTimeout=120
MaxClientRate=20000
MaxInternetClientRate=10000
DownloadManagers=IpDrv.HTTPDownload
MaxConnPerIPPerMinute=5

[IpServer.UdpServerQuery]
GameName=ut2

[IpDrv.MasterServerUplink]
DoUplink=false
UplinkToGamespy=true
SendStats=true
ServerBehindNAT=true
DoLANBroadcast=false

[IpDrv.MasterServerLink]
LANPort=21777
LANServerPort=20777
MasterServerList=(Address="ut2004master1.epicgames.com",Port=28902)
MasterServerList=(Address="ut2004master2.epicgames.com",Port=28902)

[IpDrv.HTTPDownload]
RedirectToURL=http://ut2.your-domain.local/files/

[Engine.DemoRecDriver]
AllowDownloads=True
DemoSpectatorClass=UnrealGame.DemoRecSpectator
MaxClientRate=25000
NetServerMaxTickRate=60
LanServerMaxTickRate=60

[Engine.GameReplicationInfo]
ServerName=ut2.your-domain.local::DM
ShortName=SERVER-NAME-DM
ServerRegion=0
AdminName=YOU-NICK
AdminEmail=YOU-CONTACT
MessageOfTheDay=Welcome to my DM-Server!

[UWeb.WebServer]
Applications[0]=xWebAdmin.UTServerAdmin
ApplicationPaths[0]=/ServerAdmin
Applications[1]=xWebAdmin.UTImageServer
ApplicationPaths[1]=/images
bEnabled=true
ListenPort=8177
ServerName=

[Engine.AccessControl]
GamePassword=
IPPolicies=ACCEPT;*

[XGame.xDeathMatch]
HUDType=XInterface.HudBDeathMatch
MaxLives=0
TimeLimit=30
GoalScore=50
bTeamScoreRound=False
bPlayersMustBeReady=False
bAllowTaunts=True
bForceRespawn=False
bWeaponStay=true
bCustomPreload=False
NetWait=5
bAdjustSkill=False
bAllowTrans=False
SpawnProtectionTime=1.500000
LateEntryLives=1
LoginMenuClass=GUI2K4.UT2K4PlayerLoginMenu
bAllowPrivateChat=True
bAllowWeaponThrowing=True
ResetTimeDelay=0

[XAdmin.AccessControlIni]
PrivClasses=Class'XAdmin.xKickPrivs'
PrivClasses=Class'XAdmin.xGamePrivs'
PrivClasses=Class'XAdmin.xUserGroupPrivs'
PrivClasses=Class'XAdmin.xExtraPrivs'
...

Это только базовые настройки =)

Советую обратить внимание на секцию [UWeb.WebServer] и параметр ListenPort=8177. Если эта секция присутствует, то помимо игрового порта 7777, куда будут коннектиться игроки, сервер также откроет порт 8177, на котором будет висеть полноценный веб-интерфейс для управления сервером. Я советую все сложные вещи типа ротации карт, допустимых типов игры, мутаторов, силы ботов и прочего настраивать именно через него. UT2004 позволяет создать несколько пользователей с разными правами доступа. Пароли, логины и права доступа хранятся открытым текстом в файле ./System/XAdmin.ini , вот пример моего файла:

AdminUsers=(AdminName="Admin",Password="ADMIN-PASSWORD",Privileges=,Groups=("Admin"),ManagedGroups=("kickers","GameAdmins"))
AdminUsers=(AdminName="Moderator",Password="MODERATOR-PASSWORD",Privileges=,Groups=("GameAdmins"),ManagedGroups=("kickers"))
AdminGroups=(GroupName="Admin",Privileges=,GameSecLevel=255)
AdminGroups=(GroupName="MatchSetup",Privileges="Xm",GameSecLevel=240)
AdminGroups=(GroupName="kickers",Privileges="Kp|Ko",GameSecLevel=0)
AdminGroups=(GroupName="GameAdmins",Privileges="Kp|Ko|Mr|Mm|Ml|Ms|Mu|Mb|Ma|Xb|Xc|Xp|Xv|Xm",GameSecLevel=0)

Это пример готового файла, позволяющий войти в веб-интерфейс запущенного сервера с логином Admin и паролем ADMIN-PASSWORD. Настраивать ЭТО лучше в веб-интерфейсе. Я использую один общий файл учеток XAdmin.ini для всех игровых серверов.

Теперь напишем скрипт запуска.

$ cat /home/ut2004/start_ut2k4_serv.sh 
#!/bin/bash

ADMLOGIN=Amin         # // + XAdmin.ini !!!!

echo "Stop UT 2004 Server..."
pkill ucc-bin
sleep 5

echo "Start UT 2004 Server..."
cd /usr/games/ut2004/System

screen -dmS ut2k4_dm  ./ucc-bin server \
   DM-Leviathan?game=XGame.XDeathmatch?GameStats=True?mutator=utcompv17a.MutUTComp,XGame.MutUDamageReward \
   ini=Server_DM.ini  -nohomedir log=SrvLogDM.log
screen -dmS ut2k4_tdm ./ucc-bin server \
   DM-Curse4?game=XGame.XTeamGame?GameStats=True?mutator=utcompv17a.MutUTComp,XGame.MutUDamageReward \
   ini=Server_TDM.ini -nohomedir log=SrvLogTDM.log
screen -dmS ut2k4_any ./ucc-bin server \
   AS-Glacier?game=Assault.ASAssultGame?GameStats=True?mutator=utcompv17a.MutUTComp,XGame.MutUDamageReward \
   ini=Def_serv_Any.ini -nohomedir log=SrvLogAny.log

Данный скрипт запустит три сервера — для обычного DM, командной игры и для игры в захват базы. Самые важные параметры — ведение логов игры GameStats и подключение двух мутаторов при старте — UTComp и UDamageReward. Остальные мутаторы можно включить в веб-интерфейсе.
Для запуска может потребоваться поставить дополнительные библиотеки:

yum install compat-libstdc++-33

Вот скриншот лишь малой части настроек:
ut2004_server_webface
При изменениях параметры пишутся в конфиг сервера, указанный в параметре ini= нашего скрипта запуска. Предположу, что вам не захочется писать с нуля конфиг весом под 40 Кб, так что шаблон + веб-интерфейс наше всё.
Настройки прав доступа тоже радуют:
ut2004_server_webface_permissions
Ещё важный момент — в веб-интерфейсе есть как настройки текущего игрового процесса, так и настройки сервера по-умолчанию! Не перепутайте.

Следующая секция, на которую стоит обратить внимание в INI-файле — [Engine.DemoRecDriver] и важнейшие её параметры NetServerMaxTickRate и LanServerMaxTickRate. Я рекомендую ставить минимум 60. Это включает на сервере запись так называемых серверных демок, при просмотре которых можно увидеть, как двигался каждый игрок, кто из чего стрелял и так далее. Некоторые особо маньячные товарищи, используя такие демки стороны сервера, и потом с помощью unreal-скриптов, жутко кривого Unreal Editor-а и видеоредактора делают потрясные демки:


Не знаю, сколько времени потребуется красноглазить с нереальными скриптами в нереальном редакторе, но серверная демка вам понадобится совершенно точно. И чем выше *MaxTickRate-ы — тем лучше. По умолчанию стоит вроде 20, авторы таких демок советую ставить 60. Увеличение этого параметра больше грузит процессор, но производительность современных процессоров это позволяет.

Чтобы старые демки не забивали впустую место, добавим в крон пользователю ut2004 такие строчки:

# Delete old server-side demos
30      23      *       *       *       find /usr/games/ut2004/Demos/ -name "*.demo4" -mtime +5 -delete

Эта команда будет каждый день в половину двенадцатого ночи искать демки (файлы с расширением .demo4), созданные раньше 5 дней и удалять их. Если за 5 дней демку не соизволили скачать — значит, не особо и нужна была. В среднем одна демка весит несколько мегабайт, и с помощью параметра -mtime можно задать больший срок хранения старых демок.

Теперь о логах. Есть логи собственно сервера — это лог-файлы, указанные в скрипте запуска в параметре log= , пишутся они в ./System, и при шатано работающем сервере туда смотреть особо не требуется. А есть ещё логи матчей, включаемые опцией bLocalLog=True в секции [Engine.GameStats] серверного ини-файла. Эти логи хранятся в ./UserLogs, свой файл на каждый сыгранный матч. Именно эти логи будут нашим источником данных для онлайн-статистики.

И последняя важная секция — [IpDrv.HTTPDownload], параметр RedirectToURL которой содержит URL, откуда брать файлы, в нашем случае это «http://ut2.your-domain.local/files/&#187;. Для того, чтобы скачивание недостающих карт шло по протоколу HTTP (а не по встроенному протоколу unreal://, основанному на UDP и для передачи тяжелых файлов совершенно непригодному), включим опции AllowDownloads=true и DownloadManagers=IpDrv.HTTPDownload в [IpDrv.TcpNetDriver], не забыв также увеличить параметры Max*ClientRate.

На этом этапе сервер уже можно запустить и на нём погамать. Теперь настроим веб сервер для быстрой отдачи файлов по HTTP (это особенно полезно, когда на сервере стоят нестандартные карты и мутаторы — клиент их скачает с вашего сервера при коннекте, и ему не придется их искать по всему инету) и отдачу статистики.

Тут есть одна тонкость. Карта UT2004 помимо основного файла *.ut2 тянет за собой ряд зависимостей — текстуры, скрипты, звуки, 3D-модели, шейдеры и прочее. В каталоге игры эти файлы рассованы по соответствующим подкаталогам, тогда как при скачивании все эти файлы будут искаться просто по имени относительно нашего URL. Чтобы не дублировать файлы, и не хранить по сути вторую копию игры в виде жуткой каши, воспользуемся таким модулей апача, как mod_rewrite. Естественно, надо не забыть включить директивы htaccess и обработку симлинков.

Конфиг виртуалхоста:

# cat /etc/httpd/conf.d/games-web-servers.conf 
# Game-Servers
<Directory /var/www/html_ut2004>
    Options Indexes FollowSymLinks
    AllowOverride All
</Directory>

<VirtualHost *:80>
    ServerAdmin amin@dobro.local
    DocumentRoot /var/www/html_ut2004
    ServerName ut2.your-domain.local
</VirtualHost>

А в каталоге сайта сделаем такие симлинки:

# ls -l /var/www/html_ut2004
...
lrwxrwxrwx 1 root root     23 ноя 20 17:36 demo -> /usr/games/ut2004/Demos
lrwxrwxrwx 1 root root     17 ноя 20 17:36 .ut2_dir -> /usr/games/ut2004

Теперь создадим в корне сайта подкаталог files (прописанный в конфиге сервера, параметр RedirectToURL!), и внурь положим всего один файл .htaccess с таким содержанием /* осторожно, регулярные выражения, опасно для моска */:

# cat /var/www/html_ut2004/files/.htaccess
<Files ~ "\.(cfg|CFG|so|ini|INI)$">
    Deny from all
</Files>

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteRule  ^(.*).ut2$  /.ut2_dir/Maps/$1.ut2          [nocase,last]
    RewriteRule  ^(.*).ka$   /.ut2_dir/KarmaData/$1.ka      [nocase,last]
    RewriteRule  ^(.*).u$    /.ut2_dir/System/$1.u          [nocase,last]
    RewriteRule  ^(.*).uax$  /.ut2_dir/Sounds/$1.uax        [nocase,last]
    RewriteRule  ^(.*).ukx$  /.ut2_dir/Animations/$1.ukx    [nocase,last]
    RewriteRule  ^(.*).usx$  /.ut2_dir/StaticMeshes/$1.usx  [nocase,last]
    RewriteRule  ^(.*).utx$  /.ut2_dir/Textures/$1.utx      [nocase,last]
</IfModule>

Теперь при запросе на скачивание файла /files/DM-MyMap.ut2 mod_rewite сделает прозрачный редирект на /.ut2_dir/Maps/DM-MyMap.ut2, который уже будет доступен через наш симлинк. Обязательно надо запретить чтение ини-файлов — иначе пароли админа могут утечь, и вам могут поменять настройки сервера или испортить игровой процесс.

На этом этапе к серверу можно прикручивать новые карты и мутаторы — и клиентам не придется их искать и ставить вручную. Обновление файлов сервера также заметно упрощается. Осталось самая малость — прикрутить парсинг игровых логов в базу данных, чтобы можно было прямо на сайте посмотреть онлайн-статистику.

Сперва настроим MySQL. Для наших скромных целей используемая версия и модификация не важна. Если там будет maria-db, percona или ещё что-то — не суть. Как настраивать mysql — читайте в мануалах. В принципе, всё требуемое делается несколькими команадами через консольный клиент mysql, но также можно либо использовать графический клиент типа MySQL-Workbench или распаковать в подкаталог веб-сервера phpMyAdmin. Для работы первого потребуется открыть порт TCP:3306, а ял второго — поставить на систему пакеты php-mbstring и php-mcrypt. Поскольку руками в базу данных лазить потребуется крайне редко, пароли ставим стойкие, символов по 20 минимум, и кладём в текстовый файлик внутри рутового домашнего каталога, чтобы в будущем не забыть.

Ключевые действия для базы данных MySQL:
— ставим пароль root
— сносим базу test и пустого пользователя.
— создаем пользоватея ut2004_stat со стойким паролем
— создаём пустую базу ut2004_stat
— разрешаем пользователю ut2004_stat для БД ut2004_stat действия SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE_TMP_TABLE

Необходимые команды есть в документации к MySQL. Можно и ручками поправить системные таблицы, после чего дать команду FLUSH PRIVILEGES;
Теперь идём на http://www.utstatsdb.com/ и скачиваем последнюю версию UT StatsDB в виде tar-gz архива. Нам нужна обычная версия (без встроенных апачей, собранных под шиндошс) Не помешает скачать и UT StatsDB-Extra (mapimages). Распаковываем содержимое архива в подкаиталог stat нашего веб-сайта (/var/www/html_ut2004/stat) и настраиваем строго по README.txt из архива.
В процессе настройки (делается в веб-морде через /stat/admin.php) будет задан так называемый пароль для обновления статистики.
После этого в кронтаб пользователя ut2004 можно добавить строчку, которая будет каждый час добавлять в БД логи от новых матчей:

# Refresh statistics - parsing logs
0       *       *       *       *       wget -O /dev/null http://localhost/stat/logs.php?pass=[PASSSWORD]

Параметры коннекта к БД должны быть прописаны в /stat/includes/statsdb.inc.php , нам надо исправить $SQLdb, $SQLus, $SQLpw и $InitPass. В первые два прописываем ut2004_stat, в третий — пароль для ut2004_stat, в четвертый — длинную случайную строчку символов в 100.
После этого в веб-интерфейсе /stat/admin.php мы можем настроить параметры сбора статистики. Самый главный — путь к логам игровых матчей в Logs Config — Log Path:
ut2004_server_ut_stat_config1
После этого на вашем сайте должно получиться что-то подобное.
При этом стоит мониторить логи в /var/log/httpd/error.log, и при появлении ошибок — исправить их.
Хотя у меня всё поставилось без проблем.

Теперь имеет смысл написать простейший сайт-заглушку, на котором мы и разместим ссылки на статистику, каталог с демками и баннеры для мониторинга сервера. Для мониторинга игровых серверов мне понравился проект http://www.gs4u.net/ — просто дописываем адрес нашего сервера в адресную строку, и сгененированные строки баннеров вставлем на наш сайт.

Теперь сыграем на нашем сервере матч. После этого в каталоге с демками на сайте станет доступна серверная демка игрового процесса:
ut2004_server_recorded_demos
А после парсинга логов (ежечасного) в статистике на сайте появится запись о матче с кучей подробностей. Писькомерка отменная, да.

И конечно же — неизменная строчка для автозапуска:

# cat /etc/rc.d/rc.local
su - ut2004 -c "/home/ut2004/start_ut2k4_serv.sh"

БЭКАПЫ

В итоге мы получили свой сервер UT-2004 с серверными демками и детальной онлайн-статистикой.
В отличие от серверов кваки и дума (которые можно либо не бэкапить вообще, либо сделать один-единственный бэкап, который будет обновляться только при серьезных обновлениях), тут уже появляются данные, представляющие хоть и малую, но все-таки ценность, так что самое время научиться их регулярно бэкапить.

Для этого сперва создаем в MySQL пользователя backuper c длинным паролем, у которого будут глобальные привилегии дял блокировки таблиц и чтения. Создаём linux-пользователя backuper, и подготавливаем наш сервер для отдачи бэкапов бэкапному серверу по этой статейке: https://aminux.wordpress.com/2013/08/02/backups-over-ssh/

Для локального бэкапа я использую сразу два скрипта — один из них резервирует всё установленной целиком каждую неделю, а второй — только базу данных статистики, конфиги и скрипты.
Прописываютя бэкапные скрипты в РУТОВЫЙ кронтаб:

# crontab -l
15      0       *       *       *       /root/backup/backup.sh
30      5       *       *       6       /root/backup/backup_WEEKLY.sh

Содержимое скрипта для ежесуточного бэкапа:

# cat /root/backup/backup.sh 
#!/bin/bash

date=`date "+%Y_%m_%d"`;             # current date  [YYYY_mm_dd]
days_store='4';                      # Number of backups (N last days)
dir_open=/Backups/                   # directory for store backups
tgz_bin='tar --acls -p --selinux --xattrs --label="UT2.Game-Server" --gzip -cf ';
mysqldump_bin='/usr/bin/mysqldump --defaults-extra-file=/root/backup/mysql.cnf --extended-insert --quick ';

mkdir $dir_open/$date
chown root:backuper $dir_open/$date
chmod 700 $dir_open/$date   # Lock folder
cd $dir_open/$date
sync

$tgz_bin home_root.tgz /root /home/backuper
$tgz_bin home_ut2004.tgz /home/ut2004
$tgz_bin www.tgz /var/www/html*
$tgz_bin usr_ut2004.tgz /usr/games/ut2004/System/*.ini

$tgz_bin etc.tgz /var/spool/cron  /etc/rc.d/rc.local /etc/ssh /etc/sysconfig/netw* /etc/sysconfig/ip*table* /etc/passwd /etc/shadow /etc/sudoers /etc/resolv.conf /etc/group /etc/sysctl.conf /etc/fstab  \
        /etc/my.cnf /etc/php.ini /etc/httpd/conf*   \
       /etc/selinux/config /etc/selinux/targeted/seusers* /etc/selinux/targeted/modules/active/*.local /etc/selinux/targeted/contexts/files/*.local

$mysqldump_bin mysql user db tables_priv columns_priv | gzip -9 -c > mysql_sys.gz
$mysqldump_bin --databases ut2k4_stat | gzip -9 -c > mysql_ut2004_stat.gz

sha256sum * > _ut2.game-server.sha256

find $dir_open/$date -type f -exec chown backuper:backuper {} \;
find $dir_open/$date -type f -exec chmod 400 {} \;
find $dir_open/$date -type f -name "*ut2004*" -exec chown backuper:ut2004 {} \;
find $dir_open/$date -type f -name "*ut2004*" -exec chmod 440 {} \;
find $dir_open/$date -type f -name "*.sha256" -exec chmod 440 {} \;

chmod 750 $dir_open/$date   # Unlock folder

echo '   ... Delete old backups ...';
find $dir_open -mtime +$days_store -delete     # store backups for N last days

echo "   ... Complete !\n\n";

Параметры коннекта к БД для бэкапа:

# cat /root/backup/mysql.cnf 
[client]
host=localhost
port=3306
user=backuper
password=BACKUPER-PASSWORD

Скрипт для полного бэкапа всего сервера:

# cat /root/backup/backup_WEEKLY.sh
#!/bin/bash

date=`date "+%Y_%m_%d"`;             # current date  [YYYY_mm_dd]
dir_open=/Backups/WEEKLY_$date       # directory for store backups
tgz_bin='tar --acls -p --selinux --xattrs --label="UT2--WEEKLY" --gzip -cf ';

mkdir $dir_open
cd $dir_open

chown root:backuper $dir_open
chmod 750 $dir_open   # Lock folder
sync

$tgz_bin usr_games_ut2k4.tgz /usr/games/ut2004

sha256sum * > _sha256sum.sha256

Теперь у нас будут бэкапы, которые сможет забрать бэкапный сервер.

Как видите, поднятие сервера UT 2004 чуть сложнее, чем кваки и дума, но ничего принципиально сложного нет.
Однако полученное умение делать бэкапы и работать с MySQL нам очень понадобиться, когда мы будем поднимать следующий игровой сервер, гораздо более сложный в настройке. Какой именно — пока не скажу, следите за новостями =)

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