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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN" "http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:its="http://www.w3.org/2005/11/its" version="5.0" xml:lang="pt_BR">
<info><title>Pontes de Filtragem (Filtering Bridges)</title>
<authorgroup>
<author><personname><firstname>Alex</firstname><surname>Dupre</surname></personname><affiliation> <address><email>ale@FreeBSD.org</email></address> </affiliation></author>
</authorgroup>
<legalnotice xml:id="trademarks" role="trademarks">
<para>FreeBSD is a registered trademark of the FreeBSD Foundation.</para>
<para>3Com and HomeConnect are registered trademarks of 3Com Corporation.</para>
<para>Intel, Celeron, Centrino, Core, EtherExpress, i386, i486, Itanium, Pentium, and Xeon are trademarks or registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries.</para>
<para>Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this document, and the FreeBSD Project was aware of the trademark claim, the designations have been followed by the <quote>™</quote> or the <quote>®</quote> symbol.</para>
</legalnotice>
<pubdate>$FreeBSD$</pubdate>
<releaseinfo>$FreeBSD$</releaseinfo>
<abstract>
<para>Geralmente, é útil dividir uma rede física (como uma Ethernet) em dois segmentos separados, sem precisar criar sub-redes, e usar um roteador para vinculá-los. O dispositivo que conecta as duas redes dessa maneira é chamado de ponte (bridge). Um sistema FreeBSD com duas interfaces de rede é suficiente para atuar como uma ponte.</para>
<para>Uma ponte funciona examinando os endereços do nível <acronym>MAC</acronym> (endereços Ethernet) dos dispositivos conectados a cada uma de suas interfaces de rede e encaminhando o tráfego entre as duas redes apenas se a origem e o destino estiverem em diferentes segmentos. Sob muitos pontos de vista, uma ponte é semelhante a um switch Ethernet com apenas duas portas.</para>
</abstract>
</info>
<sect1 xml:id="filtering-bridges-why">
<title>Por que usar uma ponte de filtragem?</title>
<para>Cada vez mais frequentemente, graças aos custos reduzidos de conexões de banda larga à Internet (xDSL) e também devido à redução de endereços IPv4 disponíveis, muitas empresas estão conectadas à Internet 24 horas por dia e com poucos (às vezes nem mesmo 2) endereços IP. Nestas situações, geralmente é desejável ter um firewall que filtre o tráfego de entrada e de saída de e para a Internet, mas uma solução de filtragem de pacotes baseada em roteador pode não ser aplicável, quer seja devido a problemas de sub-redes, quer seja porque o roteador é de propriedade do provedor de conectividade (<acronym>ISP</acronym>), ou porque ele não suporta tais funcionalidades. Nestes cenários, o uso de uma ponte de filtragem é altamente recomendado.</para>
<para>Um firewall baseado em uma ponte de filtragem pode ser configurado e inserido entre o roteador xDSL e seu hub/switch Ethernet sem causar nenhum problema de numeração IP.</para>
</sect1>
<sect1 xml:id="filtering-bridges-how">
<title>Como instalar</title>
<para>Adicionar funcionalidades de bridge a um sistema FreeBSD não é difícil. Desde a versão 4.5 é possível carregar tais funcionalidades como módulos ao invés de ter que reconstruir o kernel, simplificando bastante o procedimento. Nas subseções seguintes, explicarei as duas formas de instalação.</para>
<important>
<para><emphasis>Não</emphasis> siga as duas instruções: um procedimento <emphasis>exclui</emphasis> o outro. Selecione a melhor opção de acordo com suas necessidades e habilidades.</para>
</important>
<para>Antes de continuar, certifique-se de ter pelo menos duas placas Ethernet compatíveis com o modo promíscuo para recepção e transmissão, pois elas devem ser capazes de enviar pacotes Ethernet com qualquer endereço, não apenas o deles. Além disso, para ter uma boa taxa de transferência, as placas devem ser placas do barramento PCI. As melhores opções ainda são as Intel <trademark>EtherExpress</trademark> Pro, seguido pela série <trademark class="registered">3Com</trademark> 3c9xx. Para simplificar a configuração do firewall, pode ser útil ter duas placas de diferentes fabricantes (usando drivers diferentes) para distinguir claramente qual interface está conectada ao roteador e qual está conectada à rede interna.</para>
<sect2 xml:id="filtering-bridges-kernel">
<title>Configuração do Kernel</title>
<para>Então você decidiu usar o método de instalação mais antigo, e também o mais bem testado. Para começar, você precisa adicionar as seguintes linhas ao seu arquivo de configuração do kernel:</para>
<programlisting>options BRIDGE
options IPFIREWALL
options IPFIREWALL_VERBOSE</programlisting>
<para>A primeira linha adiciona o suporte para o serviço de ponte (bridge), a segunda adiciona o suporte ao firewall e a terceira é referente as funções de registro do firewall.</para>
<para>Agora é necessário compilar e instalar o novo kernel. Você pode encontrar instruções detalhadas na seção <link xlink:href="@@URL_RELPREFIX@@/doc/en_US.ISO8859-1/books/handbook/kernelconfig-building.html">Compilando e Instalando um Kernel Personalizado</link> do Handbook do FreeBSD.</para>
</sect2>
<sect2 xml:id="filtering-bridges-modules">
<title>Carregamento de módulos</title>
<para>Se você escolheu usar o método de instalação mais novo e mais simples, a única coisa a fazer agora é adicionar a seguinte linha ao <filename>/boot/loader.conf</filename>:</para>
<programlisting>bridge_load="YES"</programlisting>
<para>Desta forma, durante a inicialização do sistema, o módulo <filename>bridge.ko</filename> será carregado junto com o kernel. Não é necessário adicionar uma linha semelhante para o módulo <filename>ipfw.ko</filename>, pois ele será carregado automaticamente após a execução das etapas na seção a seguir.</para>
</sect2>
</sect1>
<sect1 xml:id="filtering-bridges-finalprep">
<title>Preparação final</title>
<para>Antes de reinicializar para carregar o novo kernel ou os módulos requeridos (de acordo com o método de instalação escolhido anteriormente), você deve fazer algumas alterações no arquivo de configuração <filename>/etc/rc.conf</filename>. A regra padrão do firewall é rejeitar todos os pacotes IP. Inicialmente vamos configurar um firewall <option>open</option> (aberto), a fim de verificar sua operação sem qualquer problema relacionado à filtragem de pacotes (no caso de você executar este procedimento remotamente, tal configuração evitará que você permaneça isolado da rede). Coloque estas linhas no <filename>/etc/rc.conf</filename>:</para>
<programlisting>firewall_enable="YES"
firewall_type="open"
firewall_quiet="YES"
firewall_logging="YES"</programlisting>
<para>A primeira linha ativará o firewall (e carregará o módulo <filename>ipfw.ko</filename> se ele não estiver compilado no kernel), a segunda irá configurá-lo no modo <option>open</option> (como explicado em <filename>/etc/rc.firewall</filename>), a terceira para não mostrar o carregamento de regras e a quarta para ativar o suporte aos logs.</para>
<para>Sobre a configuração das interfaces de rede, a maneira mais usada é atribuir um IP a apenas uma das placas de rede, mas a ponte funcionará igualmente, mesmo que ambas as interfaces ou nenhuma tenha um IP configurado. No último caso (IP-less) a máquina bridge ficará ainda mais oculta, e também inacessível pela rede: para configurá-la será necessário efetuar o login a partir do console ou através de uma terceira interface de rede separada da ponte. Às vezes, durante a inicialização do sistema, alguns programas exigem acesso à rede, digamos, para resolução de nomes de domínio: neste caso, é necessário atribuir um IP à interface externa (aquela conectada à Internet, onde o servidor <acronym>DNS</acronym> se encontra), uma vez que a ponte será ativada no final do procedimento de inicialização. Isso significa que a interface <filename>fxp0</filename> (no nosso caso) deve ser mencionada na seção ifconfig do arquivo <filename>/etc/rc.conf</filename>, enquanto o <filename>xl0</filename> não é. Atribuir um IP a ambas as placas de rede não faz muito sentido, a menos que, durante o procedimento de inicialização, os aplicativos acessem os serviços em ambos os segmentos de Ethernet.</para>
<para>Há outra coisa importante a saber. Ao executar o IP sobre Ethernet, existem dois protocolos Ethernet em uso: um é o IP, o outro é o <acronym>ARP</acronym>. O <acronym>ARP</acronym> faz a conversão do endereço IP de um host em seu endereço Ethernet (camada <acronym>MAC</acronym>). Para permitir a comunicação entre dois hosts separados pela ponte, é necessário que a ponte envie pacotes <acronym>ARP</acronym>. Esse protocolo não está incluído na camada IP, uma vez que ele existe apenas com IP sobre Ethernet. O firewall do FreeBSD filtra exclusivamente na camada IP e, portanto, todos os pacotes não-IP (<acronym>ARP</acronym> incluso) serão encaminhados sem serem filtrados, mesmo que o firewall esteja configurado para não permitir nada.</para>
<para>Agora é hora de reiniciar o sistema e usá-lo como antes: haverá algumas novas mensagens sobre a ponte e o firewall, mas a ponte não será ativada e o firewall, estando no modo <option>open</option>, não evitará operações.</para>
<para>Se houver algum problema, você deve resolvê-los agora antes de prosseguir.</para>
</sect1>
<sect1 xml:id="filtering-bridges-enabling">
<title>Habilitando a ponte</title>
<para>Neste ponto, para habilitar a ponte, você tem que executar os seguintes comandos (tendo a perspicácia para substituir os nomes das duas interfaces de rede <filename>fxp0</filename> e <filename>xl0</filename> com as suas próprias):</para>
<screen><prompt>#</prompt> <userinput>sysctl net.link.ether.bridge.config=fxp0:0,xl0:0</userinput>
<prompt>#</prompt> <userinput>sysctl net.link.ether.bridge.ipfw=1</userinput>
<prompt>#</prompt> <userinput>sysctl net.link.ether.bridge.enable=1</userinput></screen>
<para>A primeira linha especifica quais interfaces devem ser ativadas pela ponte, a segunda habilitará o firewall na ponte e, finalmente, a terceira habilitará a ponte.</para>
<note>
<para>Se você tem o FreeBSD 5.1-RELEASE ou anterior, as variáveis do sysctl são escritas de forma diferente. Veja <citerefentry><refentrytitle>bridge</refentrytitle><manvolnum>4</manvolnum></citerefentry> para detalhes.</para>
</note>
<para>Neste ponto você deve ser capaz de inserir a máquina entre dois conjuntos de hosts sem comprometer quaisquer habilidades de comunicação entre eles. Em caso afirmativo, o próximo passo é adicionar as partes <literal>net.link.ether.bridge.<replaceable>[blah]</replaceable>=<replaceable>[blah]</replaceable></literal> dessas linhas ao arquivo <filename>/etc/sysctl.conf</filename>, para que eles sejam executados na inicialização.</para>
</sect1>
<sect1 xml:id="filtering-bridges-ipfirewall">
<title>Configurando o Firewall</title>
<para>Agora é hora de criar seu próprio arquivo com regras de firewall personalizadas, a fim de proteger a rede interna. Haverá alguma complicação em fazer isso porque nem todas as funcionalidades do firewall estão disponíveis em pacotes em ponte. Além disso, há uma diferença entre os pacotes que estão sendo encaminhados e os pacotes que estão sendo recebidos pela máquina local. Em geral, os pacotes de entrada passam pelo firewall apenas uma vez, não duas vezes, como é normalmente o caso; na verdade eles são filtrados somente após o recebimento, portanto, as regras que usam <option>out</option> ou <option>xmit</option> nunca darão match. Pessoalmente, eu uso <option>in via</option> que é uma sintaxe antiga, mas uma que tem sentido quando você a lê. Outra limitação é que você está restrito a usar somente comandos <option>pass</option> ou <option>drop</option> para os pacotes filtrados por uma ponte. Coisas sofisticadas como <option>divert</option>, <option>forwar </option> ou <option>reject</option> não estão disponíveis. Essas opções ainda podem ser usadas, mas apenas no tráfego para ou a partir da própria máquina ponte (se ela tiver um endereço IP).</para>
<para>O conceito de filtragem stateful é novo no FreeBSD 4.0. Esta é uma grande melhoria para o tráfego <acronym>UDP</acronym>, que normalmente é um pedido que sai, seguido pouco depois por uma resposta com exatamente o mesmo conjunto de endereços IP e números de porta (mas com origem e destino invertidos, é claro). Para firewalls que não possuem manutenção de estado, quase não há como lidar com esse tipo de tráfego como uma sessão única. Mas com um firewall que pode <quote>lembrar</quote> de um pacote <acronym>UDP</acronym> de saída e, nos próximos minutos, permitir uma resposta, o manuseio de serviços <acronym>UDP</acronym> é trivial. O exemplo a seguir mostra como fazer isso. É possível fazer a mesma coisa com pacotes <acronym>TCP</acronym>. Isso permite que você evite alguns ataques de negação de serviço e outros truques desagradáveis, mas também faz com que sua tabela de estado cresça rapidamente em tamanho.</para>
<para>Vamos ver um exemplo de configuração. Note primeiro que no topo do <filename>/etc/rc.firewall</filename> já existem regras padrão para a interface de loopback <filename>lo0</filename>, então não devemos mais precisar delas. Regras customizadas devem ser colocadas em um arquivo separado (digamos, <filename>/etc/rc.firewall.local</filename>) e carregadas na inicialização do sistema, modificando a linha de <filename>/etc/rc.conf </filename> onde definimos o firewall <option>open</option>:</para>
<programlisting>firewall_type="/etc/rc.firewall.local"</programlisting>
<important>
<para>Você tem que especificar o caminho <emphasis>completo</emphasis>, caso contrário ele não será carregado com o risco de permanecer isolado da rede.</para>
</important>
<para>Para nosso exemplo, imagine ter a interface <filename>fxp0</filename> conectada para o exterior (Internet) e a <filename>xl0</filename> para o interior (<acronym>LAN</acronym>). A máquina ponte tem o IP <systemitem class="ipaddress">1.2.3.4</systemitem> (não é possível que o seu <acronym>ISP</acronym> possa lhe dar um endereço assim, mas para nosso exemplo ele é bom).</para>
<programlisting># Things that we have kept state on before get to go through in a hurry
add check-state
# Throw away RFC 1918 networks
add drop all from 10.0.0.0/8 to any in via fxp0
add drop all from 172.16.0.0/12 to any in via fxp0
add drop all from 192.168.0.0/16 to any in via fxp0
# Allow the bridge machine to say anything it wants
# (if the machine is IP-less do not include these rows)
add pass tcp from 1.2.3.4 to any setup keep-state
add pass udp from 1.2.3.4 to any keep-state
add pass ip from 1.2.3.4 to any
# Allow the inside hosts to say anything they want
add pass tcp from any to any in via xl0 setup keep-state
add pass udp from any to any in via xl0 keep-state
add pass ip from any to any in via xl0
# TCP section
# Allow SSH
add pass tcp from any to any 22 in via fxp0 setup keep-state
# Allow SMTP only towards the mail server
add pass tcp from any to relay 25 in via fxp0 setup keep-state
# Allow zone transfers only by the slave name server [dns2.nic.it]
add pass tcp from 193.205.245.8 to ns 53 in via fxp0 setup keep-state
# Pass ident probes. It is better than waiting for them to timeout
add pass tcp from any to any 113 in via fxp0 setup keep-state
# Pass the "quarantine" range
add pass tcp from any to any 49152-65535 in via fxp0 setup keep-state
# UDP section
# Allow DNS only towards the name server
add pass udp from any to ns 53 in via fxp0 keep-state
# Pass the "quarantine" range
add pass udp from any to any 49152-65535 in via fxp0 keep-state
# ICMP section
# Pass 'ping'
add pass icmp from any to any icmptypes 8 keep-state
# Pass error messages generated by 'traceroute'
add pass icmp from any to any icmptypes 3
add pass icmp from any to any icmptypes 11
# Everything else is suspect
add drop log all from any to any</programlisting>
<para>Aqueles de vocês que já configuraram firewalls antes podem notar algumas coisas que estão faltando. Em particular, não há regras anti-spoofing, na verdade nós <emphasis>não</emphasis> adicionamos:</para>
<programlisting>add deny all from 1.2.3.4/8 to any in via fxp0</programlisting>
<para>Ou seja, dropar os pacotes que estão vindo do lado de fora dizendo ser da nossa rede. Isso é algo que você normalmente faria para ter certeza de que alguém não tentaria escapar do filtro de pacotes, gerando pacotes nefastos que parecem ser de dentro. O problema é que existe <emphasis>pelo menos</emphasis> um host na interface externa que você não deseja ignorar: o roteador. Mas geralmente <acronym>ISP</acronym> tem anti-spoofs em seu roteador, então não precisamos nos incomodar muito.</para>
<para>A última regra parece ser uma duplicata exata da regra padrão, ou seja, não deixa passar nada que não seja especificamente permitido. Mas há uma diferença: todo tráfego suspeito será registrado.</para>
<para>Existem duas regras para passar o tráfego <acronym>SMTP</acronym> e o do <acronym>DNS</acronym> para o servidor de e-mail e o servidor de nomes, se você os tiver. Obviamente, todo o conjunto de regras deve ser definido de acordo com as suas preferências pessoais, isso é apenas um exemplo específico (o formato da regra é descrito com precisão na página de manual do <citerefentry><refentrytitle>ipfw</refentrytitle><manvolnum>8</manvolnum> </citerefentry>). Note que, para que o <quote>relay</quote> e o <quote>ns</quote> funcionem, as pesquisas de serviço de nomes devem funcionar <emphasis>antes</emphasis> da ponte ser ativada. Este é um exemplo de quando você precisa ter certeza de que definiu o IP na placa de rede correta. Como alternativa, é possível especificar o endereço IP em vez do nome do host (necessário se a máquina não tiver IP).</para>
<para>As pessoas que estão acostumadas a configurar firewalls provavelmente também estão acostumadas a ter uma regra <option>reset</option> ou <option>forward</option> para pacotes ident (<acronym>TCP</acronym> porta 113). Infelizmente, esta não é uma opção aplicável com a ponte, então o melhor é simplesmente passá-las ao seu destino. Enquanto essa máquina de destino não estiver executando um daemon ident, isso é relativamente inofensivo. A alternativa é descartar as conexões na porta 113, o que criará alguns problemas com serviços como por exemplo o <acronym>IRC</acronym> (o probe do ident irá dar timeout).</para>
<para>A única outra coisa que é um pouco estranha e que você pode ter notado é que existe uma regra para deixar a máquina ponte falar, e outra para os hosts internos. Lembre-se que isso ocorre porque os dois conjuntos de tráfego terão caminhos diferentes através do kernel e do filtro de pacotes. A rede interna passará pela ponte, enquanto a máquina local usará a pilha IP normal para falar. Assim, as duas regras lidam com casos diferentes. As regras <literal>in via fxp0</literal> funcionam nos dois caminhos. Em geral, se você usar as regras <option>in via</option> em todo o filtro, precisará abrir uma exceção para pacotes gerados localmente, porque eles não vieram em nenhuma de nossas interfaces.</para>
</sect1>
<sect1 xml:id="filtering-bridges-contributors">
<title>Colaboradores</title>
<para>Muitas partes deste artigo foram tiradas, atualizadas e adaptadas de um texto antigo sobre pontes, editado por Nick Sayer. Um par de inspirações deve-se a uma introdução sobre pontes de Steve Peterson.</para>
<para>Um grande obrigado ao Luigi Rizzo pela implementação do código de ponte (bridge) no FreeBSD e pelo tempo que ele dedicou a mim respondendo a todas as minhas perguntas relacionadas.</para>
<para>Agradeço também a Tom Rhodes, que olhou para o meu trabalho de tradução do italiano (a língua original deste artigo) para o inglês.</para>
</sect1>
</article>
|