среда, 19 ноября 2014 г.

Apache как reverse proxy

Предположим, получилась такая забавная ситуация. Пусть у нас есть сеть A и сеть B, причем из сети B компьютеры, принадлежащие сети A, не видны. Кроме того, есть один компьютер, AB-proxy, который виден из обеих сетей (например, на этом компьютере стоят две сетевые карты с адресами, соответственно, AB-proxy-ipA и AB-proxy-ipB). Предположим также, что в сети A завёлся веб-сервер A-server, к которому позарез нужно достучаться пользователям из сети В. Как это сделать?

Первый, и, наверно, лучший вариант решения - поднимаем на AB-proxy какой-нибудь прокси, например, squid, прописываем его в браузерах пользователей из сети B, и пусть гуляют в сеть A через него. Единственная проблема - а если пользователи сети B не позволят копаться в настройках своих браузеров?

Поэтому можно попробовать второй вариант решения: настроить iptables на AB-proxy. Достаточно нескольких строчек:
# очищаем ранее настроенные цепочки правил
iptables -F -t filter
iptables -X -t filter
iptables -F -t nat
iptables -X -t nat

# добавляем новую цепочку правил
iptables -t filter -A INPUT       -d AB-proxy-ipB -p tcp -dport 8080 -j ACCEPT
iptables -t nat    -A PREPOUTING  -d AB-proxy-ipB -p tcp -dport 8080 -j DNAT   --to-destination A-server-ip:80
iptables -t nat    -A POSTROUTING -d A-server-ip  -p tcp -dport 80   -j DNAT   --to-source      AB-proxy-ipA
Тогда при попытке зайти на адрес http://AB-proxy-ipB:8080 очередной tcp-пакет превратится в пакет от AB-proxy-ipA для A-server-ip:80 и успешно дойдет до сервера.

Этот вариант хорош, однако и тут есть большой подводный камень: а что, если коварный веб-сервер A-server любит прописывать своё имя во всяких тэгах <a>, <img> и вообще указывает себя явно в куках и разнообразных редиректах?

И тогда на помощь приходит третий вариант: поднять на AB-proxy обратный прокси. В нашем случае под рукой оказался Apache 2.2, и было решено воспользоваться им.

В httpd.conf раскомментируем (или добавим) следующее:
Listen 8080

LoadModule headers_module modules/mod_headers.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule substitute_module modules/mod_substitute.so

ProxyRequests off
<Proxy *>
 Order deny,allow
 Allow from all
</Proxy>

ProxyPassMatch ^/(.*)$ http://A-server/$1
ProxyPassReverse / http://AB-proxy-ipB:8080/

Header edit Location ^http://A-server/ http://AB-proxy-ipB:8080/
Header edit Set-Cookie Domain=A-server Domain=AB-proxy-ipB

AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|A-server/|AB-proxy-ipB:8080/|i"

В результате пользователи сети B заходя на адрес http://AB-proxy-ipB:8080 будут попадать на сервер A-server, а ответы этого сервера станут проверяться на предмет наличия в них его имени, которое будет заменяться на имя прокси.

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

Отправить комментарий