📜 ⬆️ ⬇️

Comodo Internet Security Local Update Server

This manual will detail the process of raising your local Comodo update server on Windows without using any paid components. Unlike Comodo Offline Updater and analogs, there is no need to configure a proxy on the client side.

Requirements:


Windows 7 SP1 Pro x64 (IIS 6.7) will be used as a server. For newer OS installation and configuration is similar.
')

1) Installing IIS


"Enable or disable Windows components" in the "Add or Remove Programs" section, check "IIS" for installation. Automatically marked components are enough.



2) Script and logic for downloading updates


The script is written in PowerShell v4, so to work correctly on Windows 7 you need to update WMF4.0. Reboot after installation is required. 7-Zip is also required for unpacking. By itself, to run a script, you need to translate the PS Execution Policy to Unrestricted. This is done with the Set-ExecutionPolicy Unrestricted command.

Comodo updates are divided into 2 parts: the base and the update of the program itself. Files of both parts can be packaged or not. I recommend using packaged ones, since they occupy much less disk space - 290MB versus 635MB only in databases.
COU.ps1
# 2017/10/06 AcidVenom v6.1
# COU
# : cis, av, av-clean
param($1)
#######################################################################
#################### ######################
$7z = "C:\Program Files\7-Zip\7z.exe" # 7z.exe
$downloadpath = "C:\inetpub\wwwroot" #
$serverurl = "https://cdn.download.comodo.com" # Comodo
$inis = "5070" #
$proto = "10" #
$xx = "x32","x64" # ("x32","x64")
$cispacked = $True # (*.7z) ($True/$False)
$avpacked = $True # (*.cav.z) ($True/$False)
$release_notes = $True # Release Notes? ($True/$False)
#######################################################################
################### ##########################
$inispath = "$downloadpath\cis\download\updates\release\inis_$inis"
$recognizerspath = "$inispath\recognizers\proto_v$proto"
$updates58path = "$downloadpath\av\updates58"
$updatesurlpath = "$downloadpath\av\updatesurl"
$basespath = "$updates58path\sigs\bases"
$updatespath = "$updates58path\sigs\updates"
$urlpath = "$updatesurlpath\sigs\updates"
$tvlpath = "$downloadpath\av\tvl"
$inisurl = "$serverurl/cis/download/updates/release/inis_$inis"
$recognizersurl = "$inisurl/recognizers/proto_v$proto"
$updates58url = "$serverurl/av/updates58"
$updatesurlurl = "$serverurl/av/updatesurl"
$basesurl = "$updates58url/sigs/bases"
$updatesurl = "$updates58url/sigs/updates"
$urlurl = "$updatesurlurl/sigs/updates"
$tvlurl = "$serverurl/av/tvl"
#######################################################################
############### ###################
if ($1 -eq "cis") {
if ($cispacked -eq $True) {$packed = ".7z"} else {$packed = ""}
# Updates
$testinis = Test-Path $inispath
$testrecognizers = Test-Path $recognizerspath
if ($testinis -eq $False) {New-Item -ItemType Directory -path $inispath}
if ($testrecognizers -eq $False) {New-Item -ItemType Directory -path $recognizerspath}
foreach ($x in $xx) {
Invoke-WebRequest -Uri "$inisurl/cis_update_$x.xml$packed" -OutFile "$inispath/cis_update_$x.xml$packed"
if ($cispacked -eq $True) {& $7z x -o"$inispath" $inispath\cis_update_$x.xml.7z -y}
$lines = Get-Content $inispath\cis_update_$x.xml | ? {$_ -match "<file name=" -and $_ -notmatch "\\"}
foreach ($line in $lines) {
$line = $line -split " "
$name = $line -match "name="
$name = $name -replace "name=|`"",""
$sha = $line -match "sha="
$sha = $sha -replace "sha=|`"",""
$sha = $sha.toupper()
$src = $line -match "src="
$src = $src -replace "src=|`"|>",""
$srcf = $src.substring(0,$src.lastindexof("/"))
$srcp = $src -replace "\/","\"
$fileexist = Test-Path "$inispath\$srcp$packed"
$folderexist = Test-Path "$inispath\$srcf"
if ($fileexist -eq $True) {
$remove = $False
if ($cispacked -eq $True) {
try {
$remove = $True
& $7z x -o"$inispath/$srcf" $inispath/$srcp.7z -y
}
catch {}
}
$hash = Get-FileHash "$inispath/$srcp" -Algorithm SHA1
if ($remove -eq $True) {Remove-Item "$inispath\$srcp"}
if ($hash.Hash -eq $sha) {Continue}
}
if ($folderexist -eq $False) {New-Item -ItemType Directory -path "$inispath\$srcf"}
try {Invoke-WebRequest -Uri "$inisurl/$src$packed" -OutFile "$inispath/$srcp$packed"}
catch {Invoke-WebRequest -Uri "$inisurl/$src" -OutFile "$inispath/$srcp"}
}
if ($cispacked -eq $True) {Remove-Item "$inispath\cis_update_$x.xml"}
# Recognizers
Invoke-WebRequest -Uri "$recognizersurl/cmdscope_update_$x.xml$packed" -OutFile "$recognizerspath/cmdscope_update_$x.xml$packed"
if ($cispacked -eq $True) {& $7z x -o"$recognizerspath" $recognizerspath\cmdscope_update_$x.xml.7z -y}
$lines = Get-Content $recognizerspath\cmdscope_update_$x.xml | ? {$_ -match "<file name=" -and $_ -notmatch "\\"}
foreach ($line in $lines) {
$line = $line -split " "
$name = $line -match "name="
$name = $name -replace "name=|`"",""
$sha = $line -match "sha="
$sha = $sha -replace "sha=|`"",""
$sha = $sha.toupper()
$src = $line -match "src="
$src = $src -replace "src=|`"|>",""
$srcf = $src.substring(0,$src.lastindexof("/"))
$srcp = $src -replace "\/","\"
$fileexist = Test-Path "$recognizerspath\$srcp$packed"
$folderexist = Test-Path "$recognizerspath\$srcf"
if ($fileexist -eq $True) {
$remove = $False
if ($cispacked -eq $True) {
try {
$remove = $True
& $7z x -o"$recognizerspath/$srcf" $recognizerspath/$srcp.7z -y
}
catch {}
}
$hash = Get-FileHash "$recognizerspath/$srcp" -Algorithm SHA1
if ($remove -eq $True) {Remove-Item "$recognizerspath\$srcp"}
if ($hash.Hash -eq $sha) {Continue}
}
if ($folderexist -eq $False) {New-Item -ItemType Directory -path "$recognizerspath\$srcf"}
try {Invoke-WebRequest -Uri "$recognizersurl/$src$packed" -OutFile "$recognizerspath/$srcp$packed"}
catch {Invoke-WebRequest -Uri "$recognizersurl/$src" -OutFile "$recognizerspath/$srcp"}
}
if ($cispacked -eq $True) {Remove-Item "$recognizerspath\cmdscope_update_$x.xml"}
}
##################################################
#Release Notes
if ($release_notes -eq $True) {
$rn = "ComodoLogo.png","Fixed.png","Header.png","Improved.png","Logo.png","New.png","Panel_body.png","Panel_footer.png","Panel_header.png","Panel_left_body.png","Panel_left_footer.png","Panel_left_header.png","Panel_left_hr.png"
$testrn = Test-Path "$inispath\images"
if ($testrn -eq $False) {New-Item -ItemType Directory -Path "$inispath\images"}
Invoke-WebRequest -Uri "$inisurl/release_notes.html" -OutFile "$inispath/release_notes.html"
foreach ($r in $rn) {Invoke-WebRequest -Uri "$inisurl/images/$r" -OutFile "$inispath/images/$r"}
}
}
#######################################################################
################### #####################
elseif ($1 -eq "av") {
if ($avpacked -eq $True) {$packed = ".z"} else {$packed = ""}
#updates58
$folders = "$basespath","$updatespath","$urlpath","$tvlpath"
foreach ($folder in $folders) {
$testfolder = Test-Path "$folder"
if ($testfolder -eq $False) {New-Item -ItemType directory -Path "$folder"}
}
Invoke-WebRequest -Uri "$tvlurl/delven.txt" -OutFile "$tvlpath\delven.txt"
Invoke-WebRequest -Uri "$updates58url/versioninfo.ini" -OutFile "$updates58path\versioninfo.ini"
$file = Get-Content "$updates58path\versioninfo.ini"
$base = $file | Where {$_ -match "MaxBase="}
$base = $base.substring(8)/1
$inc = $file | Where {$_ -match "MaxAvailVersion="}
$inc = $inc.substring(16)/1
$diff = $file | Where {$_ -match "MaxDiff="}
$diff = $diff.substring(8)/1
$incr = $inc - $diff + 1
if ($incr -gt $base) {$incr = $base + 1}
$testbases = Test-Path "$basespath\BASE_END_USER_v$base.cav$packed"
if ($testbases -eq $False) {Invoke-WebRequest -Uri "$basesurl/BASE_END_USER_v$base.cav$packed" -OutFile "$basespath\BASE_END_USER_v$base.cav$packed"}
do {
$testupdates = Test-Path "$updatespath\BASE_UPD_END_USER_v$incr.cav$packed"
if ($testupdates -eq $False) {Invoke-WebRequest -Uri "$updatesurl/BASE_UPD_END_USER_v$incr.cav$packed" -OutFile "$updatespath\BASE_UPD_END_USER_v$incr.cav$packed"}
$incr++
}
while ($incr -le $inc)
# updatesurl
Invoke-WebRequest -Uri "$updatesurlurl/versioninfo.ini" -OutFile "$updatesurlpath\versioninfo.ini"
$file = Get-Content "$updatesurlpath\versioninfo.ini"
$base = $file | Where {$_ -match "MaxBase="}
$base = $base.substring(8)
$inc = $file | Where {$_ -match "MaxAvailVersion="}
$inc = $inc.substring(16)
$incr = $base/1 + 1
do {
$testupdatesurl = Test-Path "$urlpath\BASE_UPD_END_USER_v$incr.cav.z"
if ($testupdatesurl -eq $False) {Invoke-WebRequest -Uri "$urlurl/BASE_UPD_END_USER_v$incr.cav.z" -OutFile "$urlpath\BASE_UPD_END_USER_v$incr.cav.z"}
$incr++
}
while ($incr -le $inc)
}
#######################################################################
##################### #####################
elseif ($1 -eq "av-clean") {
if ($avpacked -eq $True) {$packed = ".z"} else {$packed = ""}
$test58ver = Test-Path "$updates58path\versioninfo.ini"
$testurlver = Test-Path "$updatesurlpath\versioninfo.ini"
#$message = ""
if ($test58ver -eq $True) {
$file = Get-Content "$updates58path\versioninfo.ini"
$base = $file | Where {$_ -match "MaxBase="}
$base = $base.substring(8)/1
$aval = $file | Where {$_ -match "MaxAvailVersion="}
$aval = $aval.substring(16)/1
$diff = $file | Where {$_ -match "MaxDiff="}
$diff = $diff.substring(8)/1
$del = $aval - $diff + 1
if ($del -gt $base) {$del = $base + 1}
$names = (Get-ChildItem -Path "$basespath").basename -replace "BASE_END_USER_v|.cav",""
foreach ($name in $names) {
$name = $name/1
if ($name -lt $base) {Remove-Item "$basespath\BASE_END_USER_v$name.cav$packed"}
}
$names = (Get-ChildItem -Path "$updatespath").basename -replace "BASE_UPD_END_USER_v|.cav",""
foreach ($name in $names) {
$name = $name/1
if ($name -lt $del) {Remove-Item "$updatespath\BASE_UPD_END_USER_v$name.cav$packed"}
}
}
if ($testurlver -eq $true) {
$file = Get-Content "$updatesurlpath\versioninfo.ini"
$aval = $file | Where {$_ -match "MaxAvailVersion="}
$aval = $aval.substring(16)/1
$diff = $file | Where {$_ -match "MaxDiff="}
$diff = $diff.substring(8)/1
$del = $aval - $diff
$names = (Get-ChildItem -Path "$urlpath").basename -replace "BASE_UPD_END_USER_v|.cav",""
foreach ($name in $names) {
$name = $name/1
if ($name -lt $del) {Remove-Item "$urlpath\BASE_UPD_END_USER_v$name.cav.z"}
}
}
}
#######################################################################
#################### ###################
else {exit}
view raw COU.ps1 hosted with ❤ by GitHub


List of changes
v6 - Fixed the problem of lack of incremental databases in some cases, fixed database cleanup.
v6.1 - In the next update, we changed deletevendors.txt to delven.txt.

The script uses the following user variables:

$ 7z - Path to 7z.exe
$ downloadpath - The path for downloading, folders are created automatically. In this example, “C: \ inetpub \ wwwroot”
$ serverurl - Comodo server to download from
$ inis - Update branch, more on that below.
$ proto - the version of the recognizer
$ xx - Bit rate for download ("x32", "x64"), you can specify only one
$ cispacked - Downloading packaged (* .7z) updates or not. Possible values: $ true or $ false
$ avpacked - Download packaged (* .cav.z) databases. Possible values: $ true or $ false
$ release_notes - Downloading Release Notes. Possible values: $ true or $ false.

Regarding the program's update branches: up to version 8.2.0.4508 inclusive, inis_4010 is used, then any existing above, for example 4080. That is, if you need to update clients of versions 8 and below, then you need to deflate inis_4010 ($ inis = "4010", $ proto = "6") and current ($ inis = "4080", $ proto = "10"). Thus, I managed to upgrade from v6 to the current v10 with two reboots without any problems.

To facilitate administration, the script has 3 startup parameters:

cis - download program updates
av - database download
av-clean - removal of obsolete databases
It remains only to add tasks with a specified frequency in the Task Scheduler.

Add example




3) Configure IIS


In this example, the Default Web Site, created automatically, will be used.
For debugging, I recommend enabling the "Browse Directory". To do this, select the desired site, go to the "Browse Directory" menu and click "Enable" on the right side.

To download updates correctly, you need to configure MIME Types: in the corresponding menu item, add file extensions and assign application / octet-stream type to them.

MIME Types for Packaged Updates
.ini
.7z

MIME types for unpacked updates
.xml
.ini
.dat
.lang
.set
.theme
.sys
.cav

4) Rewrite module


Installing the URL Rewrite 2.1 module is trivial. This module is required to redirect to the desired inis_ branch.
After installation, you must re-open IIS Manager, otherwise the corresponding menu item will not be visible. To configure, go to the “URL Redefinition” item and add an empty rule for incoming traffic with the following content:

Name: arbitrary
Template:
(cis / download / updates / release / inis) _ [0-9] * / (. *)
Override URL:
{R: 1} _4080 / {R: 2}

In the last address, specify those numbers that are specified in the script in the $ inis variable.

Self-Test Image


If you need to update outdated versions, you need to create another rule above.

Name: arbitrary
Template:
(cis / download / updates / release / inis) _ [0-9] * / (. *)
Conditions (match with any of the elements):
{REQUEST_URI},. * / Inis_40 [0-1] 0 /.* and {REQUEST_URI},. * / Inis_ [1-3] [0-9] * /. *
Override URL:
{R: 1} _4010 / {R: 2}
Stop processing subsequent rules

Self-Test Image


This completes the server side setup.

5) Setting up clients on a local server


The easiest way to do this manually or through the registry. In the registry, the list of update servers is located at HKEY_LOCAL_MACHINE \ SOFTWARE \ COMODO \ CIS \ Options in the UpdateURL parameter.
For example, this option looks like when setting up the av.local server and disabling the default server: av.local ! Https: //download.comodo.com/

As a result, you get a local Comodo update server and significantly reduce the load on the external channel.

Source: https://habr.com/ru/post/333420/


All Articles