Isso é possível no linux com iptables
e tc
. Você configura o iptables para MARK
pacotes em uma conexão em que algum número de bytes foi transferido. Em seguida, você tc
coloca esses pacotes marcados em uma classe em uma disciplina de filas para limitar a largura de banda.
Uma parte um tanto complicada é limitar a conexão para uploads e downloads. tc
não suporta modelagem de tráfego da entrada. Você pode contornar isso moldando a saída na interface voltada para o servidor da web (que moldará downloads para o servidor da web) e moldando a saída na interface voltada para o provedor upstream (que moldará os envios do servidor da web). Você não está realmente moldando o tráfego de entrada (download), pois não pode controlar a rapidez com que seu provedor upstream envia dados. Mas, moldar a interface voltada para o servidor da Web resultará na queda de pacotes e no uploader diminuindo sua janela TCP para acomodar o limite de largura de banda.
Exemplo: (assume que isso esteja em um roteador baseado em Linux, onde a interface voltada para o servidor da Web está eth0
e a montante 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 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 é que você substituir FOWARD
com OUTPUT
. Para fazer o download, você precisa configurar uma disciplina de fila usando um dispositivo "Intermediate Functional Block", ou ifb
. Em resumo, ele usa uma interface virtual para que você possa tratar o tráfego de entrada como saída e moldá-lo a partir daí tc
. Mais informações sobre como configurar um ifb
podem ser encontradas aqui: /server/350023/tc-ingress-policing-and-ifb-mirroring
Observe que esse tipo de coisa tende a exigir muito ajuste para ser dimensionado. Uma preocupação imediata é que connbytes
depende do conntrack
módulo, que tende a atingir paredes escalonáveis com um grande número de conexões. Eu recomendaria testes de carga pesada.
Outra ressalva é que isso não funciona para o UDP, pois é sem estado. Existem outras técnicas para resolver isso, mas parece que seus requisitos são apenas para TCP.
Além disso, para desfazer todas as opções 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