четверг, 17 апреля 2008 г.

Transparent proxy в домашних условиях или как я просветлял Squid

И так, захотелось подключить бук к сети через стационарную машинку. При этом выход в сеть со стационара осуществляется через прокси, а сама локалка есть объединение нескольких сетей, запросы к которым идут напрямую. Настраивать прокси на буке не охота, т.к. работать он будет не только в этой сети, а перенастраивать всё это дело каждый раз лениво. Пусть сеть, к которой подключен стационар есть сеть А, а сеть между стационаром и буком есть сеть В.
Т.о. для решения проблемы надо сделать две вещи:
  1. настроить маскарадинг для сети между буком и стационаром
  2. перенаправлять все пакеты, не принадлежащие ни одной из сетей на локальный сквид, настроенный на внешний прокси.
1. Маскарадинг
...делается легко, тем более что в моём любимом AltLinux есть фронтенд для создания правил iptables. Т.о. делаем маскарад для всех tcp,udp,icmp пакетов из сети В, если адресат не принадлежит этой сети:
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE tcp -- 192.168.0.0/24 !192.168.0.0/24
MASQUERADE udp -- 192.168.0.0/24 !192.168.0.0/24
MASQUERADE icmp -- 192.168.0.0/24 !192.168.0.0/24
После этого необходимо убедиться, что у нас в ядре разрешено перенаправление пакетов:

#cat /proc/sys/net/ipv4/ip_forward

Если внутри единичка, то всё ок, иначе ищем файл, откуда этот параметр управляется, в моём случае это /etc/net/sysctl.conf строчка net.ipv4.ip_forward = 1 (на выяснение этого обстоятельства у меня ушло несколько часов). Можно, конечно, сделать #echo 1 > /proc/sys/net/ipv4/ip_forward, но это слетит после перезагрузки. Можно засунуть эту команду в какой-нить из загрузочных скриптов, но это костыль.
И так, с маскарадингом разобрались. Бук успешно заходит на ftp, smb локалки.

2. Просветление Squid
С настройкам сквида я немного схалтурил. Взял пример настройки, что уже был с ним и работал для localhost. Разрешил запросы из сети В, указал parent-proxy, сказал перенаправлять ssl-пакеты сразу на parent:
#/etc/squid/squid.conf
acl SSL method CONNECT
never_direct allow SSL //заворачиваем ssl-конекты через parent
acl our_networks src "/etc/squid/our_networks" //в our_networks список сетей, которым разрешено пользоваться прокси
http_access allow our_networks
http_port 3128 transparent //говорим, что работать надо в прозрачном режиме.
cache_peer my.proxy.ru parent 8080 0 default
#hierarchy_stoplist ... //снимаем какие-либо ограничения на загрузку контента
Так, с настройками сквида разобрались. Теперь осталось настроить прозрачность. Один из методов, использовать iptables для перенаправления пакетов, предназначенных наружу, на 3128 порт нашего прокси.
Самое простое - перенаправлять все пакеты, выходящие за рамки нашей сети, на прокси. Проблема в том, что наша сеть объединяет несколько диапазонов. Я сделал вот как:
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT 0 -- anywhere 10.0.0.0/8
ACCEPT 0 -- anywhere 192.168.0.0/16
ACCEPT 0 -- anywhere 172.16.0.0/19
ACCEPT 0 -- anywhere 127.0.0.0/8
REDIRECT tcp -- anywhere anywhere redir ports 3128
REDIRECT udp -- anywhere anywhere redir ports 3128
Т.е. если пакет принадлежит хоть одной сети, то для него выполняется ACCEPT и он вылетает из цепочки. Если же он не принадлежит ни одной из перечисленных сетей, то он докатывается до правила REDIRECT, и там уже прокси решает что с ним делать.
И так, прозрачность для локальной машинки настроили (коли мы уж заморочились с прокси, то почему бы не поиметь его преимущества и локально?). Но тут кроется один очень серьёзный подвох. ssl не работает через прозрачный прокси, никак, никогда. Дело в том, что по-сути iptables выполняют роль посредника между клиентом и прокси, что недопустимо для ssl, который направлен против этих самых посредников. Т.о. ни тебе jabber по ssl, ни почты.. для всего этого надо настраивать прокси явно. Сам же я ограничился лишь указанием ssl-proxy в браузере, как неким компромисным решением, т.к. на сквиде лежит кеширование и в перспективе - вырезка рекламы.
Теперь, для того чтобы прозрачность работала и для сети В, добавляем цепочку правил подобную OUTPUT в PREROUTING, указав eth2 (куда подключен бук), в качестве исходного интерфайса. Выглядит всё это немного необтёсано, может со временем созреет что-нить покрасивее :).

Комментариев нет: