Автоматическая настройка прокси через DHCP (WPAD)

Прокси для доступа в интернет на базе SQUID всем хорошо, кроме того, что на каждом клиенте приходится прописывать его настройки. В какой-то момент было решено сделать все это централизованно.

Для этого была использована технология Web Proxy Autodiscovery Protocol (сокращенно WPAD).

Сначала настраиваем (если ранее не был настроен) DHCP сервер. И настраиваем Proxy сервер (SQUID)
После этого в файле /etc/dhcp/dhcpd.conf дополним конфигурацию DHCP сервера и зоны.

Для начала в основную часть конфигурации (основная часть идет до строчки начинающейся на subnet) добавим описание параметра wpad

option wpad code 252 = text;

И в описании области добавим параметр

option wpad "http://192.168.xxx.xxx/wpad.dat";

который отвечает за то, откуда будет браться файл конфигурации.
(http://192.168.xxx.xxx/wpad.dat -это адрес файла конфигурации прокси)

В итоге описание зоны будет выглядеть примерно так:

subnet 192.168.xxx.0 netmask 255.255.255.0 {
range 192.168.xxx.xxx 192.168.xxx.xxx;
option routers 192.168.xxx.xxx;
option broadcast-address 192.168.xxx.255;
option wpad "http://192.168.xxx.xxx/wpad.dat";
}

Теперь остается только создать файл конфигурации и опубликовать его по протоколу HTTP.

для этого создадим простейший файл wpad.dat и запишем в него параметры Proxy сервера

function FindProxyForURL(url, host)
{
return "PROXY 192.168.xxx.xxx:3128;";
}

где 192.168.xxx.xxx:3128 это адрес и порт Proxy сервера.

Далее разместим wpad.dat на веб-сервере и перезапустим DHCP командой

sudo /etc/init.d/isc-dhcp-server restart

С этого момента все свежеподключившиеся клиенты будут получать конфигурацию прокси через DHCP.

В дальнейшем можно провести более тонкую настройку проксирования в файле wpad.dat.

Немного опишу базовый синтаксис:
//Функция использования прокси
function FindProxyForURL(url, host)
{
// если текстовое имя хоста без точек, то соединяемся с ним напрямую (полезно для локальных адресов)
if (isPlainHostName(host)) {return "DIRECT";}
//если в URL содержится blackdiver.net то соединяемся напрямую
if (shExpMatch (url, "*blackdiver.net*")) {return "DIRECT";}
//если хост в сети 192.168.xxx.0 или в сети 127.0.0.0 то тоже подключаемся напрямую
if (isInNet (host, "192.168.xxx.0", "255.255.255.0") || isInNet (host, "127.0.0.0", "255.255.255.0")) {return "DIRECT";}
//если ни одно условие не выполнилось - возвращаем имя прокси
return "PROXY 192.168.xxx.xxx:3128; DIRECT";
}

Так же можно построить обратную конфигурацию. Если адрес такой-то, то используем такой прокси, а в остальных случаях соединяемся напрямую.

Вот пример, когда yandex и mail.ru работают через прокси, а остальные — напрямую:
function FindProxyForURL(url, host)
{
if (shExpMatch (url, "*yandex.ru*") || shExpMatch (url, "*mail.ru*")) {return "PROXY 192.168.xxx.xxx:3128; DIRECT";}
return "DIRECT";
}

Или использовать несколько прокси. Тут уже все зависит от фантазии и потребностей, ведь этот файл это всего-лишь javascript.

Доступные функции:

isResolvable(host) — запрос имени хоста (прверка существования) на DNS-сервере
пример:
if (isResolvable(host))

dnsResolve(host) — запрос DNS-сервера для перевода имени в IP
пример:
if (dnsResolve(host) == "xxx.xxx.xxx.xxx")

myIpAddress() — возвращает IP-адрес (состоящий из целых чисел и точек) узла, на котором запущен браузер
пример:
if (myIpAddress() == "xxx.xxx.xxx.xxx")

isPlainHostName(host) — проверяет, содержатся ли точки в имени узла. Если точка найдена, то возвращается значение false; если нет, возвращается значение true
пример:
if (isPlainHostName(host))

dnsDomainLevels(host) — возвращает целое число, равное количеству точек в имени узла
пример:
if (dnsDomainLevels(host) > 0)

dnsDomainIs(host,».company.com») — возвращает значение true, если домен из имени узла совпадает с заданным доменом
пример:
if (isPlainHostName(host) || dnsDomainIs(host, ".company.com"))

localHostOrDomainIs(host, «www.company.com») — возвращает значение true, если домен из имени узла совпадает с заданным доменом. Выполняется только для URL-адресов, относящихся к локальному домену.
пример:
if (!localHostOrDomainIs(host, "www.company.com"))

shExpMatch(str, shexp) — возвращает значение true, если str соответствует шаблону оболочки shexp
пример:
if (shExpMatch(host, "*.com"))

isInNet(host, pattern, mask) — возвращает значение true, если IP-адрес узла соответствует указанному шаблону (например, 127.0.0.0). mask указывает, какую часть IP-адреса следует сопоставлять (255=сопоставлять, 0=игнорировать)
пример:
if (isInNet(host, "999.99.9.9", "255.0.255.0"))

url.substring(0, ) извлекает указанное количество знаков с начала строки
пример:
url.substring(0, 4)

weekdayRange( day1 [, day2] [,»GMT»] ) — возвращает значение true, если текущее время системы попадает в диапазон, заданный с использованием параметров и (необязательный). Необязательный параметр GMT указывает, что задано не местное время, а время по Гринвичу.
пример:
if(weekdayRange("WED", "SAT", "GMT"))

dateRange(day1 [,month1] [,year1] [,day2] [,month2] [,year2] [,gmt] )
day — число дня месяца между 1 и 31
month — строка: JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
year — полный (четырёхзначный) год
gmt — зона «GMT» (по Гринвичу)
примеры:
dateRange(1) //true если сегодня первое число, используется локальное время.
dateRange(1, "GMT") //true сегодня первое число, используется время по гринвичу.
dateRange(1, 15) //true если сегодня число в диапазоне с 1 по 15-е.
dateRange(24, "DEC") //true каждое 24-е декабря.
dateRange(24, "DEC", 1995) //true если сегодня 24е-е декабря 1995 года.
dateRange("JAN", "MAR") //true с января по март
dateRange(1, "JUN", 15, "AUG") //true с 1 июня по 15-е августа (включительно).
dateRange(1, "JUN", 15, 1995, "AUG", 1995) //true с 1-го июня 1995-го года по 15-е июня 1995 года.
dateRange("OCT", 1995, "MAR", 1996) //true с октября 1995 по март 1996 (включительно).
dateRange(1995) //true в течении 1995 года.
dateRange(1995, 1997) //true с 1995 до 1997.

timeRange(hour1 [,min1] [,sec1] [,hour2] [,min2] [,sec2] [,gmt] )
hour — число часа от 0 до 23
min — число минут от 0 до 59
sec — число секунд от 0 до 59
gmt — зона «GMT» (по Гринвичу)
примеры:
timerange(12) //true до 13:00.
timerange(12, 13) //true с 12:00 до 13:00.
timerange(12, "GMT") //true с начала для до 13:00 по Гринвичу.
timerange(9, 17) //true from 9am to 5pm.
timerange(8, 30, 17, 00) //true с 8:30 to 17:00.
timerange(0, 0, 0, 0, 0, 30) //true с полночи и до 00:00:30 секунд.

Так же еще поддерживаются переменные:
примеры:
ip_host = dnsResolve(host);
ip_localnet = "192.168.0.0";
ip_localhost = "127.0.0.1";
proxy_general = "PROXY gwhost.my:3128";
proxy_local = "PROXY localhost:3128";

Заказать создание и поддержку безопасной IT-инфраструктуры любой сложности

Быть уверенным в своей IT-инфраструктуре — это быть уверенным в завтрашнем дне.

Для того, чтобы сделать заказ:

Заполните форму обратной связи и мы обязательно с вам свяжемся:
Форма обратной связи
Позвоните нам по телефону:
+7(909)952-44-33
Напишите нам на электронную почту:
order@blackdiver.net
Напишите нам в Telegram:
Telegram
Другие способы связи Вы сможете найти в разделе Контакты.