Если вы занимаетесь администрированием, велика вероятность что рано или поздно встанет вопрос — «На клиентских машинах стоит антивирус Nod32, надо бы создать для них единое зеркало обновлений». И тут возможны несколько путей развития сюжета:
- «Сервер на Windows, денег достаточно». Тут всё довольно просто — покупаем лицензию, ставим нужный дистрибутив Nod32 на сервер, настраиваем, радуемся. Вариант более мифический, так как крайне редко, когда на IT «денег достаточно».
- «Сервер на Windows, денег не достаточно». Тут возможны варианты. Начиная от использования варезных лицензий, до ручного скриптинга и использования Linux-решений (cygwin в помощь).
- «Сервер на Linux». Деньги в этом случае особого значения просто не имеют. У нас есть руки, есть голова, и есть желание сделать всё довольно качественно и надежно.
Вот про третий вариант мы сейчас и поговорим.

Часть, которую можно пропустить
«Очередное велосипедостроение» подумают некоторые, и будут правы от части. Стоит немного поискать — и найдутся множество примеров аналогичных решений. И чем же это отличается? Тут я бы хотел немного удариться в лирику, описав причины которыми руководствовался, какие были плюсы и минусы найденных решений и почему они не подошли. Но, дорогой читатель, ты наверняка всегда пролистываешь эту часть, подбираясь поближе к исходникам и другим более интересным моментам. Я не стану затягивать и думаю, что некоторые решения, описанные в скрипте ты сможешь взять для себя на вооружение. Для меня это был не плохой опыт и рабочий результат, который проверен на нескольких «боевых» серверах. Исходя из соображений «поделиться положительным опытом» и был написан этот пост.
Системные требования:
- Bash (тестировал на версиях 4.1.11(2) и 4.2.24(1) — полет без ошибок);
- Apache для раздачи файлов и показа морды (опционально, тестировалось на версии 1.3.42). Для раздачи по smb этот пункт, разумеется, вычеркиваем;
- Наличие и разрешение на запуск 'curl' (проверка состояния источника), 'wget' (скачивание файлов), 'rm', 'mkdir', 'mv' и 'unrar' (для работы с официальными зеркалами).
Некоторые особенности:
- Работает как с официальными серверами, так и "пиратскими";
- Не требует вывода индекса (списка файлов) для того, чтоб забрать файлы обновлений (привет первой половине всех найденных в гугле решений);
- Разбирает 'update.ver' и создает новый (разные сервера по разному указывают пути к файлам обновлений — встречал полные пути, относительные, только имена файлов; привет второй половине всех найденных в гугле решений);
- Имеет возможность проверки под-директорий (иногда разные сервера хранят под разные версии обновления в разных под-директориях);
- Имеет возможность не скачивать сами файлы обновлений, а лишь поддерживать в актуальном виде 'update.ver'. Удобно, если раздающий обновления сервер имеет ограниченный траффик, или недостаточно ресурсов. Такая штука работает, на удивление, даже с официальными серверами — доступ у них по прямым ссылкам к файлам без авторизации (скорее всего — баг, и будет через какое-то время исправлен);
- Всегда используется политически корректный User-Agent (по крайней мере — очень похожий и проходящий валидацию). Более того, при каждом запуске скрипта некоторые его части (номера версий) случайным образом генерируются, так что идентифицировать скрипт чтоб
сделать бякузаблокировать — в общей куче становится ещё сложнее; - Настройки лимитов скорости и паузы между запросами вынесены в секцию настроек (удобно снизить нагрузку на канал и сервер);
- Подробные комментарии (на ломаном английском) и приятный, подробный вывод;
- Скачивает только обновленные файлы (--timestamping и более ничего);
- Работает без проблем на Apache версии 1.3.x, выводит приятную взгляду мордашку (в которую встраиваются ссылки на дистрибутивы, какая-либо информация для пользователей, etc.);
Настройки:
Сразу же оговорюсь — найденные «пиратские» сервера в данном случае выступают сугубо ради тестирования. Более того — они довольно часто мрут. Остальное всё должно быть довольно понятно. Смотрим:
## Servers list. Format:
## updServer{N}=('http://mirror.url/path/' 'username' 'password');
## {N} - is numeric value 0..N (N declared in ~185 line, default '10')
## 'http://mirror.url/path/' - Server URL (with '/' at the end)
## 'username' - (not required) Login for auth
## 'password' - (not required) Password for auth
updServer0=('http://38.90.226.39/eset_eval/v4/' 'TRIAL-0117918823' 'nvm8v57sch');
updServer1=('http://traxxus.ch.cicero.ch-meta.net/nod32/');
updServer2=('http://eset.mega.kg/3/');
updServer3=('http://109.120.165.199/nod32/');
updServer4=('http://antivir.lanexpress.ru/nod32_3/');
updServer5=('http://itsupp.com/downloads/nod_update/');
## Check not only server URL, also - this included sub-dirs (without
## slash at the end)
also_chek_this_subdirs=('v3' 'v4' 'v5' 'v6' 'v7' 'nod');
## If 'createLinksOnly' = true - we create ONLY 'update.ver' with full
## links to original update files. Do NOT download updates files.
## If 'createLinksOnly' = false - we write to new 'update.ver' local
## links (files names only), and DOWNLOAD all updates files.
createLinksOnly=false;
## User-agent for 'wget'. Make some random values in it.
RD=$RANDOM;
USERAGENT="ESS Update (Windows; U; 32bit; VDB $((RD%15000+10000));
BPC $((RD%2+6)).0.$((RD%100+500)).0; OS: 5.1.2600 SP 3.0 NT; CH 1.1;
LNG 1049; x32c; APP eavbe; BEO 1; ASP 0.10; FW 0.0; PX 0; PUA 0; RA 0)";
## Path where we store mirror files. With '/' at the end
PathToSaveBase='/var/www/nod32upd/';
## Path to temp work directory (will created automaticly and removed
## after update finish)
PathToTempDir=$PathToSaveBase'.tmp/';
## 'wget' limits (required).
wget_wait_sec='3';
wget_limit_rate='512k';
В общих чертах работа скрипта сводится к следующей логике:
- Проверяем доступность серверов (запрашивая файл 'update.ver' по указанному адресу) по порядку, указанному в настройках;
- При подтверждении доступности сервера — скачиваем и разбираем файл 'update.ver' выковыривая имена файлов. После чего пишем новый 'update.ver' (без путей к файлам), и 'wget'-ом выкачиваем файлы, выковыренные ранее (только обновленные). Если необходимо (опция 'createLinksOnly') — создаем только файл 'update.ver' с ссылками на оригинальные расположения файлов, не скачивая сами файлы обновлений;
- Проверяем под-директории из списка, указанного в настройках (алгоритм как в предыдущем пункте);
- Убираем за собой, создаем файл-временную метку и 'robots.txt', запрещающий индексацию.
Вывод же его выглядит примерно так:

Если обновления раздавать все таки апачем, то у нас есть выбор — делать веб-морду, или не делать :) Я решил остановиться на первом варианте, и в текущем решении заключается она в 2х файлах (header и footer), её исходники так-же включены в репозиторий на GitHub. Необходимость страницы-заглушки обусловлена тем, что поднятое зеркало обслуживает различных клиентов, и им иногда просто дается ссылка на него. Клиент заходит, скачивает по ссылке дистрибутив со встроенными настройками, и радуется. При ручном разворачивании в пределах офиса рекомендую поднять «ESET Remote Administrator Server», и его адрес также «вшить» в дистрибутив.

В config.small.xml указываем необходимые настройки:
<?xml version="1.0" encoding="utf-8"?>
<ESET>
<SECTION ID="1000103">
<SETTINGS>
<PLUGINS>
<PLUGIN ID="1000400">
<PROFILES>
<NODE NAME="Enable" VALUE="1" TYPE="DWORD" />
<NODE NAME="Active" VALUE="@My profile" TYPE="STRING" />
<NODE NAME="@My profile" TYPE="SUBNODE">
<NODE NAME="UpdateType" VALUE="22" TYPE="DWORD" />
<NODE NAME="SelectedServer" VALUE="%%url_updates_server%%" TYPE="STRING" />
<NODE NAME="Username" VALUE="%%your_username%%" TYPE="STRING" />
<NODE NAME="Password" VALUE="" TYPE="PASS" />
</NODE>
</PROFILES>
<SETTINGS>
<NODE NAME="RegistrationType" VALUE="0" TYPE="DWORD" />
<SERVERS>
<NODE NAME="Server_0" VALUE="%%url_updates_server%%" TYPE="STRING" />
</SERVERS>
</SETTINGS>
</PLUGIN>
</PLUGINS>
<CLIENT>
<NODE NAME="GraphicMode" VALUE="FFFFFFFF" TYPE="DWORD" />
<NODE NAME="ShowSplash" VALUE="0" TYPE="DWORD" />
<NODE NAME="SimpleMenu" VALUE="0" TYPE="DWORD" />
<NODE NAME="AdvancedMenu" VALUE="1" TYPE="DWORD" />
</CLIENT>
</SETTINGS>
</SECTION>
</ESET>
Где %%url_updates_server%% — в обоих случаях идентичны и равны адресу нашего сервера обновлений. Самый простой способ получить конфиг — Окно «ESET NOD32 Antivirus» → «Настройки» → «Импорт и экспорт параметров». Из получившего xml-файла удаляем всё, кроме необходимых настроек (благо все секции очень хорошо названы).
Далее скрипт установки install.cmd:
@echo off
title "Run ESET Nod32 Installer"
cls
set AppToRun=ESET_NOD32_Antivirus_4.2.71.3_(32-bit)_(rus).msi
set CfgFile=config.small.xml
rem /qb - показывается процесс установки
rem /qn - тихий режим установки без gui
start "" "msiexec" /qb /package "%cd%%AppPath%%AppToRun%" ADMINCFG="%cd%%CfgPath%%CfgFile%"
@echo on
И всё это дело при помощи детища Евгения Рошала пакуется в SFX архив с параметрами:
Path=%TEMP%Nod32Install
Setup=%TEMP%Nod32Installinstall.cmd
Silent=1
Overwrite=1
Таким образом, при двойном клике по полученному бинарнику происходит тихая распаковка в %TEMP%Nod32Install, запускается install.cmd, который запускает установку ESET_NOD32_Antivirus_4.2.71.3_(32-bit)_(rus).msi с настройками из config.small.xml не спрашивая ничего у пользователя, но отображая процесс установки. Для малоопытных пользователей — самое то.
Описывать непосредственно исходники работы самого скрипта не вижу смысла, т.к. кому интересно — тот перейдет на по ссылке ниже и своими глазами всё посмотрит. Если будут поправки — буду рад их прочитать в комментариях и добавить в исходник.
Установка
- Качаем или клонируем последнюю версию с GitHub;
- Если раздаем через smb — создаем директорию и открываем к ней общий доступ с правами только на чтение; если через http — создаем отдельный virtualhost или директорию, доступную «из вне»;
- Кладем в неё файлы ".footer.html", ".header.html" и ".htaccess", проверяем;
- Кладем в директорию, не доступную «из вне» файл «update_nod32_mirror.sh». Открываем его, прописываем путь к директории, созданной в п.2;
- Даем права "
chmod +x update_nod32_mirror.sh
" и делаем пробный запуск "./update_nod32_mirror.sh
"; - Изучаем вывод, анализируем причину «почему сразу не заработало», пишем в личку, исправляем, радуемся;
- Ставим задание в крон, запускаем 3..4 раза в сутки.
Ссылка на GitHub: https://github.com/tarampampam/nod32-update-mirror
Автор: cmepthuk