Taxa de limite de rede, mas permitir burst por conexão TCP antes de limitar

7

Nós temos um roteador Cisco que permite a limitação de taxa (eles chamam de policiamento), mas permitindo o estouro em uma base de conexão TCP. Por exemplo, podemos limitar a largura de banda a 50 MB, mas o limite não será imposto até que 4 megabytes tenham sido transferidos. Isso é imposto por cada conexão TCP feita.

Existe alguma maneira de fazer isso no Linux? Além disso, existem algumas desvantagens para tal solução? Caso seja útil para qualquer pessoa, o comando da Cisco para configurar o bursting é o terceiro parâmetro para o comando da polícia que é executado sob um mapa de políticas (pelo menos no nosso ASA 5505).

O objetivo é permitir que um servidor tire proveito do estouro de 95/5 e atenda páginas da Web o mais rápido possível para usuários normais, mas reduza as chances de estouro de mais de 5% do tempo (como se estivesse fazendo uma servidor para transferência do servidor ou grandes arquivos sendo baixados de um site). Eu entendo que com um ataque DDoS que durou muito tempo isso pode não ser uma solução, mas por várias razões isso não é uma preocupação aqui.

    
por sa289 13.09.2015 / 17:07

1 resposta

4

Isso é possível no linux com iptables e tc . Você configura iptables para MARK pacotes em uma conexão onde um certo número de bytes foi transferido. Em seguida, você usa tc para colocar esses pacotes marcados em uma classe em uma disciplina de enfileiramento para ratelimitar a largura de banda.

Uma parte um tanto complicada é limitar a conexão para uploads e downloads. tc não suporta a modelagem de tráfego da entrada. Você pode contornar isso modelando a saída na interface voltada para o servidor da Web (que moldará os downloads para o servidor da Web) e modelando a saída na interface voltada para provedor de upstream (que moldará os uploads de seu servidor da Web). Você não está realmente moldando o tráfego de ingresso (download), pois você não pode controlar a rapidez com que o seu provedor envia dados. Mas, modelar a interface voltada para o servidor da Web resultará na eliminação de pacotes e no envio da janela TCP para acomodar o limite de largura de banda.

Exemplo: (presume que isso esteja em um roteador baseado no Linux, onde a interface voltada para o servidor da web é eth0 e o upstream é eth1 )

# mark the packets for connections over 4MB being forwarded out eth1
# (uploads from webserver)
iptables -t mangle -A FORWARD -p tcp -o eth1 -m connbytes --connbytes 4194304: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50

# mark the packets for connections over 4MB being forwarded out eth0
# (downloads to webserver)
iptables -t mangle -A FORWARD -p tcp -o eth0 -m connbytes --connbytes 4194304: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50

# Setup queuing discipline for server-download traffic
tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1: classid 1:50 htb rate 50mbit

# Setup queuing discipline for server-upload traffic
tc qdisc add dev eth1 root handle 1: htb
tc class add dev eth1 parent 1: classid 1:50 htb rate 50mbit

# set the tc filters to catch the marked packets and direct them appropriately
tc filter add dev eth0 parent 1:0 protocol ip handle 50 fw flowid 1:50
tc filter add dev eth1 parent 1:0 protocol ip handle 50 fw flowid 1:50

Se você quiser fazer isso no próprio servidor da Web em vez de em um roteador Linux, ainda poderá usar as partes de upload dos itens acima. Uma mudança notável é a substituição de FOWARD por OUTPUT . Para o download, você precisa configurar uma disciplina de enfileiramento usando um dispositivo "Intermediate Functional Block" ou ifb . Em suma, ele usa uma interface virtual para que você possa tratar o tráfego de entrada como saída e modelá-lo usando tc . Mais informações sobre como configurar um ifb podem ser encontradas aqui: link

Note que esse tipo de coisa tende a exigir muito ajuste para escalar. Uma preocupação imediata é que connbytes depende do módulo conntrack , que tende a atingir paredes de escala com um grande número de conexões. Eu recomendaria testes de carga pesada.

Outra ressalva é que isso não funciona para o UDP, já que ele é sem estado. Existem outras técnicas para lidar com isso, mas parece que suas necessidades são apenas para TCP.

Além disso, para desfazer todos os itens acima, faça o seguinte:

# Flush the mangle FORWARD chain (don't run this if you have other stuff in there)
iptables -t mangle -F FORWARD

# Delete the queuing disciplines
tc qdisc del dev eth0 root
tc qdisc del dev eth1 root
    
por 18.09.2015 / 09:40