FreeBSD 9.x — SQUID 3.2.x (режим transparent proxy для IPFW)

Ну задолбала ента реклама в интернет — пространстве! Уже стала редкостью возможность читать информацию не окруженную огромным количеством всякой рекламы. Ну ладно бы она еще приличная была…., ну хорошо, согласен даже на не приличную…., ну хотя бы на рекламу, а не картинку идиотского содержания, ведущую на ресурс с еще более дебильным контентом… Я конечно понимаю, что многие живут за счет рекламы…., но пусть это будет приличная реклама. И вообще, порой реклама, обвешивающая страницу, загружается гораздо дольше чем сам полезный контент. Да и от всякой похабщины неплохо избавиться. Всего этого можно добиться используя proxy-сервер для доступа к интернету. Будем использовать одно из самых известных решений для unix систем — SQUID.  Причем использовать его будем в режиме transparent rpoxy (т.н. режим прозрачного проксирования). Плюсом выше указанного режима является то, что для работы с proxy-сервером никаких настроек  на клиентском оборудовании делать не нужно (что весьма удобно): все клиенты локальной сети получают доступ к интернету стандартным способом, даже не подозревая что работают через проки-сервер (именно по этой причине режим и называется «прозрачным»). Кроме того, не все (особенно мобильные) устройства и программы могут (имеют настройки) для работы через proxy-сервер, и это еще один «плюс» в пользу «прозрачного» режима проксирования. Есть, конечно, и минус — отсутствует возможность авторизации, но лично мне дома это не критично (учет ведется по ip-адресам), а там где это нужно (например, в крупных организациях) есть специально обученный человек и используется интеграция с AD (да и зоопарк своих мобильных устройств к рабочей сети подключать не позволяют).

Итак, начинаем бой с асоциальным контентом! Мы уже имеем полностью настроенный интернет-шлюз (а где же еще вы собираетесь использовать proxy-сервер SQUID?) с работающими DNS и DHCP службами. В качестве firewall-a используется IPFW, NAT так же реализован встроенными в ядро средствами. Перед непосредственной установкой SQUID необходимо сделать некоторые проверки. В частности, для организации работы  SQUID в режиме «прозрачного» проксирования совместно с firewall-ом IPFW ядро системы FreeBSD должно «уметь» перенаправлять пакеты. Именно ядро, поскольку firewall IPFW так же встроен в ядро, и пакеты будут перенаправляться ядром системы. Проверяем возможность перенаправления пакетов путем анализа лога загрузки:

root@testrouter:/usr/home/routeuser # grep forwarding /var/run/dmesg.boot

результат таков:

ipfw2 (+ipv6) initialized, divert loadable, nat loadable, rule-based forwarding disabled, default to deny, logging disabled

Явно видно, что перенаправление пакетов (rule-based forwarding) не активно (что не удивительно, так как по-умолчанию ядро скомпилировано без оной возможности). Надо это исправить, а именно, перекомпилировать ядро с опцией «IPFIREWALL_FORWARD«. Хотя в одной из предыдущих статей подробно описывался весь процесс пересборки ядра, опишем сей процесс и здесь (благо это не долго).  Для начала определим систему, на которой наш интернет-шлюз работает:

root@testrouter:/usr/home/routeuser # uname -mv

в результате получаем следующее информационное сообщение:

FreeBSD 9.1-RELEASE #0: Sun Mar 10 17:17:28 MSK 2013     [email protected]:/usr/obj/usr/src/sys/ROUTER  i386

из которого узнаем, что платформа нашей системы i386, и используется ядро ROUTER. Для начала скопируем конфигурационный файл текущего ядра:

root@testrouter:/usr/home/routeuser # cd /sys/i386/conf/ && cp ROUTER SQUID

нетрудно догадаться, конфигурационный файл нового ядра называется у нас SQUID (но Вы можете назвать его по-своему). Еще напомню, что наша система работает на платформе i386, и, если ваша платформа отличается, необходимо скорректировать выше указанную команду с учетом используемой платформы. Далее в конфигурационный файл /sys/i386/conf/SQUID добавляем следующую строку:

options         IPFIREWALL_FORWARD

затем запускаем компиляцию нового ядра:

root@testrouter:/sys/i386/conf # cd /usr/src && make buildkernel KERNCONF=SQUID

скорость данного процесса очень зависит от производительности «железа», так что чайку с плюшками попить успеете…

После компиляции устанавливаем новое ядро:

root@testrouter:/usr/src # cd /usr/src && make installkernel KERNCONF=SQUID

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

root@testrouter:/usr/src reboot

Смотрим информацию о нашей системе:

root@testrouter:/usr/home/routeuser # uname -mv 

и по результату:

FreeBSD 9.1-RELEASE #0: Sun Mar 10 17:17:28 MSK 2013     [email protected]:/usr/obj/usr/src/sys/SQUID  i386

приходим к мысли, что новое ядро SQUID установлено. Теперь проверим возможность перенаправления пакетов ядром системы:

root@testrouter:/usr/home/routeuser # grep forwarding /var/run/dmesg.boot

результат таков:

ipfw2 (+ipv6) initialized, divert enabled, nat enabled, rule-based forwarding enabled, default to deny, logging disabled

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

В портах у нас несколько версий SQUID, сейчас выясним каких. Сначала переходим в нужный каталог:

root@testrouter:/usr/home/routeuser # cd /usr/ports/www

 затем ищем все что относиться к SQUID-у:

root@testrouter:/usr/ports/www # echo *squid*

вот что нашлось:

lightsquid squid squid31 squid32 squid_radius_auth squidclamav squidguard squidpurge squidstats squidview

 Как видно, последняя версия, доступная в портах — 3.2, ее и будем ставить. Переходим в нужный каталог порта:

root@testrouter:/usr/ports/www # cd ./squid32

смотрим список необходимого:

root@testrouter:/usr/ports/www/squid32 # make all-depends-list

 и Perl лишь необходим…..:

/usr/ports/lang/perl5.14

 Конфигурируем установку:

root@testrouter:/usr/ports/www/squid32 # make config-recursive

параметры установки следующие:

1-600x300

2-600x3003-600x300

4-600x300

Самое главное — отметить опцию «SQUID_IPFW«, которая и компилирует SQUID для работы с IPFW в режиме «transparent proxy»!!! Так же я отметил опцию «SQUID_ICAP» — это может понадобиться для работы с антивирусными программами, а так же опцию «SQUID_DELAY_POOLS» — дабы иметь возможность гибко шейпить трафик. Желающие могут отметить опцию «SQUID_LARGEFILE» для возможности работы с кешем и файлом логов размером более 2Гб. Скачиваем все необходимое:

root@testrouter:/usr/ports/www/squid32 # make fetch-recursive

На всякий случай привожу лог загрузки:

===> Fetching all distfiles for squid-3.2.8 and dependencies
===> License GPLv2 accepted by the user
===> Found saved configuration for squid-3.2.8
=> squid-3.2.8.tar.bz2 doesn’t seem to exist in /usr/ports/distfiles/squid3.2.
=> Attempting to fetch ftp://ftp.squid-cache.org/pub/squid/squid-3.2.8.tar.bz2
squid-3.2.8.tar.bz2 100% of 2828 kB 182 kBps 00m00s
===> License ART10 GPLv1 accepted by the user
===> Found saved configuration for perl-5.14.2_2
=> perl-5.14.2.tar.bz2 doesn’t seem to exist in /usr/ports/distfiles/perl.
=> Attempting to fetch ftp://ftp.cpan.org/pub/CPAN/modules/by-module/../../src/perl-5.14.2.tar.bz2
perl-5.14.2.tar.bz2 100% of 12 MB 212 kBps 00m00s
=> BSDPAN-20111107.tar.bz2 doesn’t seem to exist in /usr/ports/distfiles/perl.
=> Attempting to fetch http://ftp.FreeBSD.org/pub/FreeBSD/ports/local-distfiles/skv/BSDPAN-20111107.tar.bz2
BSDPAN-20111107.tar.bz2 100% of 8448 B 127 kBps

после чего запускаем установку:

root@testrouter:/usr/ports/www/squid32 # make install clean

которая займет определенное время (надо же ж целый Perl скомпилировать…, да и SQUID сам по себе не мал…). После установки обновим пути поиска:

root@testrouter:/usr/ports/www/squid32 # rehash

Теперь приступим к конфигурации SQUID-а. Открываем для редактирования файл /usr/local/etc/squid/squid.conf (я использую редактор nano, поскольку он корректно работает с кириллицей в кодировке UTF-8):

root@testrouter:/usr/ports/www/squid32 # cd /usr/local/etc/squid/ && nano squid.conf

и наполняем его следующим содержимым:

visible_hostname squid.testrouter.testnet # локальное имя нашего сервера

acl localnet src 172.16.0.0/12 # наша локальная сеть 

acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT

# Напрямую с сервера доступ имеет только менеджер кэша
http_access allow localhost manager
http_access deny manager 

# запрещаем доступ к несохраненным портам
http_access deny !Safe_ports 

# Запрещаем доступ к не SSL портам
http_access deny CONNECT !SSL_ports

# в целях безопасности запрещаем http доступ
# к внутренним ресурсам сервера
http_access deny to_localhost

# Разрешаем доступ с нашей локальной сети
http_access allow localnet

# Разрешаем доступ внутри сервера
http_access allow localhost

# запрещаем все остальное
http_access deny all 

# Наш прокси «слушает» порт 3128 внутреннего локального адреса
# опция intercept указывает что трафик перенаправлен брандмауэром —
# так называемый «прозрачный» (transparent) режим
http_port 127.0.0.1:3128 intercept

# Отключим кэширование
cache deny all

# Паттерны обновления данных
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320

Проверяем конфигурационный файл squid.conf:

root@testrouter:/usr/local/etc/squid # squid -k parse /usr/local/etc/squid/squid.conf 

результат проверки таков:

2013/03/10 20:05:18| Startup: Initializing Authentication Schemes …
2013/03/10 20:05:18| Startup: Initialized Authentication Scheme ‘basic’
2013/03/10 20:05:18| Startup: Initialized Authentication Scheme ‘digest’
2013/03/10 20:05:18| Startup: Initialized Authentication Scheme ‘negotiate’
2013/03/10 20:05:18| Startup: Initialized Authentication Scheme ‘ntlm’
2013/03/10 20:05:18| Startup: Initialized Authentication.
2013/03/10 20:05:18| Processing Configuration File: /usr/local/etc/squid/squid.conf (depth 0)
2013/03/10 20:05:18| Processing: visible_hostname squid.testrouter.testnet
2013/03/10 20:05:18| Processing: acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
2013/03/10 20:05:18| Processing: acl SSL_ports port 443
2013/03/10 20:05:18| Processing: acl Safe_ports port 80 # http
2013/03/10 20:05:18| Processing: acl Safe_ports port 21 # ftp
2013/03/10 20:05:18| Processing: acl Safe_ports port 443 # https
2013/03/10 20:05:18| Processing: acl Safe_ports port 70 # gopher
2013/03/10 20:05:18| Processing: acl Safe_ports port 210 # wais
2013/03/10 20:05:18| Processing: acl Safe_ports port 1025-65535 # unregistered ports
2013/03/10 20:05:18| Processing: acl Safe_ports port 280 # http-mgmt
2013/03/10 20:05:18| Processing: acl Safe_ports port 488 # gss-http
2013/03/10 20:05:18| Processing: acl Safe_ports port 591 # filemaker
2013/03/10 20:05:18| Processing: acl Safe_ports port 777 # multiling http
2013/03/10 20:05:18| Processing: acl CONNECT method CONNECT
2013/03/10 20:05:18| Processing: http_access allow localhost manager
2013/03/10 20:05:18| Processing: http_access deny manager
2013/03/10 20:05:18| Processing: http_access deny !Safe_ports
2013/03/10 20:05:18| Processing: http_access deny CONNECT !SSL_ports
2013/03/10 20:05:18| Processing: http_access deny to_localhost
2013/03/10 20:05:18| Processing: http_access allow localnet
2013/03/10 20:05:18| Processing: http_access allow localhost
2013/03/10 20:05:18| Processing: http_access deny all
2013/03/10 20:05:18| Processing: http_port 127.0.0.1:3128 intercept
2013/03/10 20:05:18| Starting Authentication on port 127.0.0.1:3128
2013/03/10 20:05:18| Disabling Authentication on port 127.0.0.1:3128 (interception enabled)
2013/03/10 20:05:18| Disabling IPv6 on port 127.0.0.1:3128 (interception enabled)
2013/03/10 20:05:18| Processing: cache deny all
2013/03/10 20:05:18| Processing: refresh_pattern ^ftp: 1440 20% 10080
2013/03/10 20:05:18| Processing: refresh_pattern ^gopher: 1440 0% 1440
2013/03/10 20:05:18| Processing: refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
2013/03/10 20:05:18| Processing: refresh_pattern . 0 20% 4320

Как видим, ошибок и предупреждений нет. Для автоматического запуска Squid в файл /etc/rc.conf добавляем следующую строку:

squid_enable=»YES»

и можно пробовать запустить SQUID:

root@testrouter:/usr/local/etc/squid # squid start

даже если в консоли ошибок не вывелось, проверяем, запустился ли SQUID:

root@testrouter:/usr/local/etc/squid # ps -ax | grep squid

у меня результат таков:

61615 ?? Is 0:00,00 squid start
61617 ?? S 0:00,11 (squid-1) start (squid)
61618 ?? I 0:00,01 (logfile-daemon) /var/log/squid/access.log (log_file_daemon)
61632 0 S+ 0:00,00 grep squid

и сие означает, что SQUID работает (по крайней мере запустился без проблем).

Далее, проверим какой tcp-порт «слушает» SQUID:

root@testrouter:/usr/local/etc/squid # sockstat -4 -P tcp | grep squid

и видим следующее:

squid    squid      61617 11 tcp4   127.0.0.1:3128        *:*

т.е. SQUID «слушает» порт 3128 по адресу 127.0.0.1 — это именно то, что нам нужно! На данный момент мы точно знаем, что SQUID запустился и готов принимать запросы — осталось ему их «направить». А «направлять» мы будем с помощью правил Firewall-a (напоминаю, что SQUID устанавливался с поддержкой «прозрачного» режима для IPFW). Для начала посмотрим список действующих правил:

root@testrouter:/usr/local/etc/squid # ipfw show

лицезреть мы должны примерно следующее (SQUID устанавливался на уже работающий интернет-шлюз):

00100 328 38348 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00400 246 54793 allow ip from any to any via em1
01030 50649 20846028 nat 1 ip from any to any via em0
65535 5 612 deny ip from any to any

Данный набор правил формируется скриптом /etc/fw_script.01 уже настроенного интернет шлюза:

############### Скрипт fw_script.01 c командами ipfw #############
#создаем символьные подмена для более удобного написания правил
exface=»em0″ # внешний сетевой интерфейс сервера
inface=»em1″ # внутренний сетевой интерфейс сервера
in_ip=»172.16.0.100″ # ip-адрес внутреннего интерфейса сервера
# префикс команды, параметр -q означает «тихую» работу
pre_com=»ipfw -q»
# для начала удаляем все существующие правила!
$pre_com -f flush
# разрешение трафика на петлевом интерфейсе – необходимо для работы ОС
# Операционная система UNIX использует интерфейс lo0 и IP-адрес
# 127.0.0.1 для внутренних нужд. Таким образом, firewall должен
# обеспечивать беспрепятственный обмен данными на указанных интерфейсе и
# IP-адресе.
$pre_com add 100 allow ip from any to any via lo0
# запрет ip трафика от любого источника на всю сеть loopback интерфейса
$pre_com add 200 deny ip from any to 127.0.0.0/8
# запрет ip трафика со всей сети loopback интерфейса на любой источник
$pre_com add 300 deny ip from 127.0.0.0/8 to any
# разрешаем беспрепятственному прохождению трафика внутри нашей локальной сети!!!
$pre_com add 400 allow all from any to any via $inface
# включаем kernel NAT на интерфейсе em0 с параметрами
# сбрасывать таблицу соединений при смете ip-адреса сетевого интерфейса
# пытаться сохранить порты
# по-умолчанию запрещать входящие подключения
$pre_com nat 1 config log if $exface reset same_ports deny_in
# все что проходит через внешний интерфейс перенаправляем в NAT
$pre_com add 1030 nat 1 ip from any to any via $exface

Для работы SQUID в выше указанный набор нужно добавить два правила:

1. Правило, разрешающее исходящий трафик с loopback интерфейса сервера (именно на нем работает SQUID)

2. Правило, перенаправляющее трафик с нужных портов в SQUID.

Эти два новых правила для работы SQUID должны проверяться до NAT, а так же должны быть до правила №400 — иначе они никогда не будут проверяться.

Перед тем как добавить новые правила в скрипт конфигурации Firewall-a рекомендуется проверить их работу, что мы и сделаем.  Добавляем правило №1:

root@testrouter:/usr/local/etc/squid # ipfw add 350 allow tcp from me to any out via em0 keep-state uid squid

Добавленное выше правило разрешает tcp-пакетам, отправляемым демоном squid с любого интерфейса сервера уходить через интерфейс em0 (в нашем случае em0 является внешним интерфейсом.) Если правило успешно добавилось, в консоль будет выведено сообщение:

00350 allow tcp from me to any out via em0 uid squid keep-state

Заново смотрим список действующих правил Firewall-а:

root@testrouter:/usr/local/etc/squid # ipfw show

результат должен быть такой (новое 1-е правило выделено):

00100 64 6864 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00350 0 0 allow tcp from me to any out via em0 uid squid keep-state
00400 3 228 allow ip from any to any via em1
01030 152 19318 nat 1 ip from any to any via em0
65535 11 1341 deny ip from any to any

 Добавляем правило №2:

 root@testrouter:/usr/local/etc/squid # ipfw add 360 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any 80 out via em0

Добавленное правило перенаправляет все tcp-запросы, «уходящие» через интерфейс em0 с ip-адресов 172.16.0.0/24  на 80-й порт получателя. Если данное правило добавилось, в консоли появится следующее сообщение:

00360 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any dst-port 80 out via em0

Снова смотрим список действующих правил Firewall-а:

root@testrouter:/usr/local/etc/squid # ipfw show

результат должен быть такой (новое 2-е правило выделено):

00100 64 6864 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00350 0 0 allow tcp from me to any out via em0 uid squid keep-state
00360 0 0 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any dst-port 80 out via em0
00400 3 228 allow ip from any to any via em1
01030 152 19318 nat 1 ip from any to any via em0
65535 11 1341 deny ip from any to any

Настало время попробовать открыть какую нибудь WEB-страницу с ПК локальной сети. Показателями нормальной работы SQUID в режиме «прозрачного» проксирования являются: доступность WEB-страниц (это легко проверяется) и НЕНУЛЕВЫЕ значения срабатывания правил 350 и 360, что можно проверить командой:

root@testrouter:/usr/local/etc/squid # ipfw show

В моем случае результат таков:

00100 256 43452 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00350 700 297460 allow tcp from me to any out via em0 uid squid keep-state
00360 340 34022 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any dst-port 80 out via em0
00400 936 350101 allow ip from any to any via em1
01030 520 109626 nat 1 ip from any to any via em0
65535 11 1341 deny ip from any to any

Как видно, правила 350 и 360работают, на чем тест драйв считаем завершенным. Исходный скрипт /etc/fw_script.01 «кромсать» не будем, а сделаем на его основе новый:

root@testrouter:/usr/home/routeuser # cp /etc/fw_script.01 /etc/fw_script.proxy

Как не трудно догадаться, все изменения вносить будем уже в файл /etc/fw_script.proxy. Добавим в него два новых правила:

# разрешаем исходящий трафик через внешний интерфейс с процесса squid
$pre_com add 350 allow tcp from me to any out via $exface keep-state uid squid
# весь трафик tcp по нужным портам отправляем в SQUID
$pre_com add 360 fwd 127.0.0.1,3128 tcp from $loc_net to any 80 out via $exface

не забывая при этом описать переменную loc_net, определяющую диапазон адресов локальной сети.  Итоговое содержимое файла /etc/fw_script.proxy таково (изменения выделены):

############### Скрипт /etc/fw_script.proxy c командами ipfw #############
#создаем символьные подмена для более удобного написания правил
exface=»em0″ # внешний сетевой интерфейс сервера
inface=»em1″ # внутренний сетевой интерфейс сервера
in_ip=»172.16.0.100″ # ip-адрес внутреннего интерфейса сервера

loc_net=»172.16.0.0/24″ # локальная сеть
# префикс команды, параметр -q означает «тихую» работу
pre_com=»ipfw -q»
# для начала удаляем все существующие правила!
$pre_com -f flush
# разрешение трафика на петлевом интерфейсе – необходимо для работы ОС
# Операционная система UNIX использует интерфейс lo0 и IP-адрес
# 127.0.0.1 для внутренних нужд. Таким образом, firewall должен
# обеспечивать беспрепятственный обмен данными на указанных интерфейсе и
# IP-адресе.
$pre_com add 100 allow ip from any to any via lo0
# запрет ip трафика от любого источника на всю сеть loopback интерфейса
$pre_com add 200 deny ip from any to 127.0.0.0/8
# запрет ip трафика со всей сети loopback интерфейса на любой источник
$pre_com add 300 deny ip from 127.0.0.0/8 to any
# разрешаем исходящий трафик через внешний интерфейс с процесса squid
$pre_com add 350 allow tcp from me to any out via $exface keep-state uid squid
# весь трафик tcp по нужным портам отправляем в SQUID
$pre_com add 360 fwd 127.0.0.1,3128 tcp from $loc_net to any 80 out via $exface
# разрешаем беспрепятственному прохождению трафика внутри нашей локальной сети!!!
$pre_com add 400 allow all from any to any via $inface
# включаем kernel NAT на интерфейсе em0 с параметрами
# сбрасывать таблицу соединений при смете ip-адреса сетевого интерфейса
# пытаться сохранить порты
# по-умолчанию запрещать входящие подключения
$pre_com nat 1 config log if $exface reset same_ports deny_in
# все что проходит через внешний интерфейс перенаправляем в NAT
$pre_com add 1030 nat 1 ip from any to any via $exface

Теперь запустим скрипт /etc/fw_script.proxy:

root@testrouter:/usr/home/routeuser # sh /etc/fw_script.proxy

и взглянем на список действующих правил Firewall-a:

root@testrouter:/usr/home/routeuser # ipfw show

в моем случае результат таков:

00100 0 0 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00350 0 0 allow tcp from me to any out via em0 uid squid keep-state
00360 0 0 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any dst-port 80 out via em0
00400 0 0 allow ip from any to any via em1
01030 33 2500 nat 1 ip from any to any via em0
65535 4 701 deny ip from any to any

Можно констатировать, что новые правила добавились. Теперь пробуем открыть с ПК локальной сети WEB-страничку в интернете. Наша цель состоит в проверке работоспособности правил скрипта /etc/fw_script.proxy. Если WEB-страницы открываются, снова смотрим список действующих правил Firewall-а:

root@testrouter:/usr/home/routeuser # ipfw show

В моем случае результат таков:

00100 544 109274 allow ip from any to any via lo0
00200 0 0 deny ip from any to 127.0.0.0/8
00300 0 0 deny ip from 127.0.0.0/8 to any
00350 3750 2223167 allow tcp from me to any out via em0 uid squid keep-state
00360 1475 172951 fwd 127.0.0.1,3128 tcp from 172.16.0.0/24 to any dst-port 80 out via em0
00400 4090 2366520 allow ip from any to any via em1
01030 876 281451 nat 1 ip from any to any via em0
65535 4 701 deny ip from any to any

Отчетливо видно, что правила 350 и 360 работают, и можно настроить выполнение скрипта /etc/fw_script.proxy при загрузке нашего сервера. Для этого в файле /etc/rc.conf строку:

firewall_script=»/etc/fw_script.01″

меняем на

firewall_script=»/etc/fw_script.proxy»

Можно перезагрузить сервер и проверить работоспособность сервера после перезагрузки.

Следующий шаг — настройка возможности просмотра статистики.
Оригинал: суперхрюн.рф/index.php/freebsd/18-freebsd-9-x-squid-3-2-x-rezhim-transparent-proxy-dlya-ipfw

Рубрика: *Proxy, *Unix,*Linux, FreeBSD | 2 комментария

Создаем сервер — Часть 1. SAMBA

Создаем сервер — Часть 1. SAMBA

Доброго времени суток, друзья. Сегодня я начинаю серию статей о создании сервера в компании. Это практическое руководство, которое затронет все аспекты создания сервера начиная от установки системы вплоть до запуска. Начнем.

Итак, нам понадобятся:

  • компьютер
  • операционная система
  • голова и руки

Технические задачи:

  • файл-сервер SAMBA
  • VPN PPTP
  • Почтовый сервер
  • VoIP
  • Терминальный сервер

Предположим, что компьютер у нас есть. Оговорюсь, здесь не нужно серверное железо, простой компьютер с минимум 2 Гб оперативной памяти из расчета, что пользователей у вас будет до 100. Далее нам необходимо установить операционную систему. Дабы не устраивать здесь «холивар», я не буду говорить, какая система будет лучшей и самой надежной. Все они хороши, но выбрать стоит что-то из списка топ сайта Distrowatch.com (не Mint или Mageia). В данный момент у меня на работе установлен сервер на Debian. Но сейчас мы будем использовать CentOS 6.4, так как я считаю ее основополагающей при изучении Linux и достаточно надежной.

Вернемся к нашему проекту. Нам нужно установить систему. Уверен, что с процессом установки вы знакомы и мы не будем описывать здесь пошагово все. Единственное вам нужно решить вопрос с разметкой, если вы собираетесь (а мы собираемся) установить файл-сервер Samba и вы имеете в наличии 2 жестких диска, создать RAID-массив и также решите, в каком виде вы хотите получить операционную систему — минимальную консоль или с GUI. В общем, это вы решите сами.

Ну что ж, систему мы установили, перейдем непосредственно к задачам. И первый у нас на очереди «файл-сервер».

SAMBA

В моей системе после установки уже были установлены все необходимые пакеты SAMBA, в противном случае пакеты необходимо установить.

1
2
3
# su
pass:
# yum install -y samba

После того, как пакеты установились SAMBA не будет стартовать при старте системы, поэтому необходимо добавить процесс автозагрузки.

1
2
# chkconfig --level 345 smb on
# chkconfig --level 345 nmb on

Далее нам необходимо разрешить прослушивание портов UDP и TCP, так как по умолчанию данная опция не доступна. Для этого нам необходимо править iptables.

1
2
3
4
5
# iptables -I INPUT 4 -s 192.168.10.0/24 -m state --state NEW -m udp -p udp --dport 137 -j ACCEPT
# iptables -I INPUT 5 -s 192.168.10.0/24 -m state --state NEW -m udp -p udp --dport 138 -j ACCEPT
# iptables -I INPUT 6 -s 192.168.10.0/24 -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT
# service iptables save
# service iptables restart

Теперь, когда мы выполнили все начальные действия, можно приступить непосредственно к настройке нашего файлового сервера. Делается это в конфигурационном файле SAMBA smb.conf. Сперва создадим копию оригинального конфигуратора на случай «форс-мажор».

1 # cp /etc/samba/smb.conf /etc/samba/smb.conf.backup

Теперь приступим к настройке сервера. Я буду использовать редактор Midnight Commander, но вы можете делать это в любом удобном для вас.

1 mcedit /etc/samba/smb.conf

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[global]
# Имя рабочей группы
workgroup = WORKGROUP
# Описание компьютера
server string = MyServer
# Имя  компьютера в локальной сети
netbios name = CentOS
# Место расположение лог файла
log file = /var/log/samba/log.%m
# Максимальный размер лог файла
max log size = 50
# Тип доступа
security = user
# Видимость ресурса в сети
browseable = yes
# Является публичным, т.е. доступ разрешен всем.
public = yes
# Имя пользователя для доступа к шаре
guest account = user
# Название расшаренной папки в шаре
[share]
# Комментарий
comment = share
# Путь до расшаренной папки
path = /media/disk/share
# Видимость ресурса в сети
browseable = yes
# Разрешаем чтение и запись
read only = no
writable = yes
# Общий доступ или только для пользователя указанного в guest account - user
guest only = yes
guest ok = yes
public = yes

Я специально оставил комментарии, чтобы менее опытные пользователи понимали, что за что отвечает. Люди, более или менее владеющие английским языком могут обратиться к созданной копии. Там все очень подробно описано. Также советую обратиться к очень полезному ресурсу в сети по SAMBA — http://smb-conf.ru. От себя скажу, нужно запомнить один важный момент касательно конфигурационного файла — чем он меньше, тем лучше. Каждый параметр, имеющийся в SAMBA, имеет значение по умолчанию, поэтому если это значение по умолчанию совпадает с тем, что вы хотите указать, просто опустите его и система автоматически будет его использовать.

Итак, мы настроили конфигурацию нашего сервера и теперь нам необходимо создать пользователей. Сперва добавим пользователя в систему. Мы не хотим, чтобы этот пользователь мог выполнять вход на наш сервер, поэтому отключим ему shell и не будем создавать пароль и каталог. Но сперва создадим группы, в которые будем.

1 # groupadd group1 group2 group3

Группы созданы. Теперь создадим пользователей.

1 # useradd -M -G group1,group2 user1 --shell=/bin/false

Пользователи созданы. Теперь можно добавить созданных пользователей в SAMBA.

1
2
# smbpasswd -a user1
pass:

Добавим пользователям пароли для SAMBA. Не забываем, что в системе уже должны быть созданы соответствующие конфигурации папки и настроены права. Все, на этом создание файл-сервера закончено и в другой ОС уже все должно работать. Но в CentOS есть нюанс, который не позволит пользователям использовать сервер — это Firewall ОС. Пользователи могут видеть общие каталоги, но не могут в них войти. Есть два варианта выхода из данной ситуации — отключение Firewall’а ОС или его настройка. Нас, естественно, интересует второй вариант, так как это сервер и, хоть это и Linux, у него должна быть защита. Итак, для корректной работы файл-сервера необходимо дать разрешение Firewall’у использовать ресурсы сети.

1
2
3
4
# for i in "здесь вписываете названия общих каталогов SAMBA без кавычек"
> do
> chcon -R -t samba_share_t /"директория, в которой расположены общие каталоги"/$i
> done

Данное действие позволит SELinux разрешать пользователям использовать ресурсы SAMBA, но только до первой перезагрузки или обновления. Поэтому мы сделаем разрешения постоянными.

1
2
# semanage fcontext -a -t samba_share_t '/(/.*)?'
# restorecon -R /

Если вы вдруг столкнулись с ошибкой «semanage: команда не найдена», установите следующее.

1 # yum install -y policycoreutils-python

Вот и все. На этом настройка файл-сервера закончена. Если вы все сделали правильно, сервер прослужит надежно и долго.

Оригинал:alkom.by/alkomnet/archives/48

Рубрика: *CentOS, *Unix,*Linux | Оставить комментарий

OpenVPN custom ports and bridge with SELinux enabled

By default, SELinux policy on RHEL/CentOS only allow OpenVPN to work only on port 1194, and also without ability to execute brctl for setup bridge (even you configured script-security 2 in config)

You need to create SELinux plugins module to enable OpenVPN to execute brctl from external script and also able to connect any ports, but not listen (read bottom of this article, there is the way to enable allow listen to specific ports that not already defined by other SELinux policy).

here is how …

First, install required package

  • checkpolicy
  • policycoreutils
  • policycoreutils-python

create folder for store plugins such as /etc/selinux/local, cd to that folder

create openvpn-local.te files

module openvpn-local 1.0;

require {
        type openvpn_t;
        type port_t;
        type brctl_exec_t;
        class file { read getattr open execute execute_no_trans };
        class tcp_socket { name_connect };
}

#============= openvpn_t ==============
allow openvpn_t brctl_exec_t:file { read getattr open execute execute_no_trans };
allow openvpn_t port_t:tcp_socket { name_connect };

then compile module with

# checkmodule -M -m openvpn-local.te -o openvpn-local.mod

Then package selinux module with

# semodule_package -o openvpn-local.pp -m openvpn-local.mod

You can also download my prepackaged plugin here.

Now module is compiled, you can install by run

# semodule -i openvpn-local.pp

From now on, you should able to connect to OpenVPN and can execute brctl for interface setup scripts from OpenVPN.
Actually we can also enable OpenVPN script to execute any binary, but it too risky and not recommended (I will not talk into details here, it can complete by adjust above policy a bit).

But if you want OpenVPN to be able to listen to other port other than 1194. Create policy for listen to any ports is too risk, the safe way is to edit SELinux policy openvpn_t port lists. This archived by using this command to list ports allow by current openvpn SELinux policy.

# semanage port -l | grep openvpn_port_t
openvpn_port_t                 tcp      1194
openvpn_port_t                 udp      1194

This show only tcp/udp 1194. Now add the ports you want, but SELinux only allow port not defined by others type (see output of ‘semanage port -l’ to check which ports already defined).

This command add TCP port 11940 to openvpn_port_t to SELinux Policy

# semanage port -a -t openvpn_port_t -p tcp 11940

Your OpenVPN now should able listen on TCP port 11940.

I usually use this to test captive-portal remotely using VM bridged to OpenVPN interface that bridged to hotspot network on remote side.
This is example of my openvpn configuration that bridge to vlan10 bridge. (I did not include any encryption here, just for testing).

hotspot.conf

port 11940
proto tcp-server
dev-type tap
dev vpn.hotspot
persist-tun
script-security 2
up /etc/openvpn/hotspot.up

hotspot.up (remember to chmod +x)

#!/bin/bash

/sbin/ip link set dev vpn.hotspot up
/usr/sbin/brctl addif vlan10 vpn.hotspot

Comments:

# semanage ports -l | grep openvpn_port_t
Invalid parameter ports not defined.
*port

Sorry, my mistake.
The actual command is

  1. semanage port -l | grep openvpn_port_t

    port not ports.

    Оригинал: sf-alpha.bjgang.org/wordpress/2012/09/openvpn-custom-ports-and-execute-brctl-with-selinux-enabled/

Рубрика: *CentOS, *Unix,*Linux | Оставить комментарий

Особенности высоконагруженных WEB систем

Система начинается с данных

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

Нас в первую очередь интересуют два подхода к хранению и работе с данными SQL и NoSQL.

SQL (Structured Query Language) — язык структурированных запросов, применяемый для создания, модификации и управления данными в реляционных базах данных, основанных на реляционной модели данных. Думаю, подробно останавливаться на рассмотрении одноименного подхода не стоит, так как это первое с чем сталкивается любой, при изучении баз данных.

NoSQL (not only SQL, не только SQL) — ряд подходов, направленных на реализацию моделей баз данных, имеющих существенные отличия от средств языка SQL, характерного для традиционных реляционных баз данных.

Термин NoSQL был придуман Эриком Эвансом, когда Джоан Оскарсон из Last.fm хотел организовать мероприятие для обсуждения распределенных баз данных с открытым исходным кодом.

Концепция NoSQL не является полным отрицанием языка SQL и реляционной модели. NoSQL — это важный и полезный, но не универсальный инструмент. Одна из проблем классических реляционных БД — это сложности при работе с данными очень большого объема и в высоконагруженных системах. Основная цель NoSQL — расширить возможности БД там, где SQL недостаточно гибок, не обеспечивает должной производительности, и не вытеснять его там, где он отвечает требованиям той или иной задачи.

В июле 2011 компания Couchbase, разработчик CouchDB, Memcached и Membase, анонсировала создание нового SQL-подобного языка запросов — UnQL (Unstructured Data Query Language). Работы по созданию нового языка выполнили создатель SQLite Ричард Гипп (Richard Hipp) и основатель проекта CouchDB Дэмиен Кац ( Damien Katz). Разработка передана сообществу на правах общественного достояния

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

NoSQL системы

NoSQL СУБД

Определимся с понятиями.

Масштабируемость — автоматическое распределение данных между несколькими серверами. Такие системы мы называем распределенные базы данных. В них входят Cassandra, HBase, Riak, Scalaris и Voldemort. Если вы используете объем данных, который не может быть обработан на одной машине или если вы не хотите управлять распределением вручную, то это то, что вам нужно.

Следует обратить внимание на следующие вещи: поддержка нескольких датацентров и возможность добавления новых машин в работающий кластер прозрачно для ваших приложений.

Прозрачное добавление машины в кластер Поддержка нескольких датацентров
Cassandra X X
HBase X
Riak X X
Scalaris X
Voldemort Необходимо доработать напильником

К нераспределенным базам данных относятся: CouchDB, MongoDB, Neo4j, Redis и Tokyo Cabinet . Эти системы можно использовать в качестве «прослойки» для распределенных систем.

Модель данных и запросов

Существует огромное количество моделей данных и API запросов в NoSQL базах данных.

Модель данных API запросов
Cassandra Семейство столбцов Thrift
CoutchDB Документы Map / Reduce
HBase Семейство столбцов Thrift, REST
MongoDB Документы Cursor
Neo4j Графы Graph
Redis Коллекции Collection
Riak Документы Nested hashes, REST
Scalaris Ключ / Значение Get / Put
Tokyo Cabinet Ключ / Значение Get / Put
Voldemort Ключ / Значение Get / Put

Система семейства столбцов (column family) используется в Cassandra и HBase. В обеих системах, у вас есть строки и столбцы, но количество строк не велико: каждая строка имеет переменное число столбцов и столбцы не должны быть определены заранее.

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

Документно-ориентированные базы данных — это по существу следующий уровень систем ключ/значение, позволяющие связывать вложенные данные с ключом. Поддержка таких запросов более эффективна, чем просто возвращение всего значения.

Neo4J обладает уникальной моделью данных, которая описывает объекты в виде узлов и ребер графа. Для запросов, которые соответствуют этой модели (например, иерархических данных) производительность может оказаться выше на несколько порядков, чем для альтернативных вариантов.

Scalaris уникальна в части использования распределенных транзакций между несколькими ключами.

Система хранения данных

Это вид, в котором данные представлены в системе.

Вид данных
Cassandra Memtable / SSTable
CoutchDB Append-only B-Tree
HBase Memtable / SSTable on HDFS
MongoDB B-Tree
Neo4j On-disk linked list
Redis In-memory with background snapshots
Riak Hash
Scalaris In-memory only
Tokyo Cabinet Hash or B-Tree
Voldemort Pluggable (primarily BDB MySQL)

Система хранения данных может помочь при оценке нагрузок.

Системы, хранящие данные в памяти, очень-очень быстрые, но не могут работать с данными превышающими размер доступной оперативной памяти. Сохранность таких данных при сбое или отключении питания может стать проблемой. Количество данных которые могут ожидать записи на может быть очень велико. Некоторые системы, например Scalaris, решают данную проблему с помощью репликации, но Scalaris не поддерживает масштабирование на несколько датацентров.

Memtables / SSTables буферизируют запросы на запись в памяти (Memtable), а после записи добавляют в лог. После накопления достаточного количества записей, Memtable сортируется и записывается на диск, как SSTable. Это позволяет добиться производительности близкой к производительности оперативной памяти, в тоже время избавиться от проблем, актуальных при хранении только в памяти.

B-деревья используются в базах данных уже очень давно. Они обеспечивают надежную поддержку индексирования, однако производительность, при использовании на машинах с магнитными жесткими дисками, очень низкая.
Интересным является использование в CouchDB B-деревьев, только с функцией добавления (append-only B-Trees), что позволяет получить хорошую производительность при записи данных на диск. Достигается это тем, что бинарное дерево не нужно перестраивать при добавлении элемента.

Отдельного рассмотрения заслуживает проект Memcached , ставший прародителем для множества других систем.

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

Хеш-таблица — это структура данных, реализующая интерфейс ассоциативного массива, позволяющая хранить пары (ключ, значение) и выполнять три операции: операцию добавления новой пары, операцию поиска и операцию удаления пары по ключу.

С помощью клиентской библиотеки Memcached позволяет кэшировать данные в оперативной памяти из множества доступных серверов. Распределение реализуется путем сегментирования данных по значению хэша ключа по аналогии с сокетами хэш-таблицы. Клиентская библиотека, используя ключ данных, вычисляет хэш и использует его для выбора соответствующего сервера. Ситуация сбоя сервера трактуется как промах кэша, что позволяет повышать отказоустойчивость комплекса за счет наращивания количества memcached серверов и возможности производить их горячую замену.

Memcached имеет множество модификаций, развиваемых в рамках нескольких проектов: Mycached, membase, Memcache, MemcacheQ, Memcacheddb и libMemcached .

Центральный проект, локомотив концепции NoSQL — Memcached. Один из самых существенных минусов Memcached состоит в том, что сам кэш — весьма ненадежное место хранения данных. Устранить этот недостаток и призваны дополнительные решения: Memcacheddb и membase. На уровне интерфейса (API) эти продукты полностью совместимы с Memcached. Но здесь, при устаревании данных, они сбрасываются на диск (стратегия « db checkpoint »). В таком виде они представляют собой яркий пример «нереляционных баз данных» — персистентных (долговременных) систем распределённого хранения данных в виде пар «ключ-значение».

Следующий продукт, на основе Memcached — MemcacheQ. Это система очередей сообщений, в которой используется очень упрощенный API от Memcached. MemcacheQ образует именованный стек, куда можно записать свои сообщения, а сами данные физически хранятся в БД BerkeleyDB (аналогично Memcacheddb), следовательно, обеспечиваются сохранность, возможность реплицирования и прочее.

LibMemcached — это известная клиентская библиотека, написанная на С++, для работы с уже стандартным протоколом Memcached.

Все нереляционные хранилища, выполненные в виде распределенной системы и хранящие пары «ключ-значение», можно подразделить на два типа: устойчивые и неустойчивые. Устойчивые (например, MemcachedB, membase, Hypertable ) — записывают данные на диск, обеспечивая их сохранность в случае сбоя. Неустойчивые (классический Memcached) — хранят ключи в энергозависимой памяти и не гарантируют их сохранность. Неустойчивые хранилища оправдано использовать для кеширования и снижения нагрузки на устойчивые — в этом их неразрывная связь и главное преимущество.

Устойчивые хранилища – это уже полноценные NoSQL базы данных, которые совмещают в себе скорость работы Memcached и позволяют хранить более сложные данные.

Схема frontend+backend

Самая распространенная схема, при которой в роли frontend выступает быстрый и легкий web сервер (например Nginx), а в качестве backend работает Apache.

Давайте рассмотрим преимущества такой схемы на примере. Представим, что web серверу Apache необходимо обслужить порядка 1000 запросов одновременно, причем многие из этих клиентов подключены к интернету по медленным каналам связи. В случае использования Apache мы получим 1000 процессов httpd, на каждый из которых будет выделена оперативная память, и эта память будет занята до тех пор, пока клиент не получит запрошенный контент или не возникнет ошибка.

В случае применения схемы frontend+backend, после того как пришел запрос клиента, Nginx передает запрос Apache и быстро получает ответ. А в случае со статическим контентом (html, картинки, файлы кеша и пр.) Nginx самостоятельно сформирует ответ, не потревожив Apache. Если нам все-таки нужно выполнить логику (php-скрипт), Apache после того как сделал это и отдал ответ Nginx освобождает память, далее с клиентом взаимодействует web сервер Nginx, который как раз и предназначен для раздачи статического контента, большому количеству клиентов, при незначительном потреблении системных ресурсов. В купе с грамотным кэшированием, получаем колоссальную экономию ресурсов сервера и систему, которую по праву можно назвать высоконагруженной.

Рабочие лошадки

Apache — оптимизация производительности

Для схемы frontend+backend производительность Apache не стоит столь остро, но если Вам дорога каждая микросекунда процессорного времени и каждый байт оперативной памяти, то следует уделить внимание этому вопросу.

Самый «крутой» способ – увеличить производительность сервера – поставить более шустрый процессор(ы) и побольше памяти, но мы с Вами пойдем по менее радикальному пути для начала. Ускорим работу Apache путем оптимизации его конфигурации. Существуют конфигурации, которые можно применить только при пересборке Apache, другие же можно применять без перекомпиляции сервера.

Загружайте только необходимые модули

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

Уменьшив количество модулей, Вы уменьшите объем потребляемой памяти. Если вы решили скомпилировать Apache самостоятельно, то либо тщательно подходите к выбору списка модулей, которые Вы хотите включить, либо скомпилируйте их как DSO, используя apxs в Apache1 и apxs2 в Apache2. Чтобы отключить ненужные DSO-модули, достаточно закомментировать лишние строчки LoadModule в httpd.conf. Если скомпилировать модули статически, Apache будет потреблять чуть меньше памяти, но Вам придется каждый раз его перекомпилировать, чтобы отключить или вкличить тот или иной модуль.

Выбирайте подходящий MPM

Для обработки запроса в Apache выделяется свой процессе или поток. Эти процессы работают в соответствии с одной из MPM (Мультипроцессорная модель). Выбор MPM зависит от многих факторов, таких как наличие поддержки потоков в ОС, объема свободной памяти, а также требований стабильности и безопасности.

Если безопасность превыше производительности, выбирайте peruser или Apache-itk. Если важнее производительность, обратите внимание на prefork или worker.

Название Разработчик Поддерживаемые OS Описание Назначение Статус
worker Apache Software Foundation Linux, FreeBSD Гибридная мультипроцессорно-мультипоточная модель. Сохраняя стабильность мультипроцессорных решений, она позволяет обслуживать большое число клиентов с минимальным использованием ресурсов. Среднезагруженные веб-серверы. Стабильный.
pre-fork Apache Software Foundation Linux, FreeBSD MPM, основанная на предварительном создании отдельных процессов, не использующая механизм threads. Большая безопасность и стабильность за счёт изоляции процессов друг от друга, сохранение совместимости со старыми библиотеками, не поддерживающими threads. Стабильный.
perchild Apache Software Foundation Linux Гибридная модель, с фиксированным количеством процессов. Высоконагруженные серверы, возможность запуска дочерних процессов используя другое имя пользователя для повышения безопасности. В разработке, нестабильный.
netware Apache Software Foundation Novell NetWare Мультипоточная модель, оптимизированная для работы в среде NetWare. Серверы Novell NetWare Стабильный.
winnt Apache Software Foundation Microsoft Windows Мультипоточная модель, созданная для операционной системы Microsoft Windows. Серверы под управлением Windows Server. Стабильный.
Apache-ITK Steinar H. Gunderson Linux, FreeBSD MPM, основанная на модели prefork. Позволяет запуск каждого виртуального хоста под отдельными uid и gid. Хостинговые серверы, серверы, критичные к изоляции пользователей и учёту ресурсов. Стабильный.
peruser Sean Gabriel Heacock Linux, FreeBSD Модель, созданная на базе MPM perchild. Позволяет запуск каждого виртуального хоста под отдельными uid и gid. Не использует потоки. Обеспечение повышенной безопасности, работа с библиотеками, не поддерживающими threads. Стабильная версия от 4 октября 2007 года, экспериментальная — от 10 сентября 2009 года.

Для смены MPM требуется перекомпиляция Apache. Для этого удобнее взять source-based дистрибутив.

DNS lookup

Директива HostnameLookups включает обратные DNS запросы, при этом в логи пишутся dns-хосты клиентов вместо ip-адресов. Это существенно замедляет обработку запроса, т.к. запрос не обработается, пока не будет получен ответ от DNS-сервера. Следите, чтобы эта директива всегда была выключена (HostnameLookups Off). Если необходимы dns-адреса, можно «прогнать» лог в утилите logresolve.

Кроме того, следите, чтобы в директивах Allow from и Deny From использовались ip-адреса а не доменные имена. В противном случае Apache будет делать два dns запроса (обратный и прямой), чтобы узнать ip и убедиться что клиент валиден.

AllowOverride

Если директива AllowOverride не установлена в None, Apache попытается открыть .htaccess файлы в каждой директории, которую он посещает и во всех директориях выше нее. Например:

DocumentRoot /var/www/html

AllowOverride all

Если будет запрошен /index.html, Apache попытается открыть (и интерпретировать) файлы /.htaccess, /var/.htaccess, /var/www/.htaccess, и /var/www/html/.htaccess. Очевидно, что это увеличивает время обработки запроса. Так что, если вам нужен .htaccess только для одной директории, разрешите его только для нее:

DocumentRoot /var/www/html

AllowOverride None

AllowOverride all

FollowSymLinks и SymLinksIfOwnerMatch

Если для каталога включена опция FollowSymLinks, Apache будет следовать по символическим ссылкам в этом каталоге . Если включена опция SymLinksIfOwnerMatch, Apache будет следовать по символическим ссылкам, только если владелец файла или каталога на которую указывает эта ссылка, совпадает с владельцем указанного каталога. Поэтому при включенной опции SymLinksIfOwnerMatch Apache делает больше системных запросов. Кроме того, дополнительные системные запросы требуются, когда FollowSymlinks не определен. Следовательно, наиболее оптимальным для производительности будет включение опции FollowSymlinks, конечно, если политика безопасности позволяет это сделать.

Content Negotiatio

Механизм, определенный в HTTP спецификации, который позволяет обслуживать различные версии документа (представления ресурса), для одного и того же URI, чтобы клиент смог определить, какая версия лучше соответствует его возможностям. Когда клиент отправляет запрос на сервер, то сообщает серверу, какие типы файлов он понимает. Каждому типу соответствует рейтинг, описывающий насколько хорошо клиент его понимает. Таким образом, сервер, способен предоставить версию ресурса, который наилучшим образом соответствует потребностям клиента.

Нетрудно понять, чем это грозит для производительности сервера, поэтому избегайте применения content negotiaion.

MaxClients

Директива MaxClients устанавливает максимальное количество параллельных запросов, которые будет поддерживать сервер. Значение MaxClient не должно быть слишком маленьким, иначе многим клиентам будет отказано. Нельзя устанавливать слишком большое количество – это грозит нехваткой ресурсов и «падением» сервера. Ориентировочно, MaxClients = количество памяти выделенное под веб-сервер / максимальный размер порожденного процесса или потока. Для статических файлов Apache использует около 2-3 Мб на процесс, для динамики (php, cgi) – зависит от скрипта, но обычно около 16-32 Мб. Если сервер уже обслуживает MaxClients запросов, новые запросы попадают в очередь, размер которой устанавливается директивой ListenBacklog.

MinSpareServers, MaxSpareServers, и StartServers

Создание потока, и особенно процесса – ресурсоемкая операция, поэтому Apache создает их про запас. Директивы MaxSpareServers и MinSpareServers устанавливают минимальное и максимальное число процессов/потоков, которые должны быть готовы принять запрос. Если значение MinSpareServers слишком мало и пришло много запросов, Apache начнет создавать много новых процессов/потоков, что создаст лишнюю нагрузку в пиковые моменты. Если MaxSpareServers слишком велико, Apache будет излишне нагружать систему, даже если число запросов минимально.

Опытным путем нужно попдобрать такие значения, чтобы Apache не создавал более 4 процессов/потоков в секунду. Если он создаст более 4, в ErrorLog будет сделана соответствующая запись – сигнал того что MinSpareServers нужно увеличить.

MaxRequestsPerChild

Директива MaxRequestsPerChild определяет максимальное число запросов, которое может обработать один дочерний процесс/поток прежде чем он завершиться. По умолчанию значение установлено в 0, что означает, что не будет завершен никогда. Рекомендуется установить MaxRequestsPerChild равное числу запросов за час. Это не создаст лишней нагрузки на сервер и, в то же время, поможет избавиться от проблем с утечкой памяти в дочерних процессах (например, если вы используете нестабильную версию php).

KeepAlive и KeepAliveTimeout

KeepAlive позволяет делать несколько запросов в одном TCP-подключении. При использовании схемы frontend+backend, эти директивы не актуальны.

HTTP-сжатие

Сейчас все современные клиенты и практически все сервера поддерживают HTTP-сжатие. Использование сжатия позволяет понизить трафик между клиентом и сервером до 4-х рах, повышая при этом нагрузку на процессор сервера. Но, если сервер посещает много клиентов с медленными каналами, сжатие способно снизить нагрузку посредством уменьшения времени передачи сжатого ответа. При этом ресурсы, занятые дочерним процессом освобождаются быстрее, и уменьшается число одновременных запросов. Это особенно заметно в условиях ограничения памяти.

Отмечу, что не следует устанавливать степень сжатия gzip более 5, так как существенно возрастает нагрузка на процессор, а степень сжатия растет незначительно. Также, не следует сжимать файлы, формат которых уже подразумевает сжатие – это практически все мультимедийные файлы и архивы.

Кеширование на стороне клиента

Не забывайте устанавливать Expires заголовки для статических файлов (модуль mod_expires). Если файл не изменяется, то всегда следует дать указание клиенту закэшировать его. При этом у клиента будут быстрее загружаться страницы, а сервер избавиться от лишних запросов.

Отключение логов

Отключение логов помогает временно справиться с нагрузкой в пиковые моменты. Эта мера существенно сокращает нагрузку на все виды ПО и является универсальным средством в критической ситуации. Естественно, при очевидных недостатках, не может рекомендоваться к применению и служит лишь временным решением проблемы.

Nginx

Простой и легкий веб-сервер, специально предназначенный для обработки статических запросов. Причина его производительности в том, что рабочие процессы обслуживают одновременно множество соединений, мультиплексируя их вызовами операционной системы select, epoll ( Linux) и kqueue ( FreeBSD). Сервер имеет эффективную систему управления памятью с применением пулов. Ответ клиенту формируется в буферах, которые хранят данные либо в памяти, либо указывают на отрезок файла. Буферы объединяются в цепочки, определяющие последовательность, в которой данные будут переданы клиенту. Если операционная система поддерживает эффективные операции ввода-вывода, такие как writev и sendfile , то Nginx, по возможности, применяет их.

При использовании в связке с Apache, Nginx настраивается на обработку статики и используется для балансировки нагрузки. Подавляющее время занимается лишь тем, что отдает статический контент, делает это очень быстро и с минимальными накладными расходами.

Lighttpd

«Веб-сервер, разрабатываемый с расчётом на быстроту и защищённость, а также соответствие стандартам.» – википедия

Является альтернативой Nginx и применяется для тех же целей.

Акселераторы PHP

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

Существующие решения

The Alternative PHP Cache —был задуман, как бесплатный, открытый и стабильный фреймворк для кэширования и оптимизации исходного кода PHP. Поддерживает PHP4 и PHP5, включая 5.3.

eAccelerator — это свободный открытый проект, выполняющий также роли акселератора, оптимизатора и распаковщика. Имеет встроенные функции динамического кэширования контента. Имеется возможность оптимизации PHP-скриптов. Поддерживает PHP4 и PHP5, включая 5.3.

PhpExpress бесплатный ускоритель обработки PHP скриптов на веб-сервере. Также обеспечивает поддержку загрузки файлов закодированных через Nu-Coder. Поддерживает PHP4 и PHP5, включая 5.3

XCache поддерживает PHP4 и PHP5, включая 5.3. Начиная с версии 2.0.0 (release candidate от 2012-04-05) включена поддержка PHP 5.4.

Windows Cache Extension for PHP — PHP-акселератор для Microsoft IIS (BSD License). Поддерживает только PHP (5.2 и 5.3).

Логика кэширования

«Кэшировать, кэшировать и еще раз кэшировать!» — вот девиз высоконагруженной системы.

Давайте представим себе идеальный высоконагруженный сайт. Сервер получает http запрос от клиент. Frontend сопоставляет запрос с физическим файлом на сервере и, если тот существует, отдает его. Загрузку скриптов и картинок опустим, так как это в большинстве своем статика и отдается по такому же принципу. Далее, если физически файл не существует, frontend обращается с этим запросом к backend-у, который занимается обработкой логики (скриптов php и т.д.). Backend должен решить кэшировать ли данный запрос и создать файл в определенном месте, который и будет отдаваться frontend-ом в дальнейшем. Таким образом, мы навсегда закэшировали данный запрос и сервер будет обрабатывать его максимально быстро с минимально возможной нагрузкой на сервер.

Данный идеальный пример подходит для страниц, содержание которых не меняется с течением времени, либо меняется редко. На практике же мы имеем страницы, содержимое которых может меняться с каждым последующим запросом. Вернее часть этого содержимого. Примером такого содержимого может служить пользовательская информация, которая должна меняться с незаметной для пользователя задержкой или отображаться в реальном времени (обновляться при каждой перезагрузке страницы). Тут перед нами возникает задача, которая сводится к разделению динамических и статических данных на странице.

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

Таким образом, запрос клиента (кроме запроса статики) переадресуется на backend и его обработка сводится к следующим действиям:

  1. Получение информации о блоках, которые будут на странице.
  2. Проверка информации о кэшах для каждого блока. Кэш может не существовать или нуждаться в обновлении. В этом случае генерируем файл кэша. Если блок не должен кэшироваться выполняем соответствующую логику. Информацию о кэшах можно хранить в nosql базе данных или в файловой структуре. Тут требование одно: получение этой информации должно занимать минимум ресурсов.
  3. Формируем html страницы. Закэшированные блоки встраиваем при помощи ssi инструкции (вставляется ссылка на файл кэша), что позволит существенно экономить память.
  4. Страница попадает на frontend, который производит замену всех ssi инструкций на содержимое файлов и отдает страницу клиенту.

Также, распространенным является кэширование результатов выполнения функции или метода класса. При этом, мы передаем кэширующей функции ссылку на объект (если вызываем метод), имя метода или функции (если это глобальная функция) и параметры, предназначающиеся этому методу или функции. Кэширующая функция проверит наличие файла кэша, при необходимости, сформирует его или прочтет, а затем вернет результат.

Это общее описания принципа работы высоконагруженного сайта. Конкретная реализация будет отличаться деталями, но концепция останется прежней.

Картинки, пикчи, тумбочки

Оказывается изображение тоже можно кэшировать. Зачем? Спросите Вы. В принципе, после загрузки на сервер у нас уже есть файл, который frontend быстренько выплюнет при необходимости. Но часто нам требуется получить на основе уже имеющейся картинки другое изображение (например, других размеров). Допустим, нам нужна миниатюра изображения – thumbnail (тумбочка жарг.). В этом случае, нам достаточно сформировать путь к бедующему файлу уменьшенной картинки и отдать страницу клиенту.

  1. Клиент, получив исходный код страницы, начинает подгружать статику и обращается с запросом на несуществующую пока картинку к frontend-у.
  2. Frontend переадресует запросы к несуществующим изображениям на backend.
  3. Backend анализирует запрос, формирует файл изображения и отдает бинарные данные с соответствующим http-заголовком.
  4. Все последующие запросы будут отдаваться frontend-ом.

    Оригинал: kharchuk.ru/%D0%A1%D1%82%D0%B0%D1%82%D1%8C%D0%B8/7-PHP%20%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5/160-highload-sites

Рубрика: *CentOS, *Unix,*Linux, *Web | Оставить комментарий

Установка memcached на CentOS 6

Установка memcached на CentOS/RHEL/Fedora

Memcached – это система кэширования данных в памяти,  поэтому это самое быстрое кэширование в отличие от файлового кэша расположенного на жёстком диске, который в десятки раз медленнее. Главный плюс Memcached в том, что он снижает нагрузку на базу данных и файловую систему в целом путём уменьшения количества обращения к ней. И таким образом увеличивает скорость обращения к наиболее часто используемым данным. Memcached, конечно же, рекомендуется для установки на высоконагруженных серверах. А также на сервера с большим количеством пользовательских подключений.

В данный момент мы будем производить установку на на CentOS 6. Отличие от ранних версий CentOS и других операционных систем Linux указанных выше лишь в подключаемых репозиториях и синтаксисе. В остальном указанное ниже без проблем устанавливается на то, что будете использовать и вы.

1. Подключаем дополнительный репозиторий REMI, который не потребуется в случае, если вы используете Fedora 17, Fedora 16, Fedora 15, Fedora 14, Fedora 13, Fedora 12 или RHEL 6:

# rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm

# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm

2. Теперь, когда мы подключили дополнительные репозитории можно устанавливать Memcache:

# yum install memcached

# yum —enablerepo=remi install memcached

3. Далее необходимо внести изменения в конфигурационный файл memcache:

PORT=»11211″

USER=»memcached»

MAXCONN=»2048

″ Параметр отвечает за максимальное количество подключений

CACHESIZE=»4096

″ Укажите четверть от количества фактической ОЗУ на сервере

OPTIONS=»-l 127.0.0.1

″ Либо можно ничего не указывать

4. Добавим memcached в автозагрузку и запустим. Также перезапустим apache:

# chkconfig memcached on

# service memcached start

# service httpd restart

5. Теперь проверим статус работы:

memcached (pid 17302) is running…

tcp        0     0 0.0.0.0:11211      0.0.0.0:*           LISTEN      17302/memcached tcp        0     0 :::11211                    :::*                        LISTEN      17302/memcached udp       0     0 0.0.0.0:11211      0.0.0.0:*                                 17302/memcached udp       0     0 :::11211                    :::*                                              17302/memcached

На экране не очень ровно, но суть ясна. Значит всё ОК. Вроде бы и всё, но есть ещё пара ньюансов.

6. Если Memcached будет использоваться другими локальными серверами, то необходимо внести изменения в iptables:

-A INPUT -m state —state NEW -m tcp -p tcp —dport 11211 -j ACCEPT

Перезапустим iptables

service iptables restart

или

/etc/init.d/iptables restart

7. В заключении давайте ещё установим Memcache и/или Memcached PHP Module:

# yum install php-pecl-memcache

# yum install php-pecl-memcached

Последний шаг прописать extension в файлике php.ini

extension = “memcache.so”

Сохраняем. Ну и не забываем перезапустить apache…

Если всё правильно, то вывод команды php -i | grep memcache должен показать примерно следующее:

memcache

memcache support => enabled

memcache.allow_failover => 1 => 1

memcache.chunk_size => 8192 => 8192

memcache.default_port => 11211 => 11211

memcache.default_timeout_ms => 1000 => 1000

memcache.hash_function => crc32 => crc32

memcache.hash_strategy => standard => standard

memcache.max_failover_attempts => 20 => 20

Registered save handlers => files user sqlite memcache

Оригинал: wiki.hpfh.net/ustanovka-memcached-na-centos-6/

Рубрика: *CentOS | Оставить комментарий