Принудительное проксирование ipv6 трафика

Постановка задачи

Есть локальная сеть с IPv6. Есть маршрутизатор/фаервол на Linux и есть squid на отдельной машине, тоже под Linux.

Надо завернуть http трафик для IPv6 через сквид прозрачно для клиентов.

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

Общая идея

Поднимаем отдельный линк между маршрутизатором и прокси. Можно либо физически выделить по сетевому интерфейсу на каждой из машин, либо поднять отдельный VLAN.

Весь http-трафик из локальной сети на маршрутизаторе заворачиваем на прокси. Чтобы не было петли исключаем из этого процесса трафик, идущий со стороны прокси через выделенный линк.

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

+--------------+    +----------------------+    +-------------------+
|              |    |                      |    |                   |
|             <-----------+          +<----------+                  |
|    Client    |    |     |  Router  |     |    |    HTTP Server    |
|             +------->+  |          |  +-------->                  |
|              |    |  |  |          |  |  |    |                   |
+--------------+    +--|--|----------|--|--+    +-------------------+
                       |  |          |  |
                       |  |          |  |
                    +--|--|----------|--|--+
                    |  |  |          |  |  |
                    |  |  +<---------+  |  |
                    |  |      Proxy     |  |
                    |  +--------------->+  |
                    |                      |
                    +----------------------+

Настройки прокси

Настраиваем выделенный линк в сторону маршрутизатора

/etc/conf.d/net
vlans_eth0="4"
vlan4_name="eth0.0004"
 
config_eth0="null"
config_eth0_0004="172.17.4.5/24 2001:DB8:0002:0004::5/64" # proxy

Объясняем сквиду, что локальный IPv6 трафик надо отправлять с конкретного адреса, трафик от локальной сети надо маркировать и слушать на порту 3129. Что значит tproxy, смотрим в доке на сквид. :)

squid.conf
http_port 3129 tproxy
acl LAN6 src 2001:DB8:2::/48
tcp_outgoing_mark 0x5 LAN6
tcp_outgoing_address 2001:DB8:2:4::5

Готовим таблицы маршрутизации и политики

#Чистим
ip -6 route flush table 53
ip -6 route flush table 64
ip -6 rule del from all fwmark 0x5
ip -6 rule del from all fwmark 0x6
 
#Это таблица для исходящих пакетов от сквида
ip -6 route add default via 2001:DB8:2:4::1 dev eth0.0004 table 53
ip -6 rule add from all fwmark 0x5 lookup 53
 
#Это таблица для входящих пакетов, которые надо завернуть на сквид
ip -6 route add local default dev lo table 64
ip -6 rule add from all fwmark 0x6 lookup 64

Настраиваем iptables

ip6tables -t mangle -N divert
ip6tables -t mangle -A divert -j MARK --set-mark 0x6
ip6tables -t mangle -A divert -j ACCEPT
 
ip6tables -t mangle -A PREROUTING -p TCP -m socket -j divert
ip6tables -t mangle -A PREROUTING -p TCP -i eth0.0004 \
                -j TPROXY --tproxy-mark 0x6 --on-port 3129

Суть происходящего:

  1. Входящий пакет проверяется на принадлежность к уже открытым сокетам. Если данный пакет принадлежит уже установленному соединению, и сокет уже существует, мы маркируем пакет и прерываем просмотр цепочки PREROUTING. Иначе проверяем, что пакет пришёл от маршрутизатора по выделенному линку. Если это так, мы его маркируем и отправляем на порт 3129.
  1. На этапе принятия решения о маршрутизации срабатывает правило from all fwmark 0x6 lookup 64, и пакет попадает в таблицу 64, в результате чего попадает на сквид. Сквид создаёт своё соединение с HTTP-сервером, для чего отправляет пакет с меткой 5. Через правило from all fwmark 0x5 lookup 53 пакет попадает в таблицу 53 и уходит на маршрутизатор через выделенный линк.

Настройки маршрутизатора

Настраиваем выделенный линк в сторону прокси сервера

/etc/conf.d/net
vlans_eno2="4"
vlan4_name="eno2.0004"
config_eno2="null"
config_eno2_0004="172.17.4.1/24 2001:DB8:0002:0004::1/64" # выделенный VLAN для прозрачного проксирования

Готовим сет с номерами портов, которые надо проксировать:

ipset -! destroy ip6_proxying_port_list
ipset -! create  ip6_proxying_port_list bitmap:port range 1-65535
ipset    flush   ip6_proxying_port_list
 
ipset -! add     ip6_proxying_port_list       80
ipset -! add     ip6_proxying_port_list       81
ipset -! add     ip6_proxying_port_list       85
ipset -! add     ip6_proxying_port_list       88
ipset -! add     ip6_proxying_port_list     8000
ipset -! add     ip6_proxying_port_list     8001
ipset -! add     ip6_proxying_port_list     8080
ipset -! add     ip6_proxying_port_list     8081
ipset -! add     ip6_proxying_port_list     8101
ipset -! add     ip6_proxying_port_list     8108
ipset -! add     ip6_proxying_port_list     8888
ipset -! add     ip6_proxying_port_list     9080

Готовим таблицу маршрутизации и политики

#Чистим
ip -6 route flush table 106
ip -6 rule del fwmark 0x6 2> /dev/null
 
 
#Это таблица перенаправления трафика на сквид
ip -6 route add 2000::/3 via 2001:DB8:2:4::5 dev eno2.0004 table 106
ip -6 rule add fwmark 0x6 priority 106 lookup 106

Настраиваем iptables

ip6tables -t mangle  -A PREROUTING  -p TCP \
        ! -i eno2.0004 \
        -m set ! --match-set "ip6_all_vlans"  dst \
        -m set   --match-set "ip6_proxying_port_list" dst \
                -j MARK --set-mark 0x6
 
ip6tables -t mangle  -A PREROUTING  -p TCP \
        ! -i eno2.0004 \
        -m set ! --match-set "ip6_all_vlans"  src \
        -m set   --match-set "ip6_proxying_port_list" src \
                -j MARK --set-mark 0x6

Суть происходящего:

  • игнорируем пакеты со стороны прокси
  • если пакет идет во внешний мир (не в локальные сети) и его dst-порт подлежит обязательному проксированию ставим метку
  • если пакет идет из внешнего мира (не из локальных сетей) и его src-порт подлежит обязательному проксированию ставим метку
  • отмеченные пакеты через политику fwmark 0x6 priority 106 lookup 106 попадают в таблицу 106 и сливаются на прокси

Кроме того, надо настроить FORWARD правила (выдержка, разумеется):

ip6tables -N forward_conntrack_check
ip6tables -N forward_tcp_packets
 
echo    "                forward_conntrack_check"
ip6tables -A forward_conntrack_check           -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A forward_conntrack_check   -p TCP  -m conntrack --ctstate INVALID  -m set --match-set "ip6_proxying_port_list" dst  -j RETURN
ip6tables -A forward_conntrack_check   -p TCP  -m conntrack --ctstate INVALID  -m set --match-set "ip6_proxying_port_list" src  -j RETURN
ip6tables -A forward_conntrack_check           -m conntrack --ctstate INVALID             -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "INVALID ctstate: "
ip6tables -A forward_conntrack_check           -m conntrack --ctstate INVALID             -j DROP
 
 
echo    "                forward_tcp_packets"
# ОТ НАС В ТЫРНЕТ
# 1. LAN во внешний мир
ip6tables -A forward_tcp_packets -p TCP -m set --match-set "ip6_lan_2_inet_tcp"            src,dst     -j allowed_tcp_packets
# 2. Сервера во внешний мир
ip6tables -A forward_tcp_packets -p TCP -m set --match-set "ip6_servers_2_inet_tcp"        src,dst     -j allowed_tcp_packets
 
#######################################################################
#
##  FORWARD.
#
#######################################################################
 
#Проверяем чёрный список
ip6tables -A FORWARD -p ALL -m set --match-set "ip6_black_list"        src -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "SRC black-listed: "
ip6tables -A FORWARD -p ALL -m set --match-set "ip6_black_list"        src -j DROP
ip6tables -A FORWARD -p ALL -m set --match-set "ip6_black_list"        dst -m limit --limit 3/minute --limit-burst 3 -j LOG --log-prefix "DST black-listed: "
ip6tables -A FORWARD -p ALL -m set --match-set "ip6_black_list"        dst -j DROP
 
#Принимаем установленные соединения и чистим мусор
ip6tables -A FORWARD -p ALL  -j forward_conntrack_check
ip6tables -A FORWARD -p TCP  -j bad_tcp_packets
 
#Выпускаем всех из белого списка
ip6tables -A FORWARD -p ALL -m set --match-set "ip6_white_list_2_inet" src -j ACCEPT
 
#Проверяем и принимаем лигитимный трафик
ip6tables -A FORWARD -p TCP    -j forward_tcp_packets

Сеты ip6_lan_2_inet_tcp и ip6_servers_2_inet_tcp содержат пары (адрес локальной сети; номер порта). Порты, подлежащие принудительному проксированию, также должны быть указаны и в данных сетах.

Коннекшен трекер ломается на проксируемых соединениях, поэтому мы исключаем их из проверки.


net/принудительное_проксирование_ipv6_трафика.txt · Последние изменения: 2016-05-06 02:07 — Andrew A. Sabitov