Блокировка Web-узлов с помощью ISA Server. Механизм фильтрации контента доменов из «черных списков»

Такие средства для фильтрации контента, как продукты фирм Websense и SurfControl, прекрасно справляются с задачей управления доступом пользователей к нежелательным Web-узлам, но обходятся они недешево. Те же, кто располагает системой Microsoft ISA Server 2004 или ISA Server 2006, для блокировки доступа к запрещенным сайтам могут использовать ее в комбинации со службой «черных списков».

Службы «черных списков» предоставляют списки Web-узлов, содержащих материалы порнографического характера, материалы, разжигающие ненависть и призывающие к насилию, инструменты хакеров или другой запрещенный контент. За умеренную плату можно стать абонентом такой службы и с помощью сценария импортировать ее список (обычно обновляемый раз в неделю) в ISA Server. Кстати, к данной статье я прилагаю бесплатно распространяемый сценарий для выполнения этой задачи. Хотя кому-то может показаться, что речь идет о сложной процедуре, на самом деле все реализуется достаточно просто. Давайте рассмотрим все этапы процесса от начала до конца.

Шаг 1. Задействовать систему ISA Server

Разумеется, для решения поставленной задачи необходимо располагать пакетом ISA Server 2004 или 2006, а Web-браузеры пользователей должны быть настроены таким образом, чтобы доступ в Internet по протоколу HTTP осуществлялся через эту систему. При подготовке статьи я исходил из того, что данные условия выполнены; если нет — можно загрузить пробную версию ISA Server по адресу http://www.microsoft.com/isaserver. Если же в распоряжении администратора имеется Microsoft Windows Small Business Server (SBS) 2003 Premium Edition Service Pack 1 (SP1) или SBS 2003 Premium Release 2 (R2), нужно иметь в виду, что в эти пакеты входит ISA Server 2004.

Шаг 2. Сформировать набор имен доменов

В системе ISA Server администратор может, воспользовавшись правилами политики брандмауэра, предоставить или заблокировать доступ пользователей к набору имен доменов — т. е. к списку доменов DNS. Список может включать как полные доменные имена (например, www.windowsitpro.com), так и домены с подстановочными символами (например, *.microsoft.com). Набор доменных имен нужен нам для того, чтобы внести в него сотни тысяч доменов, доступ к которым требуется заблокировать. Назовем его Bad-Sites.

Чтобы создать набор доменных имен Bad-Sites, следует открыть оснастку Microsoft Management Console (MMC) ISA Server Management, открыть контейнер сервера ISA Server и щелчком мыши указать контейнер Firewall Policy. Далее правой клавишей мыши нужно щелкнуть на контейнере Firewall Policy и выбрать пункт View и элемент Task Pane (если он еще не выбран). В правой части экрана откроется панель задач. В панели задач следует перейти на вкладку Toolbox, после чего выбрать категорию Network Objects. Правой клавишей мыши щелкните на пункте Domain Name Sets, а затем выберите пункт New Domain Name Set. Введите имя Bad-Sites и нажмите кнопку ОК. Затем нужно сохранить внесенные изменения, нажав кнопку Apply в верхней части окна консоли. На экране 1 показан набор доменных имен во вкладке Toolbox. Список Bad-Sites пока пуст, но мы скоро заполним его именами доменов, внесенных в «черный список».

Шаг 3. Создать правило блокировки

Когда список нежелательных доменов Bad-Sites будет готов, мы заблокируем доступ к этим сайтам с помощью правила, указанного в политике брандмауэра. Это правило будет расположено как раз перед правилом, которое в иных случаях открывает доступ в Internet (я исхожу из того, что последнее правило уже существует).

Чтобы создать правило блокировки направленных в домены Bad-Sites запросов, следует щелкнуть на правиле политики брандмауэра, которое позволяет пользователям выходить в Internet. Теперь правой клавишей мыши нужно щелкнуть на контейнере Firewall Policy в консоли управления ISA Server Management console, выбрать в контекстном меню пункты New, Access Rule, присвоить правилу имя Site_ Blocker, нажать кнопку Next, выбрать Deny, нажать Next, принять для правила предлагаемую по умолчанию настройку «применять ко всему исходящему трафику» и щелкнуть Next. Нажмите кнопку Add и внесите в список источников Internal Network (чтобы увидеть объект Internal Network, следует открыть папку Networks и нажать Next). Нажмите кнопку Add и добавьте имя Bad-Sites в поле назначения (чтобы увидеть объект Bad-Sites, надо открыть папку Name Sets).

Экран 1. Панель управления ISA Server с политиками

Нажмите кнопку Next. Примите предлагаемый по умолчанию параметр All Users, затем щелкните Next и Finish. Затем правой клавишей мыши надо щелкнуть на новом правиле Site_Blocker и в случае необходимости переместить его вверх или вниз, чтобы расположить над правилом, позволяющим пользователям выходить в Internet. Сохраним внесенные изменения, нажав кнопку Apply в верхней части окна консоли. Завершенное правило Site_Blocker, включая набор Bad-Sites в столбце To, можно увидеть на экране 1.

Шаг 4. Загрузить «черный список»

Итак, мы имеем правило Site_Blocker, блокирующее доступ к доменам из списка Bad-Sties. Пока этот список пуст, пришло время заполнить его сотнями тысяч доменов с нежелательным контентом; отметим, кстати, что его следует обновлять по меньшей мере еженедельно. Но где можно получить эти сведения в пригодной для использования форме? И как загрузить их в наш список? В Internet имеются бесплатно распространяемые и недорогие источники сведений для «черных списков», которые могут быть импортированы в наш список Bad-Sties. Возможно, среди бесплатно распространяемых «черных списков» наибольшей популярностью пользуются squidGuard (http://www.squidguard.org/blacklist) и DansGuardian (http://www.dansguardian.org). Эти списки предназначены для фильтров UNIX/Linux, но они вполне совместимы и с ISA Server.

Я предпочитаю работать со службой «черных списков» по адресу http://www.urlblacklist.com. На данный момент компания может раз в неделю загружать по этому адресу один обновленный «черный список» за 190 долл. в год; при этом ограничения на число пользователей не предусматриваются. Размеры абонентской платы, взимаемой с образовательных учреждений и отдельных пользователей, меньше.

URLBlacklist.com — не бесплатная, а коммерческая служба, поэтому ее списки управляются лучше, и выше вероятность того, что через год эта организация все еще будет существовать. Небольшой демонстрационный список для проверки возможностей службы можно загрузить бесплатно.

Когда вы загрузите один из этих «черных списков», скорее всего, он будет сжат по технологии GNU zip (gzip) в файл .tar, т. е. будет иметь расширение .tar.gz. Для распаковки текстов «черных списков» можно использовать графические программы, такие как WinZip (http://www.winzip.com), или бесплатно получить Windows-версии файлов gunzip.exe и tar.exe по адресу http://unxutils.sourceforge.net (обратите внимание, что unxutils пишется с одним i) или в бесплатно распространяющей свои рассылки службе Microsoft Windows Services for Unix (SFU) по адресу http://www.microsoft.com/technet/interopmigration/unix/sfu.

Чтобы распаковать полученный по адресу http://www.urlblacklist.com файл bigblacklist.tar.gz, нужно переместить файл bigblacklist.tar.gz в новую папку и выполнить в оболочке CMD следующие команды:

gunzip.exe bigblacklist.tar.gz tar.exe -xf bigblacklist.tar

В результате будет создана новая папка, содержащая все файлы «черного списка». Эти файлы будут размещаться в подпапках, названных в соответствии с их содержимым. К примеру, одна из этих подпапок будет иметь имя porn и в папке porn будет находиться большой текстовый файл с именем domains.

Для импортирования текстового файла porn\domains в наш список блокируемых доменов Bad-Sites мы воспользуемся сценарием. Затем прибегнем к помощи еще одного сценария для того, чтобы автоматизировать загрузку обновлений «черного списка» и их импорт в набор доменных имен Bad-Sites.

Шаг 5. Импортировать «черный список» в Bad-Sites

Получите сценарий ImportBlacklist.vbs и скопируйте его и еще один файл на жесткий диск ISA Server. О втором файле ScheduledUpdate.bat я расскажу чуть позже.

Сценарий ImportBlacklist.vbs обеспечивает импорт текстового файла с именами доменов в набор доменных имен системы ISA Server 2004 или 2006 (как Standard edition, так и Enterprise edition). Скопируем файл «черного списка» porn\domains на систему ISA Server, где установлен сценарий ImportBlacklist.vbs. Затем заполним список Bad-Sites, выполнив в оболочке CMD следующую команду (вся команда должна разместиться на одной строке):

cscript.exe ImportBlacklist.vbs Bad-Sites domains

Чтобы импортировать домены из нескольких файлов, нужно объединить их в один большой файл. Так, для присоединения одного файла (domains1) к концу второго файла (domains2) следует использовать команду Type в виде:

type domains1 >> domains2

Можно применить и другое решение. Создадим несколько наборов Bad-Sites — по одному для каждого файла, который предстоит импортировать, — и добавим все эти наборы Bad-Sites в поле destination правила Site_Blocker.

По умолчанию сценарий сначала удаляет содержимое доменного набора имен, а затем осуществляет импорт из текстового файла, поэтому операции по управлению списком лучше всего осуществлять в текстовом файле, а не в самом доменном наборе имен. По завершении выполнения сценария нужно просмотреть новое содержимое списка Bas-Sites, для чего требуется обновить панель управления ISA Server (либо закрыть и вновь открыть консоль, что часто занимает меньше времени).

Вот и все. Теперь если пользователь запросит файл из заблокированного домена, на экране его компьютера отобразится страница с сообщением об ошибке. Если соответствующий HTTP-запрос направляется через ISA Server, этот механизм блокировки доменов функционирует даже в тех случаях, когда браузер пользователя не сконфигурирован в качестве proxy-клиента Web. Но все-таки лучше настраивать все браузеры как proxy-клиенты. А падение производительности вследствие выполнения операций по блокировке доменов довольно незначительно, поскольку речь идет не о поиске по шаблону, а о простом сопоставлении строк с запрошенным пользователем URL.

Шаг 6. Загружать обновления по расписанию

Такие операции, как загрузка обновлений «черных списков» и импорт их в ISA Server, не составляют особого труда. Их можно выполнять и вручную, но удобнее использовать сценарии. Пакетный сценарий на базе бесплатно распространяемой Windows-версии файла wget.exe (http://www.gnu.org/software/wget) может еженедельно или ежесуточно загружать последнюю версию вашего любимого «черного списка», затем запускать файлы gunzip.exe, tar.exe и ImportBlacklist.vbs для обновления системы ISA Server в автоматическом режиме.

В листинге 2 показан простой пакетный сценарий ScheduledUpdate.bat, предназначенный для выполнения указанных задач. Сценарий загружает небольшой демонстрационный список с узла URLBlacklist.com и импортирует содержащийся в нем список porn в доменный набор имен сервера ISA Server, именуемый Bad-Sites, с помощью сценария ImportBlacklist. В реальных условиях эксплуатации нужно будет отредактировать этот сценарий так, чтобы он загружал полную версию оплаченного «черного списка», а также выполнял проверку на наличие ошибок, регистрации и/или по извещению администратора. Для указания времени, в которое должен выполняться сценарий, следует использовать приложение Scheduled Tasks панели управления.

Важно регулярно обновлять «черные списки», так как новые хакерские сайты обнаруживаются в Internet каждую неделю. Составить график этой работы очень важно, поскольку импорт больших файлов требует времени. Если, к примеру, у сервера, оснащенного одним процессором Pentium 4 на 2,2-ГГц, на импорт 100 тыс. доменов из файла «черного списка» уходит менее 10 минут, то на импорт 500 тыс. доменов эта система потратит три часа. Причем в процессе импорта загрузка процессора будет стабильно составлять 100%. Поэтому назначайте операции по обновлению «черных списков» на периоды с низкой нагрузкой и при выполнении сценария ImportBlacklist.vbs используйте параметр \belownormal (как указано в последней строке листинга 2), который снижает приоритет многозадачности. Другим процессам ISA Server будет проще получить свою долю циклов процессора.

Отметим, что для обеспечения выполнения пакетного сценария нужно будет разрешить серверу ISA Server выходить в Internet по протоколу HTTP. Действуя в соответствии с инструкциями, изложенными в шаге 3, необходимо создать правило, предоставляющее системе ISA Server доступ только к сайту, откуда будет осуществляться загрузка «черного списка». В качестве значения для поля source network нужно установить Local Host, а для поля destination URL — адрес сайта, откуда будет загружаться «черный список».

Импорт «черных списков» для блокировки доступа к доменам — лишь один из примеров использования сценариев в работе ISA Server. На таких сайтах, как http://www.isatools.org, http://www.isaserver.bm и http://www.isascripts.org (мой сайт), можно найти множество других сценариев, а те, кто хочет писать собственные сценарии, могут воспользоваться поставляемым корпорацией Microsoft комплектом средств разработчика ISA Server software development kit (SDK).

По масштабируемости и функциональности описанные в данной статье решения на базе «черных списков» и сценариев уступают коммерческим фильтрам контента, но тех, кто ограничен в средствах, они вполне могут устроить.

Джейсон Фоссен (
jason@enclaveconsulting.comЭтот e-mail адрес защищен от спам-ботов, для его просмотра у Вас должен быть включен Javascript
) — владелец зарегистрированной в г. Даллас компании Enclave Consulting. Подготовил для института SANS Institute недельный учебный курс Windows Security and ISA Server. Имеет звание Most Valuable Professional по Microsoft ISA Server

 

Другие средства фильтрации содержимого Web

Наряду с функцией блокировки списка сайтов ISA Server наделен и другими средствами фильтрации содержимого Web, которые могут быть полезны. Поэкспериментируем с этими возможностями. Действуя в соответствии с инструкциями, изложенными в шаге 3 основной статьи, создадим еще одно правило блокировки, но на этот раз назовем его File_Blocker и в поле destination укажем не имя Bad-Sites, а внешнюю сеть. Переместим правило File_Blocker так, чтобы в списке политики брандмауэра оно размещалось как раз над правилом Site_Blocker.

Правой клавишей мыши нужно щелкнуть на правиле File_Blocker, в открывшемся меню выбрать пункт Properties и перейти на вкладку Content Types. По умолчанию правило применяется ко всем типам контента, т. е. оно блокирует загрузку из среды Web любых файлов. Это не входит в наши планы. Выберите настройку Selected content types и выставьте только флажки Audio и Video, как показано на экране A. Теперь ISA Server будет блокировать попытки пользователей загружать из среды Web по протоколу HTTP любые аудио- или видеофайлы.

Рисунок A. Выбор типа файла для блокировки

Тип файла в ISA Server определяется его расширением (скажем, .mp3) и MIME-описанием (например, audio/mpeg). Можно указать тип файла на вкладке на экране A и, нажав кнопку Details, увидеть список файловых расширений, а также MIME-описаний, относящихся к данному типу контента. Кроме того, нажатием кнопки New можно создавать собственные типы контента.

Отметим, однако, что в случае указания типов файлов на вкладке Content Types какого-либо правила последнее применяется только к трафику HTTP. Это справедливо даже для тех случаев, когда на вкладке Protocols указывается, что правило применяется ко всему трафику. Чтобы заблокировать протоколы, отличные от HTTP, придется создавать дополнительные правила. Но и после этого вы не сможете блокировать загрузку с использованием отличных от HTTP протоколов по их расширениям или по типу MIME — эта функция предусмотрена только для протокола HTTP. Более того, если не приобрести дополнительный модуль от независимого поставщика, такой как разработанное фирмой Collective Software расширение ClearTunnel, вы не сможете ограничивать трафик по протоколу HTTP Secure (HTTPS), поскольку этот канал шифруется.

Далее, перейдем на вкладку Action. На этой вкладке (показанной на экране B) можно вводить указатель URL внутреннего Web-сервера, где размещается специализированная страница Denied Access, содержащая официальную политику приемлемого использования. Если не ввести указатель URL, заблокированные HTTP-запросы будут генерировать страницы с универсальными сообщениями об ошибках. Можно настроить оба правила (File_Blocker и Site_Blocker) так, чтобы при их выполнении в случаях, когда доступ блокируется, отображалась ваша специализированная страница.

Рисунок Б. Указание URL для демонстрации специализированной страницы с извещением об отказе в доступе

Наконец, для реализации еще более сложной фильтрации трафика по протоколу HTTP нужно открыть диалоговое окно Properties того правила, которое разрешает доступ в Internet (речь идет не о правилах блокировки), перейти на вкладку Protocols, нажать кнопку Filtering и выбрать пункт Configure HTTP. На экране появится набор вкладок для выполнения фильтрации по протоколу HTTP на уровне приложений. В данной статье я не могу рассмотреть все доступные варианты HTTP-фильтрации, но вы можете получить представление об имеющихся возможностях, если перейдете на вкладку Extensions, выберете пункт Block specified extensions и добавите к списку расширение .wmf. Это равнозначно использованию вкладки Content Types для блокировки нежелательных типов файлов. В данном случае блокируется тип файла изображений, связанный с уязвимым местом процессора рендеринга графики, о котором говорилось в бюллетене Microsoft Security Bulletin MS06-001-Vulnerability in Graphics Rendering Engine Could Allow Remote Code Execution за январь 2006 г. Нажмите кнопки ОК и Apply для сохранения изменений.

Листинг 1. ImportBlacklist.vbs


‘*************************************************************************************
‘ Script Name: ImportBlacklist.vbs
‘ Version: 1.2
‘ Author: Jason Fossen
‘Last Updated: 19.Jan.2006
‘ Purpose: Automatically update an ISA Server Domain Name Set with domains; for example,
‘ these could be domains of spammers, pornographers, hacking sites, etc.
‘ Arguments: First arg is name of Domain Name Set, in double-quotes if necessary. The
‘ second arg is the HTTP URL, local full path, or file name (if in same
‘ folder as script) of a text file containing the domain data. This file,
< ‘ if it contains comments, must use #-marks or semicolons to denote comments.
‘ Each line must be just a domain name, but if IP addresses are in the list, they
‘ will be ignored automatically. This script is compatible with the lists at:
‘ http://urlblacklist.com
‘ http://www.stearns.org/sa-blacklist/
‘ http://www.squidguard.org/blacklists/
‘ and with other similarly-formatted lists of domains. It also works if a
‘ listed domain begins or ends with a period or begins with «*.» as a wildcard.
‘ File with domains can use either Windows-style or UNIX-style newlines.
‘ Note: The fastest way to see that the Domain Name Set had been filled correctly
‘ is to close and open the ISA MMC console again, not by refreshing.
‘ Works on both ISA Standard and Enterprise.
‘ Legal: SCRIPT PROVIDED «AS IS» WITHOUT WARRANTIES OR GUARANTEES OF ANY KIND.
‘ USE AT YOUR OWN RISK. Test on non-production servers first.
‘*************************************************************************************
Option Explicit
On Error Resume Next
ReDim aDomainsArray(0) ‘Array of Domains to be added to the Domain Name Set.
Dim sDomainNameSetName ‘Name of Domain Name Set to be created and/or updated.
Dim bUseLocalDomainsFile ‘If true, use local file. If false, get domains from http URL.
Dim sDomainsFilePath ‘An HTTP URL or a local filesystem path to a file of domains.
Dim oFPC ‘See MakeIsaObjects()
Dim oIsaArray ‘See MakeIsaObjects()
Dim oFileSystem : Set oFileSystem = WScript.CreateObject(«Scripting.FileSystemObject»)
Call CatchAnyErrorsAndQuit(«Problems creating the FileSystemObject.»)
‘*************************************************************************************
‘ Main()
‘*************************************************************************************
Call ProcessCommandLineArguments()
Call CreateIsaObjects()
Call MakeArrayOfDomains()
Call CreateDomainNameSet()
Call EmptyTheDomainNameSet()
Call CreateNewDomains()
‘*************************************************************************************
‘ Procedures
‘*************************************************************************************
Sub ProcessCommandLineArguments()
On Error Resume Next

‘ First arg…

sDomainNameSetName = WScript.Arguments.Item(0)
Dim sArg : sArg = LCase(sDomainNameSetName)
If (WScript.Arguments.Count = 0) Or (WScript.Arguments.Count => 3) Or (sArg = «/?»)_
Or (sArg = «-?») Or (sArg = «/h») Or (sArg = «/help») Or (sArg = «—help») Then
Call ShowHelpAndQuit()
End If

‘ Second arg…

sDomainsFilePath = WScript.Arguments.Item(1)
If InStr(LCase(sDomainsFilePath), «http://») = 0 Then
bUseLocalDomainsFile = True ‘Use a local text file.
Else
bUseLocalDomainsFile = False ‘Use an http URL.
End If
On Error Goto 0
End Sub
Sub CreateIsaObjects()
‘This sub is just a placeholder for something to add later on…
Set oFPC = CreateObject(«FPC.Root»)
Set oIsaArray = oFPC.GetContainingArray
Call CatchAnyErrorsAndQuit(«Problems connecting to ISA Server or ISA Array.»)
End Sub
Sub MakeArrayOfDomains()
If bUseLocalDomainsFile Then
If Not ParseInputFile(sDomainsFilePath, aDomainsArray) Then
Err.Raise -1
Call CatchAnyErrorsAndQuit(«Problems reading the local domains file: « & sDomainsFilePath)
End If
Else ‘Get the domains file from the http URL…
Dim sUrlText : sUrlText = HttpGetText(sDomainsFilePath)
If InStr(sUrlText, «GET-Error!») 0 Then ‘ «GET-Error!» would be returned by HttpGetText() function,
not the web server.
Err.Raise -1
Call CatchAnyErrorsAndQuit(«Problems getting domains file from « & sUrlToDomainsFile)
End If

If oFileSystem.FileExists(«domains-downloaded-from-url.txt») Then
oFileSystem.DeleteFile «domains-downloaded-from-url.txt», True ‘Delete prior domains file, if it exists.
End If

If Not AppendToFile(sUrlText, «domains-downloaded-from-url.txt») Then
Err.Raise -1
Call CatchAnyErrorsAndQuit(«Problems writing to the domains-downloaded-from-url.txt file.»)
End If

If Not ParseInputFile(«domains-downloaded-from-url.txt», aDomainsArray) Then
Err.Raise -1
Call CatchAnyErrorsAndQuit(«Problems reading file: domains-downloaded-from-url.txt»)
End If
End If

End Sub

Sub CreateDomainNameSet()
On Error Resume Next
Dim cDomainNameSets ‘FPCDomainNameSets collection.
Dim oDomainNameSet ‘FPCDomainNameSet object.

‘Set oFPC = CreateObject(«FPC.Root»)
‘Set oIsaArray = oFPC.GetContainingArray
Set cDomainNameSets = oIsaArray.RuleElements.DomainNameSets

Set oDomainNameSet = cDomainNameSets.Add(sDomainNameSetName)

If Err.Number = -2147024713 Then
Err.Clear ‘Already exists, so ignore error.
Else
cDomainNameSets.Save
End If

Call CatchAnyErrorsAndQuit(«Problems recreating Domain Name Set named « & sDomainNameSetName)
On Error Goto 0
End Sub

Sub EmptyTheDomainNameSet()
‘Note: Clear the Domain Name Set instead of deleting it because it may be used in rules already.
Dim cDomainNameSets ‘FPCDomainNameSets collection.
Dim cDomainNameSet ‘FPCDomainNameSet collection.
Dim sDomain

‘Set oFPC = CreateObject(«FPC.Root»)
‘Set oIsaArray = oFPC.GetContainingArray
Set cDomainNameSet = oIsaArray.RuleElements.DomainNameSets.Item(sDomainNameSetName)

For Each sDomain In cDomainNameSet
cDomainNameSet.Remove(sDomain)
Next

cDomainNameSet.Save

Call CatchAnyErrorsAndQuit(«Problems emptying Domain Name Set named « & sDomainNameSetName)
End Sub

Sub CreateNewDomains()
On Error Resume Next
Dim cDomains ‘FPCURLSets collection.
Dim oDomain ‘FPCDomain object.
Dim cDomainNameSet ‘FPCDomainNameSet collection.
Dim cDomainNameSets ‘FPCDomainNameSets collection.
Dim sIPaddress, sMask, sDomain, sDomainName

Set cDomainNameSet = oIsaArray.RuleElements.DomainNameSets.Item(sDomainNameSetName)

For Each sDomain In aDomainsArray
If (Left(sDomain, 1) «#») And (Left(sDomain, 1) «;») And (Left(sDomain, 1) «<») And (Len(sDomain) 0) And Not IsIpAddress(sDomain) The
If Right(sDomain,1) = «.» Then sDomain = Left(sDomain, Len(sDomain) — 1) ‘Trim off a trailing period, if present
If Left(sDomain,2) «*.» Then sDomain = «*.» & sDomain ‘Prepend «*.» if not already there.
sDomain = Replace(sDomain, «..», «.») ‘Correct if first char was already a period.
cDomainNameSet.Add(sDomain)
If Err.Number = -2147024713 Then Err.Clear ‘Domain already added, so ignore error.
‘WScript.Echo sDomain & « was added.» ‘For debugging…
End If
Next

cDomainNameSet.Save

Call CatchAnyErrorsAndQuit(«Problems creating new domain objects in « & sDomainNameSetName)
On Error Goto 0
End Sub

Sub CatchAnyErrorsAndQuit(sMessage)
Dim oStdErr
If Err.Number 0 Then
Set oStdErr = WScript.StdErr ‘Write to standard error stream.
oStdErr.WriteLine vbCrLf
oStdErr.WriteLine «>>>>>> ERROR: « & sMessage
oStdErr.WriteLine «Error Number: « & Err.Number
oStdErr.WriteLine « Description: « & Err.Description
oStdErr.WriteLine «Error Source: « & Err.Source
oStdErr.WriteLine « Script Name: « & WScript.ScriptName
oStdErr.WriteLine vbCrLf
WScript.Quit Err.Number
End If
End Sub

Sub ShowHelpAndQuit()
Dim sUsage : sUsage = vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & «IMPORTBLACKLIST.VBS DomainNameSetName FilePath» & vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & «Creates or updates an ISA Server Domain Name Set (`DomainNameSet`)» & vbCrLf
sUsage = sUsage & «with the domains from a text file (`FilePath`) obtained from» & vbCrLf
sUsage = sUsage & «either an HTTP URL or a local filesystem path.» & vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & « DomainNameSet Name of Domain Name Set to be created or» & vbCrLf
sUsage = sUsage & « updated with domain entries. Will be» & vbCrLf
sUsage = sUsage & « created in the local ISA Server or» & vbCrLf
sUsage = sUsage & « current ISA Server Array.» & vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & « FilePath A full HTTP URL or local filesystem path» & vbCrLf
sUsage = sUsage & « to a text file containing domains. All» & vbCrLf
sUsage = sUsage & « comments must start with # or ;. Examples» & vbCrLf
sUsage = sUsage & « might be `filename.txt`, `c:\filename.txt`,» & vbCrLf
sUsage = sUsage & « or `http://www.fqdn.com/filename.asp`.» & vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & «Note that all domains defined in the Domain Name Set are deleted» & vbCrLf
sUsage = sUsage & «prior to importing the domains from the text file. If necessary,» & vbCrLf
sUsage = sUsage & «the Domain Name Set object will be created. Place double-quotes» & vbCrLf
sUsage = sUsage & «around the DomainNameSet and FilePath arguments if they contain» & vbCrLf
sUsage = sUsage & «any space characters. When providing an HTTP URL, the downloaded» & vbCrLf
sUsage = sUsage & «file will be saved as ‘domains-downloaded-from-url.txt` in the « & vbCrLf
sUsage = sUsage & «same folder as the script; it will be overwritten whenever a URL» & vbCrLf
sUsage = sUsage & «path is used again. Script must be run on the ISA Server itself.» & vbCrLf
sUsage = sUsage & vbCrLf
sUsage = sUsage & «SCRIPT PROVIDED «»AS IS»» AND WITHOUT WARRANTIES OR GUARANTEES OF» & vbCrLf
sUsage = sUsage & «ANY KIND. USE AT YOUR OWN RISK.» & vbCrLf
sUsage = sUsage & vbCrLf

WScript.Echo sUsage
WScript.Quit
End Sub

‘*************************************************************************************
‘ Functions
‘*************************************************************************************
Function IsIpAddress(sInput)
‘Regular expression would be more accurate, but slower…quick-n-dirty will do since
‘having a «*.dottedIPaddress» domain doesn’t break anything if an IP address sneaks by…

IsIpAddress = False

Dim sEnd
sInput = LCase(sInput)
sEnd = Right(sInput,1) ‘This will catch 98% of cases, so it’s faster than RegEx.
If (sEnd = «m») Or (sEnd = «u») Or (sEnd = «l») Or (sEnd = «v») Or (sEnd = «g»)_
Or (sEnd = «t») Or (sEnd = «z») Or (sEnd = «o») Or (sEnd = «e») Or (sEnd = «s»)_
Or (sEnd = «r») Or (sEnd = «n») Or (sEnd = «c») Or (sEnd = «k») Or (sEnd = «e») Then Exit Function

Dim aArray, x
aArray = Split(sInput,».»)
If UBound(aArray) 3 Then Exit Function

If Not (IsNumeric(aArray(0)) And IsNumeric(aArray(1)) And IsNumeric(aArray(2)) And IsNumeric(aArray(3))) Then Exit
Function

IsIpAddress = True
End Function

Function HttpGetText(sURL)
On Error Resume Next

If Not IsObject(oHTTP) Then Dim oHTTP : Set oHTTP = WScript.CreateObject(«Microsoft.XMLHTTP»)

oHTTP.Open «GET», sURL, False ‘False = Script waits until the full HTTP response is received.
oHTTP.Send ‘Send the HTTP command as defined with the Open method.

If Err.Number = 0 Then
HttpGetText = oHTTP.ResponseText
HttpGetText = Replace(HttpGetText, vbLf, vbCrLf) ‘Flip UNIX new lines to DOS, if necessary.
Else
HttpGetText = «GET-Error! Error Number: « & Err.Number
End If
End Function

Function ParseInputFile(ByVal sFile, ByRef aArray)
On Error Resume Next
Const ForReading = 1
Const OpenUsingDefault = -2
Dim sCurrentFolder, oFileSystem, oInputFile, i, iCurrentSize
Dim iPreserveCounter, oFile, oTextStream, iLineCount, sLine

‘Expand environmental variables, if any.
If InStr(sFile, «%») 0 Then
If Not IsObject(oWshShell) Then Set oWshShell = WScript.CreateObject(«WScript.Shell»)
sFile = oWshShell.ExpandEnvironmentStrings(sFile)
End If

‘Assume input file is in current folder if a full path is not given.
If InStr(sFile, «\») = 0 Then
sCurrentFolder = WScript.ScriptFullName
sCurrentFolder = Left(sCurrentFolder, InstrRev(sCurrentFolder, «\»))
sFile = sCurrentFolder & sFile
End If

‘Verify that file exists and is readable, return false if not.
If Not IsObject(oFileSystem) Then Set oFileSystem = WScript.CreateObject(«Scripting.FileSystemObject»)
Set oFile = oFileSystem.GetFile(sFile)
Set oTextStream = oFile.OpenAsTextStream(ForReading, OpenUsingDefault)
If Err.Number 0 Then
‘WScript.Echo «Problem opening « & sFile & « (« & Err.Description & «)»
ParseInputFile = False
Exit Function
End If

‘Count the number of lines in file, not including an empty line at the very end (if present).
iLineCount = 0
Do While Not oTextStream.AtEndOfStream
oTextStream.SkipLine
iLineCount = iLineCount + 1
Loop

‘ReDim the array to be equal to expected size of the input from file.
If iLineCount 0 Then
ReDim aArray(iLineCount — 1)
oTextStream.Close
Set oTextStream = Nothing
Else ‘The input file was empty!
ReDim aArray(0)
‘aArray(0) = «» ‘Assign default here if desired.
oTextStream.Close
Set oTextStream = Nothing
Set oFile = Nothing
Set oFileSystem = Nothing
If Err.Number = 0 Then
ParseInputFile = True
Else
ParseInputFile = False
End If
Exit Function
End If

‘Read each line of file into an element of the array, excluding blank lines.
Set oTextStream = oFile.OpenAsTextStream(ForReading, OpenUsingDefault)
i = 0
iPreserveCounter = 0
Do While Not oTextStream.AtEndOfStream
sLine = Trim(oTextStream.ReadLine) ‘Note the trimming here.
If Len(sLine) 0 Then
aArray(i) = sLine
i = i + 1
Else
iPreserveCounter = iPreserveCounter + 1 ‘Keep track of blank lines.
End If
Loop
oTextStream.Close
Set oTextStream = Nothing

‘If there were blank lines in the file, trim the array of empty elements.
If iPreserveCounter 0 Then
iCurrentSize = UBound(aArray)
ReDim Preserve aArray(iCurrentSize — iPreserveCounter)
End If

Set oFile = Nothing
Set oFileSystem = Nothing

If Err.Number = 0 Then
ParseInputFile = True
Else
ParseInputFile = False
End If
End Function

Function AppendToFile(sData, sFile)
On Error Resume Next

Const ForAppending = 8 ‘Request NTFS appending permission.
Const ForOverWriting = 2 ‘Request NTFS writing permission.
Const ForReading = 1 ‘Request NTFS read permission.
Const OpenAsASCII = 0 ‘ASCII text format.
Const OpenAsUnicode = -1 ‘Unicode text format.
Const OpenUsingDefault = -2 ‘ASCII is default for FAT32, Unicode default for NTFS.

Dim sCurrentFolder, oTextStream

‘Create FileSystemObject if it doesn’t exist yet.
If Not IsObject(oFileSystem) Then Set oFileSystem = WScript.CreateObject(«Scripting.FileSystemObject»)

‘Expand any environmental variables to their full paths.
If InStr(sFile, «%») 0 Then If Not IsObject(oWshShell) Then Set oWshShell = WScript.CreateObject(«WScript.Shell»)
sFile = oWshShell.ExpandEnvironmentStrings(sFile)
End If

‘Use current folder of script for output file path, if not path is given.
If InStr(sFile, «\») = 0 Then
sCurrentFolder = WScript.ScriptFullName
sCurrentFolder = Left(sCurrentFolder, InstrRev(sCurrentFolder, «\»))
sFile = sCurrentFolder & sFile
End If

‘Get output file if it exists, or create one if it doesn’t.
If Not oFileSystem.FileExists(sFile) Then
Set oTextStream = oFileSystem.CreateTextFile(sFile)
Else
Set oFile = oFileSystem.GetFile(sFile)
Set oTextStream = oFile.OpenAsTextStream(ForAppending, OpenUsingDefault)
End If

‘Must write data to a new line, so check the column number first.
If oTextStream.Column = 1 Then
oTextStream.Write(sData)
Else
oTextStream.WriteBlankLines(1)
oTextStream.Write(sData)
End If

oTextStream.Close

If Err.Number = 0 Then
AppendToFile = True
Else
AppendToFile = False
End If
End Function

‘END OF SCRIPT************************************************************************


Листинг 2. ScheduledUpdate.bat


@ECHO OFF
REM ********************************************************
REM Сценарий: ScheduledUpdate.bat
REM Версия: 1.0 (18 января 2006 г.)
REM Автор: Джейсон Фоссен
REM Назначение: Данный сценарий предназначен для загрузки
REM «черного списка» с сайта urlblacklist.com и импорта содержащегося в нем списка porn
REM в набор доменных имен ISA Server
REM с именем Bad-Sites с помощью сценария
REM ImportBlacklist.vbs. Скорее всего, в сценарий придется внести изменения; он представляет собой прежде всего иллюстрацию того, как решается задача, поэтому
REM в нем не предусмотрены операции по проверке ошибок,
REM регистрации или по извещению администратора.
REM
REM Примечание. Загруженный «черный список» — это короткий демонстрационный список,
REM а не большой коммерческий список,
REM за получение которого следует вносить плату.
REM
REM Сценарий предоставляется «как есть», без поручительств или
REM гарантий. ИСПОЛЬЗУЙТЕ ЕГО НА СВОЙ СТРАХ И РИСК.
REM ********************************************************
REM Загрузите сжатый по технологии gzip файл «черного списка» tar:
wget.exe -q -t 2 -w 5 -O bigblacklist.tar.gz «http://urlblacklist.com/cgi-bin/commercialdownload.pl?
type=download&file=smalltestlist»
REM Распакуйте этот файл:
gunzip.exe -f bigblacklist.tar.gz
REM Перенесите отдельные файлы «черного списка» в подкаталог (/blacklists) локальной папки tar.exe -xf bigblacklist.tar
REM Импортируйте домены с порнографическим контентом в набор Bad-Sites:
start /belownormal cscript.exe ImportBlacklist.vbs Bad-Sites .\blacklists\porn\domains


Журнал «Windows IT Pro», Издательство «Открытые системы» (http://www.osp.ru/)