Introdução
Nessa segunda parte do artigo vou mostrar como criar um shell script usando o iptables para filtragem de pacotes e CBQ para controle de banda.
O script está fácil de entender e sua utilização é bem simples. É necessário criar um arquivo texto contento informações sobre cada máquina cliente que possui acesso à internet. Informações como IP, MAC, Download, Upload, se vai passar pelo Squid e se está bloqueado o acesso. Com base nestas informações, o script cria as regras no firewall bloqueando ou liberando acessos, amarrando IP ao endereço MAC, faz proxy transparente e determina qual a velocidade de download e upload para cada um. Fora isso, é criado o arquivo /etc/dhcpd.con usado pelo servidor DHCP associando o IP ao seu MAC, fazendo com que um cliente obtenha sempre o mesmo IP.
Firewall e Controle de Banda
É recomendado um conhecimento básico sobre Linux e Shell Script para bom entendimento do código.
#!/bin/bash ARQUIVO="/var/www/bandcontrol/scripts/pontosderede.txt" # Contem os pontos de rede cadastrados MOD=$(which modprobe) # Comando para carregar modulos do kernel IPT=$(which iptables) # Caminho do iptables TC=$(which tc) # tc (pacote iproute2) I_WAN="eth0" # Interface internet I_LAN1="eth1" # Interface Rede local GATEWAY_IP="192.168.254.254" NETMASK="255.255.255.0" CLASSE_LAN1="192.168.254" # Classe de IP utilizada na rede local. Ex.: 10.0 PROXY_SERVER="$GATEWAY_IP:3128" # O proprio gateway tambem roda o Squid na porta 3128 DHCPD_DAEMON="/etc/init.d/dhcp3-server" # Executavel do dhcpd server DHCPDCONF="/etc/dhcp3/dhcpd.conf" # Arquivo de configuracao do dhcpd DOMINIO="gustavohenrique.net" # Dominio ao qual a rede faz parte DNS_SERVERS="$GATEWAY_IP, 8.8.8.8, 4.2.2.2" # Servidores DNS. O primeiro é o próprio gateway # Remove o controle de banda function parar_controle_de_banda { $TC qdisc del dev $I_LAN1 root $TC qdisc del dev $I_WAN root } # Cria as regras iniciais para controle de banda function iniciar_controle_de_banda { # Remove as regras do controle de banda parar_controle_de_banda # Download $TC qdisc add dev $I_LAN1 root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8 $TC class change dev $I_LAN1 root cbq weight 10Mbit allot 1514 # Upload $TC qdisc add dev $I_WAN root handle 1 cbq bandwidth 100Mbit avpkt 1000 cell 8 $TC class change dev $I_WAN root cbq weight 10Mbit allot 1514 # Cache Full. Pacotes marcados com TOS 60 vao para a classe 1:9999 cuja banda é 100 Mbit (rede ethernet) $TC class add dev $I_LAN1 parent 1: classid 1:9999 cbq bandwidth 100Mbit rate 100Mbit weight 10Mbit prio 4 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded $TC filter add dev $I_LAN1 parent 1:0 protocol ip prio 3 u32 match ip protocol 0x6 0xff match ip tos 60 0xff classid 1:9999 } # Limpa o firewall function parar_firewall() { # Configura a politca padrao para aceitar tudo $IPT -P INPUT ACCEPT $IPT -P OUTPUT ACCEPT $IPT -P FORWARD ACCEPT $IPT -t nat -P PREROUTING ACCEPT # Limpa a tabela netfilter $IPT -F $IPT -X $IPT -t nat -F $IPT -t nat -X $IPT -t mangle -F $IPT -t mangle -X } # Cria as regras de firewall function iniciar_firewall() { # Finaliza o script se nao existir o arquivo contendo os pontos de rede if [ ! -f $ARQUIVO ]; then echo "Arquivo contendo os pontos de rede ($ARQUIVO) nao existe."; exit 0 fi # Carrega modulos do iptables $MOD ip_tables $MOD iptable_nat $MOD ipt_MASQUERADE $MOD ipt_LOG $MOD ipt_REJECT $MOD ip_conntrack_ftp $MOD ip_nat_ftp # Limpa todas as regras do firewall parar_firewall # Recria as regras para controle de banda iniciar_controle_de_banda # Por padrao bloqueia tudo que for entrar no firewall $IPT -P INPUT DROP $IPT -t nat -P PREROUTING DROP # Habilita redirecionamento de pacotes para compartilhar internet echo 1 > /proc/sys/net/ipv4/ip_forward # Aumenta o limite do nf_conntrack_max echo 99999 > /proc/sys/net/netfilter/nf_conntrack_max # Libera acesso para pacotes vindos da internet (CUIDADO) $IPT -t nat -A PREROUTING -s 0/0 -i $I_WAN -p all -j ACCEPT $IPT -A INPUT -i $I_WAN -j ACCEPT # Cria uma nova chain para tratar do proxy transparente $IPT -t nat -N proxy # O software conectividade social da Caixa Economica nao funciona se # estiver passando pelo proxy. Tudo que for destinado ao IP da Caixa # nao vai passar pelo proxy $IPT -t nat -A proxy -p tcp -d 200.201.174.0/16 --dport 80 -j ACCEPT $IPT -t nat -A proxy -p tcp -d 200.201.173.0/16 --dport 80 -j ACCEPT $IPT -t nat -A proxy -p tcp -d 200.201.0.0/16 --dport 80 -j ACCEPT $IPT -t nat -A proxy -p tcp -d 200.201.174.207 --dport 80 -j ACCEPT # Internet Caixa nao passa pelo proxy $IPT -t nat -A proxy -p tcp -d 200.201.169.0/8 --dport 80 -j ACCEPT $IPT -t nat -A proxy -p tcp -d 200.201.169.69 --dport 80 -j ACCEPT # Esse servidor tambem roda o Apache na port 80. Nao quero que as # paginas locais passem pelo proxy, pois assim posso controlar a banda # de pacotes vindos do apache definindo a velocidade máxima da rede $IPT -t nat -A proxy -p tcp -d $GATEWAY_IP --dport 80 -j ACCEPT # Proxy transparente redirecionando os pacotes para a porta do Squid $IPT -t nat -A proxy -s 0/0 -p tcp --dport 80 -j DNAT --to-dest $PROXY_SERVER # Se o pacote nao for pra porta 80 (não é navegação), deixa passar $IPT -t nat -A proxy -i $I_LAN1 -j ACCEPT # Libera o IP abaixo sem amarrar com MAC e sem passar pelo proxy #$IPT -t nat -A PREROUTING -i $I_LAN1 -s 192.168.254.2 -j ACCEPT # Configuracao inicial do dhcpd.conf. Distribuicao de IPs na faixa 192.168.254.80 a 192.168.254.90 echo "# Arquivo dhcpd.conf criado pelo BandControl" > $DHCPDCONF echo "ddns-update-style none;" >> $DHCPDCONF echo "option domain-name \"$DOMINIO\";" >> $DHCPDCONF echo "option domain-name-servers $DNS_SERVERS;" >> $DHCPDCONF echo "default-lease-time 600;" >> $DHCPDCONF echo "max-lease-time 7200;" >> $DHCPDCONF echo "authoritative;" >> $DHCPDCONF echo "shared-network 0-2 {" >> $DHCPDCONF echo " subnet $CLASSE_LAN1"."0 netmask $NETMASK { range $CLASSE_LAN1.80 $CLASSE_LAN1.90; }" >> $DHCPDCONF echo "}" >> $DHCPDCONF # Inicio do loop para liberacao e bloqueio de clientes. # O formato do arquivo é: codigo_identificador-descricao-ip-mac-download-upload-liberado-proxy # Ex.: 1-gustavo_henrique_notebook-192.168.254.10-512-256-S-S # Acesso liberado e uso do proxy sao valores que devem ser True ou False for i in `cat $ARQUIVO`; do CODIGO=$(echo $i | awk -F "-" {'print $1'}) # Numero usado como identificador no controle de banda IP=$(echo $i | awk -F "-" {'print $3'}) # IP MAC=$(echo $i | awk -F "-" {'print $4'}) # MAC em letras minusculas e separado por dois pontos (:) DOWNLOAD=$(echo $i | awk -F "-" {'print $5'}) # Numero correspondente a velocidade de download em Kbit UPLOAD=$(echo $i | awk -F "-" {'print $6'}) # Numero correspondente a velocidade de upload em Kbit POSSUI_ACESSO_LIBERADO=$(echo $i | awk -F "-" {'print $7'}) # True para sim, False para bloquear o acesso VAI_USAR_PROXY=$(echo $i | awk -F "-" {'print $8'}) # True para usar o proxy, False para não usar # Configurar dhcpd para associar IP ao MAC if [ "$MAC" != "" ]; then LINHA="host $CODIGO { hardware ethernet $MAC; fixed-address $IP; option subnet-mask $NETMASK; option routers $GATEWAY_IP; option domain-name-servers $DNS_SERVERS; }" echo $LINHA >> $DHCPDCONF fi # Se o IP nao esta liberado, bloqueia no firewall if [ "$POSSUI_ACESSO_LIBERADO" == "False" ]; then EXECUTAR_REGRA="$IPT -t nat -A PREROUTING -p tcp -i $I_LAN1 -s $IP -j DROP" else if [ "$VAI_USAR_PROXY" == "True" ]; then EXECUTAR_REGRA="$IPT -t nat -A PREROUTING -i $I_LAN1 -s $IP -m mac --mac-source $MAC -j proxy" else EXECUTAR_REGRA="$IPT -t nat -A PREROUTING -i $I_LAN1 -s $IP -j ACCEPT" fi fi # Executa a regra referente ao IP dentro do loop $EXECUTAR_REGRA # Aplica o controle de banda ao IP. Para cada IP é criada uma classe de download e upload. WEIGHT_DOWN=$(expr $DOWNLOAD / 10) ID_DOWN=1"$CODIGO" $TC class add dev $I_LAN1 parent 1: classid 1:$ID_DOWN cbq bandwidth 10Mbit rate "$DOWNLOAD"Kbit weight "$WEIGHT_DOWN"Kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded $TC filter add dev $I_LAN1 parent 1:0 protocol ip prio 100 u32 match ip dst $IP classid 1:$ID_DOWN WEIGHT_UP=$(expr $UPLOAD / 10) ID_UP=2"$CODIGO" $TC class add dev $I_WAN parent 1: classid 1:$ID_UP cbq bandwidth 10Mbit rate "$UPLOAD"Kbit weight "$WEIGHT_UP"Kbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded $TC qdisc add dev $I_WAN parent 1:$ID_UP handle $ID_UP tbf rate "$UPLOAD"Kbit buffer 10Kb/8 limit 15Kb mtu 1500 $TC filter add dev $I_WAN parent 1:0 protocol ip prio 100 u32 match ip src $IP classid 1:$ID_UP done # Aplica o TOS 60 nas portas utilizadas por outros serviços. Assim é usado a velocidade total da rede # para acesso ao SSH, Apache e Samba $IPT -t mangle -A OUTPUT -p tcp --sport 22 -j TOS --set-tos 60 $IPT -t mangle -A OUTPUT -p tcp --sport 80 -j TOS --set-tos 60 $IPT -t mangle -A OUTPUT -p tcp --sport 137:139 -j TOS --set-tos 60 $IPT -t mangle -A OUTPUT -p udp --sport 137:139 -j TOS --set-tos 60 $IPT -t mangle -A INPUT -p tcp --dport 137:139 -j TOS --set-tos 60 $IPT -t mangle -A INPUT -p udp --dport 137:139 -j TOS --set-tos 60 # Compartilha a internet $IPT -t nat -A POSTROUTING -o $I_WAN -j MASQUERADE # Bloqueio contra Scanners Ocultos (Shealt Scan) $IPT -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j DROP # Libera ping (CUIDADO com ataques ddos) $IPT -A INPUT -i $I_LAN1 -p icmp -j ACCEPT $IPT -A INPUT -i $I_WAN -p icmp -j ACCEPT # Libera acesso para o proprio gateway $IPT -A INPUT -i lo -j ACCEPT $IPT -A FORWARD -i lo -j ACCEPT # Libera acesso ao Apache $IPT -A INPUT -p tcp --dport 80 -j ACCEPT $IPT -A INPUT -p tcp --dport 443 -j ACCEPT # Libera acesso ao Squid $IPT -A INPUT -p tcp --dport 3128 -j ACCEPT # Libera acesso ao SSH $IPT -A INPUT -p tcp --dport 22 -j ACCEPT # Libera acesso ao DNS $IPT -A INPUT -p udp --dport 53 -j ACCEPT # Libera acesso aos compartilhamentos do Samba $IPT -A INPUT -p tcp --dport 137:139 -j ACCEPT $IPT -A INPUT -p udp --dport 137:139 -j ACCEPT # Libera acesso ao SNMP #$IPT -A INPUT -p udp --dport 160:162 -j ACCEPT # Tratamento de conexoes TCP $IPT -A INPUT -p tcp --syn -j DROP $IPT -A INPUT -p tcp -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT $IPT -A INPUT -m limit --limit 3/minute --limit-burst 3 -j DROP # Bloqueando pacotes estranhos $IPT -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP $IPT -A INPUT -p tcp --tcp-flags ALL ALL -j DROP $IPT -A INPUT -p tcp --tcp-flags ALL FIN -j DROP $IPT -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP $IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP $IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP echo "Firewall iniciado" } case $1 in # Inicia o firewall e o dhcpd start) iniciar_firewall; $DHCPD_DAEMON stop; $DHCPD_DAEMON start; exit ;; # Finaliza o firewall sem parar o dhcp stop) parar_firewall; exit ;; # Inicia o firewall sem reiniciar o dhcpd only) iniciar_firewall; exit ;; # Finaliza o controle de banda fast) parar_controle_de_banda; exit ;; # Se nenhum parametro for passado, mostra a ajuda abaixo *) echo "Use assim: $0 start|stop|only|fast"; exit 1;; esac
Conclusão
Com o término da segunda parte do artigo é possível colocar um servidor Linux funcionando com eficiência, segurança e estabilidade para compartilhar uma conexão de internet. É uma ótima solução custo/benefício para micro e pequenas empresas.
Na próxima parte vou mostrar como desenvolver uma interface web para gerenciar melhor os pontos de rede. Isso dá mais agilidade ao trabalhar com muitas máquinas na rede.
Algumas considerações:
- Tomem cuidado na configuração do firewall. Esse é um script simples que serve não deve ser tomado como solução definitiva.
- Há outra alternativa para controle de banda chamada HTB. Pessoalmente prefiro o CBQ, o mesmo utilizado nesse script, mas vale a pena dar uma estudada.
- Usar um arquivo texto contendo os dados dos pontos de rede para ser lido pelo shell script foi a idéia mais simples e não a de melhor desempenho. Também fiz o script fazer consultas ao MySQL mas não senti diferença na velocidade comparado com a leitura de um arquivo de texto.
Bom, a parte 3 do artigo só em 2010. Nesse momento já estou em algum lugar sem internet e talvez sem celular. ![]()
Feliz ano novo à todos!















Posted in
Tags: 