Як зробити прозорий WWW-proxy, Сервери, Інтернет-технології, статті

Мережеві рішення

У деякий момент я виявив, що більшу частину вхідного трафіку в моїй мережі становить WWW. При цьому клієнти не користувалися Proxy, хоча це помітно прискорило б їхню роботу (hit ratio становить у нас майже 50%), а пройтися по всім клієнтам і поправити настройки їх броузерів я не мав можливості (та й бажання теж). Думаю, подібні проблеми часто виникають і в ISP, коли поправити налаштування клієнтів просто не можна.

Почитавши Squid’овскій FAQ, я знайшов там опис того, як змусити клієнтів насильно використовувати Proxy, проблема полягала тільки в тому, що запропонований спосіб не працював. З іншого боку, я знав, що в RadioMSU таки змусили працювати всіх своїх клієнтів через Proxy.
Після консультації все стало на свої місця і остаточне рішення було зроблено за пару годин.
Як це у мене працює

Дійові особи та виконавці:

• Роутер Cisco 2511 виробництва Cisco Systems. До нього підключені всі клієнти (локальна мережа на Ethernet і клієнти по Dialup), зовнішній канал на Demos теж включений туди ж. Для простоти уявімо, що LAN має адреси / маску 192.168.1/24, а dialup-клієнти – 192.168.2/24.
• Машина, на якій встановлено кешуючий proxy – Pentium-200, 64M RAM, 8Gb дисків. Працює під управлінням FreeBSD 2.2.5. На машині встановлений IPFilter 3.2.3 та Squid 1.NOVM.20. Для простоти викладу уявімо, що адреса цієї машини – 192.168.1.1
Налаштування

На Cisco

Потрібно звернути всі транзитні пакетики з destination eq 80 на Proxy. Це робиться приблизно так:
! Prevent loops
access-list 101 deny tcp host 192.168.1.1 any eq 80
! All other clients:
access-list 101 permit tcp 192.168.1.0 0.0.0.255 any eq 80
access-list 101 permit tcp 192.168.2.0 0.0.0.255 any eq 80
! Route-map
route-map forced-proxy permit 10
match ip address 101
set ip next-hop 192.168.1.1
!
! Інтерфейси:
! LAN
interface Ethernet 0
ip policy route-map forced-proxy
!
! Dialup
interface Group-Async 1
group-range 1 16
ip policy route-map forced-proxy
На машині з proxy

Насамперед потрібно загорнути приходять на 80-й порт пакети на proxy. Припускаючи, що proxy працює на порту 3128, це робиться якось так:
ipnat -f – <<EOM
rdr ed0 192.168.1.1/32 port 80 -> 192.168.1.1 port 80
rdr ed0 0.0.0.0/0 port 80 -> 192.168.1.1 port 3128
EOM
Перше правило дозволяє працювати локальному WWW-серверу – він буде продовжувати отримувати свої пакетики. Друга строчка перенаправляє всі інші пакети з destination port 80 на локальний Squid.
В squid.conf пишуться рядки виду
httpd_accel www.your.domain 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on
В FAQ рекомендовано замість імені сервера в рядку httpd_accel писати слово virtual. Це – неправильно, у всякому разі для Squid-1.NOVM.18 .. 20. Проблема в тому, що в цьому режимі Squid визначає destination server за викликом getsockname (2), проте цим викликом він може отримати тільки один зі своїх адрес, а це явно не підходить до умов задачі.
Отримана конструкція працює за такою ось схемою (я малював цю картинку хвилин 10 і хоча вона тут майже не потрібна, не пропадати ж добру):
Покращення

При такій настройці, адреса реального сервера до якого звертається користувач буде братися з заголовка Host: HTTP-запиту. Для переважної більшості клієнтів цього достатньо – всі скільки поширені броузери цей заголовок ставлять. Однак хочеться більшого.
В-принципі, можна було б написати окрему маленьку програму (замість proxy), яка запитувала б у IPFilter реальний destination-address пакета, формувала б заголовок Host: і віддавала б все це кешуючого proxy. Проте такий підхід має свої недоліки – в логах Squid будуть тільки локальні адреси і зіставити, скажімо, Hit Ratio з конкретним клієнтом буде непросто. Я пішов іншим шляхом і вмонтував необхідну функціональність прямо в Squid. Після установки цього патча, Squid почне розуміти директиву httpd_accel_ uses_ipfilter_redirect в конфігураційному файлі. Використовувати її потрібно так:
httpd_accel_uses_ipfilter_redirect on
В squid 2.x ця функціональність присутня, якщо запускати configure-enable-ipf-transparent, при цьому ніяких додаткових директив не потрібно, це включено за замовчуванням.
Після всіх цих змін все працює і без заголовка Host. Правда вимога, щоб клієнт був HTTP-1.x (а не HTTP/0.9) залишається, але вже HTTP/0.9 клієнтів я взагалі дуже давно не зустрічав.
Можливі проблеми

Можливі проблеми пов’язані з ICMP-повідомленнями ‘packet too big’. Справа тут ось у чому. Припустимо, між HTTP-Proxy і клієнтом є лінк з маленьким MTU, при цьому і клієнт і proxy живуть на media з великим MTU. Уявімо, що proxy починає відповідати клієнтові з якимось розміром пакету, який не пролізе через цей тонкий лінк. Ipnat підмінить source-address у цього пакета на IP-address сервера до якого звертався клієнт. Якщо на шляху зустрінеться занадто маленький MTU, то ICMP-повідомлення про це виїде на якийсь www.microsoft.com, якому він абсолютно ні до чого.
Ідея лікування зрозуміла – загорнути на тій же Cisco все ICMP-пакети на хост з WWW-proxy, там їх перевіряти на предмет відповідності з якоюсь рядком з таблиці трансляції Ipnat, все які “неправильні” віддавати прямо місцевим TCP-стеку, всі інші – відсилати далі (можна при цьому підміняти у них source address на якийсь лівий). Це теорія. До практики у мене руки поки не дійшли за повною непотрібністю – У мене всі клієнти мають MTU 1500.
Олексій Тутубалін

editorial

“Все це звичайно дуже здорово, – скажете ви, – але знаєте-ли, в нашій країні, на відміну від сусідської дружньої Росії, культ FreeBSD не поширився настільки широко – ми все” чиста по Лінуху “. Що ж нам з цими рекомендаціями робити? “. Ви маєте рацію, шановний читач 🙂 Тому, не вдаючись в подробиці, я вирішила черконути пару слів про облаштування прозорою проксі під Лінукс.
Якщо припустити, що ваші клієнти також підключені до циске, все описане Олексієм в цьому розділі залишається без змін. Для ядер 2.0.х (береться з прикладу для 2.0.29 – обережно, з іншими ядрами можуть бути нюанси!) –
1. компілюємо ядро ​​з підтримкою наступних речей:
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
#
# Networking options
#
CONFIG_FIREWALL=y
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
CONFIG_IP_FORWARD=y
# CONFIG_IP_MULTICAST is not set
CONFIG_IP_FIREWALL=y
# CONFIG_IP_FIREWALL_VERBOSE is not set
CONFIG_IP_MASQUERADE=y
CONFIG_IP_TRANSPARENT_PROXY=y
CONFIG_IP_ALWAYS_DEFRAG=y
# CONFIG_IP_ACCT is not set
CONFIG_IP_ROUTER=y
і в ipfwadm, поряд з іншими потрібними вам речами, прописуємо щось на кшталт:
ipfwadm-I-a accept-P tcp-D 208.206.76.44 80 # запобігаємо зациклення. тут 208.206.76.44 80 – адреса цієї машини
ipfwadm -I -a accept -P tcp -D 0/0 80 -r 3128
Для ядер 2.2.х все це господарство буде виглядати приблизно так:
Збираємо ядро ​​з підтримкою наступного:
[*] Network firewalls
[ ] Socket Filtering
[*] Unix domain sockets
[*] TCP/IP networking
[ ] IP: multicasting
[ ] IP: advanced router
[ ] IP: kernel level autoconfiguration
[*] IP: firewalling
[ ] IP: firewall packet netlink device
[*] IP: always defragment (required for masquerading)
[*] IP: transparent proxy support
Ланцюжок ipchains, що відповідає за переадресацію веб-трафіку користувачів на веб-проксі, може виглядати так:
/sbin/ipchains -A input -p tcp -s 10.0.3.22/16 -d 0/0 80 -j REDIRECT 8081
Ну ось, загалом і в цілому все. За подробицями звертайтеся до відповідних HOWTO та man’ам, в першу чергу по ipfwadm, ipchains, squid, наприклад, до
www.squid-cache.org/Doc/FAQ/ , Звідки і була почерпнута значна частина інформації цього післямови 😉

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*