Хорошо спроектированная система обладает следующими признаками:
- Обладает максимальным охватом всех возможных применений в рамках её предназначения
- Управляется централизованно и имеет автоматические проверки и процедуры для минимизации влияния т. н. человеческого фактора
- Имеет лаконичное и хорошо читаемое описание
- Не требует большого количества исключений и их ручной настройки
- Рационально использует ресурсы
Может быть, что-то ещё, но направление мысли, думаю, понятно. Применительно, предположим, к настройке подключения к интернету пользователей в организации — если централизованно вроде бы что-то и настроено, но при этом постоянно нужно что-то делать на пользовательских машинах, прописывать маршруты, ставить-снимать галки в свойствах браузера, делать резервирования в DHCP, разрешать прямой выход в интернет в обход прокси-сервера, просить сетевиков написать на шлюзе очередное правило для одной машины, при этом все эти 100500 изменений нигде не записаны и делаются бессистемно от случая к случаю; если в организации существуют дополнительные шлюзы, где всё открыто, потому что «надо работать и некогда разбираться» — это всё наводит на мысли, что система спроектирована как-то неправильно.
К сожалению, мало кто занимается осмыслением какой-либо системы в целом, особенно той, которая уже давно работает — люди адаптивны и привыкают практически ко всему, им лень что-то менять, да и опасно (тут прилагается большой список офисной мудрости, предписывающей сидеть тихо, максимально не брать на себя никакой ответственности и не выказывать инициатив, чтобы иметь долговременный и стабильный кусок хлеба). Как-то работает — и ладно, сейчас ещё одну проволочку прикрутим, а сбоку пластилинчика ещё налепим, и хорошо. Тем более, что всегда так настраивали и работали, в чём проблема-то?
Предлагая что-то улучшить, не стоит ждать поддержки. Никто не увлечётся и не будет содействовать, скорее, наоборот. Тебе всегда предложат всё придумать и сделать самому, а на вопросы по делу и высказываемые сомнения в существующем положении вещей ещё будут обижаться — что же, мы тут годами работаем, а ты намекаешь, что тут всё через одно место? Ты что, самый умный?
Сопротивление изменениям, и особенно автоматизации, связано также и с тем, что люди очень боятся стать ненужными. Условно говоря, раньше руками сто компьютеров за день настраивали с пупочным надрывом, а теперь это делается автоматически в тысячу раз быстрее и точнее, а мы теперь становимся не нужны и нас уволят, так зачем эта автоматизация? Пусть руками, зато будет что написать в список выполненных работ, и получить премию за ударный труд.
Тем не менее, необходимо заниматься повышением своего профессионального уровня и на этой базе улучшать положение вещей вокруг себя, как ни горько порой бывает думать обо всём вышенаписанном. В очередной раз наблюдая борения с тем или иным софтом на компьютерах пользователей, который почему-то не работал через прокси-сервер, или работал, но тогда не работало что-то другое, захотелось попробовать как-то улучшить эту ситуацию, хотя я ничего не знаю про автонастройку клиентов и что куда должно ходить. С другой стороны, месяц назад я ничего не знал про Squid, а сейчас он настроен и успешно работает под тестовой нагрузкой.
Выяснилось, что за автонастройку клиентов отвечает файл wpad.dat
следующего содержания:
function FindProxyForURL(url, host)
{
$NewProxy = "PROXY proxy.domain.ru:3128";
if (isPlainHostName(host)) {return "DIRECT";}
if (isInNet(host, "10.1.0.0", "255.255.0.0")) {return "DIRECT";}
if (dnsDomainIs(host,"localhost")) {return "DIRECT";}
if (dnsDomainIs(host,"127.0.0.1")) {return "DIRECT";}
if (dnsDomainIs(host,"domain.ru")) {return "DIRECT";}
if (dnsDomainIs(host,"support.domain.ru")) {return "DIRECT";}
if (dnsDomainIs(host,"test-sps.domain.ru")) {return "DIRECT";}
if (dnsDomainIs(host,"portal.domain.ru")) {return "DIRECT";}
if (dnsDomainIs(host,"portal.domain.ru")) {return "DIRECT";}
if (shExpMatch(url, "http:*")
|| shExpMatch(url, "https:*")
|| shExpMatch(url, "ftp:*")
|| shExpMatch(url, "gopher:*"))
return $NewProxy;
return $NewProxy;
}
Не принимая в расчёт общую неструктурированность файла, дубль записи и явную копипасту раздела с url (кто вообще сегодня знает про gopher?), возникает вопрос — а почему просто не пустить напрямую весь локальный .domain.ru? «А потому что есть ресурсы в domain.ru, опубликованные на внешних IP-адресах», — ответили мне. Дело в том, что и внешний, и внутренний домен названы одинаково. Что же делать? Полез в интернет и через некоторое время обнаружил отличное описание файла конфигурации с примером, как раз подходящим в моей ситуации:
function FindProxyForURL(url, host) {
if (
(isPlainHostName(host) || dnsDomainIs(host, ".mozilla.org")) &&
!localHostOrDomainIs(host, "www.mozilla.org") &&
!localHostOrDoaminIs(host, "merchant.mozilla.org")
) {
return "DIRECT";
} else {
return "PROXY w3proxy.mozilla.org:8080; DIRECT";
}
}
Красивая логика — на одну ступенечку сложнее, и уже такая мощь! Пускаем напрямую имена без указания домена или весь домен, но не конкретные имена в этом же домене. Больше того, можно указывать цепочку прокси-серверов — в данном примере, если не будет доступен w3proxy.mozilla.org, то идти напрямую.
Так, логика ясна. И сразу напрашивается решение эти опубликованные вовне ресурсы локального домена собирать из DNS автоматически — они ведь могут добавляться туда — и на этой основе формировать файл автонастройки. Тут уже приходит на помощь любимый Powershell:
$domainRecs = Get-DnsServerResourceRecord -ZoneName "domain.ru" -computerName "srv-dc3" |select hostname,recordtype,@{n='IPAddr';e={$_.RecordData.ipv4address.IPAddressToString}},@{n='Alias';e={$_.RecordData.hostnamealias -replace "\.domain\.ru\."}}
$domainARecsExt = $domainRecs |? {$_.IPAddr -match "^186" -and $_.recordtype -eq "A"}
$domainCnameRecsExt = foreach ($aRec in $domainARecsExt.hostname) {
$domainRecs |? {$_.recordtype -eq "CNAME" -and $_.alias -eq "$aRec"}
}
$domainAllExtRecs = ($domainARecsExt + $domainCnameRecsExt).hostname -replace "$",".domain.ru" |sort
$pac1 = "function FindProxyForURL(url, host) {
if (
(isPlainHostName(host) ||
dnsDomainIs(host, `".domain.ru`") ||
isInNet(host, `"10.0.0.0`", `"255.0.0.0`") ||
isInNet(host, `"127.0.0.0`", `"255.0.0.0`") ||
localHostOrDomainIs(host, `"localhost`")) `&`&
"
$total = $domainAllExtRecs.count
$C = 1
$pac2 = $domainAllExtRecs |% {
if ($c -lt $total) {
" !localHostOrDomainIs(host, `"$_`") `&`&"
}
else {
" !localHostOrDomainIs(host, `"$_`")"
}
$c++
}
$pac3 = "
) {
return `"DIRECT`";
} else {
return `"PROXY proxy.domain.ru:3128`";
}
}
"
$pac1 + ($pac2 -join "`n") + $pac3 |Out-File ~\Documents\proxy.pac -Encoding default
По желанию можно прикрутить сверку и оповещение на почту, если что-то убрали или добавили в DNS (в примере адреса начинаются на 186). Вот итоговый файл:
function FindProxyForURL(url, host) {
if (
(isPlainHostName(host) ||
dnsDomainIs(host, ".domain.ru") ||
isInNet(host, "10.0.0.0", "255.0.0.0") ||
isInNet(host, "127.0.0.0", "255.0.0.0") ||
localHostOrDomainIs(host, "localhost")) &&
!localHostOrDomainIs(host, "8mar.domain.ru") &&
!localHostOrDomainIs(host, "wolf.domain.ru") &&
!localHostOrDomainIs(host, "wolf1.domain.ru") &&
!localHostOrDomainIs(host, "wolf3.domain.ru") &&
!localHostOrDomainIs(host, "wolfapi.domain.ru") &&
!localHostOrDomainIs(host, "docs.domain.ru") &&
!localHostOrDomainIs(host, "old.domain.ru") &&
!localHostOrDomainIs(host, "xonix.domain.ru") &&
!localHostOrDomainIs(host, "services.domain.ru") &&
!localHostOrDomainIs(host, "test.xonix.domain.ru") &&
!localHostOrDomainIs(host, "test.services.domain.ru") &&
!localHostOrDomainIs(host, "web.domain.ru") &&
!localHostOrDomainIs(host, "www.8mar.domain.ru") &&
!localHostOrDomainIs(host, "www.docs.domain.ru") &&
!localHostOrDomainIs(host, "www.domain.ru") &&
!localHostOrDomainIs(host, "www.xonix.domain.ru") &&
!localHostOrDomainIs(host, "www.services.domain.ru")
) {
return "DIRECT";
} else {
return "PROXY proxy.domain.ru:3128";
}
}
По-моему, очень красиво и чётко. Получается, в этом файле описываются локальные ресурсы — имена машин, указанные без домена, сеть, сам домен и localhost. Исключения из локального домена и всё остальное идёт через прокси-сервер, где уже есть правила доступа и списки запрещённых и разрешённых портов и ресурсов. Всё настраивается централизованно, и не надо ковыряться в локальных настройках пользовательских машин.
А теперь уже можно заняться другими интересными вещами — отрезать назойливую телеметрию, засоряющую access.log, настраивать кэширование для того, чтобы каждый компьютер не лез в интернет за обновлением Google Chrome, а получал его с прокси-сервера, и так далее.