Alterando a Rota Padrão do Squid com Iptables

Category : Linux, Roteamento

Hoje resolvi sujar as mãos um pouquinho e resolver um problema pertinente lá na empresa: fazer com que o Squid utilize uma rota alternativa a rota padrão do gateway. Temos dois links de internet conectados ao gateway e queriamos definir as rotas de acordo com o tráfego. O problema era o tráfego gerado pelo próprio gateway, como o Proxy, DNS e Atualização do DNS dinâmico com ddclient.

Vasculhando um pouco pelo google achei uma alternativa interessante, que seria usar o módulo owner do iptables para marcar o tráfego vindo do usuário proxy (usamos Debian no gateway) para uma tabela de roteamento alternativa.

Diagrama do Gateway

Diagrama do Gateway

O script requer o pacote iproute2 instalado, bem como o Squid já configurado.

A tabela de Roteamento

Nosso gateway padrão atualmente é 192.168.15.254, na subrede 192.168.15.0/24. Com a função set_route() é criada uma nova tabela de roteamento com identificação numérica armazenada na variável $TABELA.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
declare LAN="192.168.1.0/24"
declare WAN="10.0.0.0/24"
declare IFLAN="eth0"
declare IFWAN="eth2"
declare GATEWAY="10.0.0.254"
declare TABELA="100"

declare IPROUTE="/sbin/ip route"

#Cria a tabela de roteamento alternativa com o iproute
function set_route() {
    $IPROUTE add $LAN dev $IFLAN table $TABELA
    $IPROUTE add $WAN dev $IFWAN table $TABELA
    $IPROUTE add default via $GATEWAY dev $IFWAN table $TABELA
    $IPROUTE flush cache
}

As Regras de Roteamento

A função set_rule() primeiro marca os pacotes oriundos do usuário proxy usando os matchers MARK e CONMARK. Em seguida é criada uma regra de roteamento para capturar os pacotes marcados e roteá-los através da nova tabela.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
declare IPTABLES="/sbin/iptables"
declare IPRULE="/sbin/ip rule"

#Cria as regras para o trafego que utilizara a tabela de roteamento alternativa
function set_rule() {
    $IPTABLES -t mangle -A PREROUTING -j CONNMARK --restore-mark   

    #A regra que marca o trafego gerado pelo usuario do proxy
    $IPTABLES -t mangle -A OUTPUT -m owner --uid-owner proxy -j MARK --set-mark $TABELA

    $IPTABLES -t mangle -A POSTROUTING -o $IFWAN -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -A POSTROUTING -j CONNMARK --save-mark

    #A regra que captura os pacotes marcados e os insere na nova tabela
    $IPRULE add fwmark $TABELA table $TABELA
}

Você pode ampliar as regras como, por exemplo, fazer com que todo tráfego pop3 e smtp sejam roteados através da nova tabela.

1
2
    $IPTABLES -t mangle -A PREROUTING -p TCP --dport smtp -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -A PREROUTING -p TCP --dport pop3 -j MARK --set-mark $TABELA

Juntando tudo

Se você já possui mais de uma tabela de roteamento configurada com o iproute basta adaptar o script conforme a sua necessidade.

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/bin/bash
# Desctiption: Script de roteamendo avancado
# Author: Fabiano Sobreira

#Variaveis
declare LAN="192.168.1.0/24"
declare WAN="10.0.0.0/24"
declare IFLAN="eth0"
declare IFWAN="eth2"
declare GATEWAY="10.0.0.254"
declare TABELA="100"

declare IPTABLES="/sbin/iptables"
declare IPROUTE="/sbin/ip route"
declare IPRULE="/sbin/ip rule"

#Cria a tabela de roteamento alternativa com o iproute
function set_route() {
    $IPROUTE add $LAN dev $IFLAN table $TABELA
    $IPROUTE add $WAN dev $IFWAN table $TABELA
    $IPROUTE add default via $GATEWAY dev $IFWAN table $TABELA
    $IPROUTE flush cache
}

function unset_route() {
    $IPROUTE flush table $TABELA
}

#Cria as regras para o trafego que utilizara a tabela de roteamento alternativa
function set_rule() {
    $IPTABLES -t mangle -A PREROUTING -j CONNMARK --restore-mark   

    #A regra que marca o trafego gerado pelo usuario do proxy
    $IPTABLES -t mangle -A OUTPUT -m owner --uid-owner proxy -j MARK --set-mark $TABELA

    #Regras que marcam o trafego smtp e pop3
    $IPTABLES -t mangle -A PREROUTING -p TCP --dport smtp -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -A PREROUTING -p TCP --dport pop3 -j MARK --set-mark $TABELA

    $IPTABLES -t mangle -A POSTROUTING -o $IFWAN -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -A POSTROUTING -j CONNMARK --save-mark

    #A regra que captura os pacotes marcados e os insere na nova tabela
    $IPRULE add fwmark $TABELA table $TABELA
}

function unset_rule() {
    $IPTABLES -t mangle -D PREROUTING -j CONNMARK --restore-mark
    $IPTABLES -t mangle -D OUTPUT -m owner --uid-owner proxy -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -D PREROUTING -p TCP --dport smtp -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -D PREROUTING -p TCP --dport pop3 -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -D PREROUTING -p TCP --dport imap -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -D POSTROUTING -o $IFWAN -j MARK --set-mark $TABELA
    $IPTABLES -t mangle -D POSTROUTING -j CONNMARK --save-mark
    $IPRULE del fwmark $TABELA table $TABELA
}

function do_start() {
    set_route
    set_rule
}

function do_stop() {
    unset_rule
    unset_route
}

case $1 in
    start)
        printf "%s\n" "Iniciando o roteamento"
        do_start
        exit
    ;;
    stop)
        printf "%s\n" "Parando o roteamento"
        do_stop
        exit
    ;;
    restart)
        printf "%s\n" "Reiniciando o roteamento"
        do_stop
        do_start
        exit
    ;;
    *)
        printf "%s\n" "Uso: ${SCRIPT} (start|stop|restart)"
        exit
    ;;
esac

Links Sobre o Assunto

Linux Advanced Routing & Traffic Control
Linux Packet Filtering and Iptables

Comments (4)

Leia no meu Blog: Alterando a Rota Padrão do #Squid com #Iptables http://goo.gl/fb/Hmmr #linux #roteamento #iproute

obs. uso squid como proxy e gt e uso marcacao para controlar banda com htb, a pergunta e se esse script poderar ser adaptado para trabalhar com conjunto com o squid+htb

É possível sim, mas vai precisar de algumas alterações nos scripts. Se quiser podemos trocar algumas idéias pelo email blog at sobreira.eti.br

Muito obrigado amigo por responder minha questao,

se nao for muito incomodo, poderia-mos trocar informaçoes a respeito do assunto, aqui tenho alguns script 100% funcionais. acredito que com pouca coisa poderemos resolver, ja que tenho um conhecimento razoavel sobre o assunto

um abraço
msn chikinho_bb@hotmail,com
email

Post a comment