AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 545033
Accepted
cyqsimon
cyqsimon
Asked: 2019-10-04 20:50:22 +0800 CST2019-10-04 20:50:22 +0800 CST 2019-10-04 20:50:22 +0800 CST

Limitar a largura de banda em uma porta específica no CentOS 7?

  • 772

Estou executando o CentOS 7 no meu VPS e gostaria de limitar a largura de banda em uma porta específica. Eu olhei em volta extensivamente e, entre as soluções que posso encontrar, é um limite colocado em uma interface ou é uma configuração iptable vagamente descrita que parece ter sido tentada apenas no CentOS 6.

No meu caso, meu lado do servidor Shadowsocks (um aplicativo proxy) está escutando na porta 1080, 1081e 1082no eth0. Eu gostaria de permitir 1080largura de banda ilimitada, mas limitar ambos 1081e 1082cerca de 1 MBps. Como é um aplicativo proxy, o tráfego de entrada e saída é aproximadamente igual. Observe que é uma única instância do Shadowsocks ouvindo em 3 portas, NÃO 3 instâncias ouvindo em 1 porta cada, portanto, limitar a largura de banda por processo não é aplicável.

Mas, caso contrário, qualquer solução está na mesa para mim, seja algo que o CentOS suporta imediatamente ou algum tipo de camada de monitoramento intermediária. Desde que faça o trabalho, estou aberto a isso.

Desde já, obrigado.

centos
  • 1 1 respostas
  • 6413 Views

1 respostas

  • Voted
  1. Best Answer
    A.B
    2019-10-09T05:49:00+08:002019-10-09T05:49:00+08:00

    O tráfego pode ser limitado usando apenas o Controle de Tráfego do Linux .

    Apenas para esclarecer, shadowsocks cria um túnel com um lado como um proxy SOCKS5 ( sslocal, estou assumindo que é o que está sendo executado no servidor do OP considerando as portas fornecidas), comunicando-se com um endpoint remoto ( ssserver) que se comunicará com o destino real servidores. shadowsocks manipula SOCKS5 UDP ASSOCIATE e usa então (SOCKS5) UDP na mesma porta que a porta TCP (SOCKS5).

    Esta solução funciona como está (veja a nota 1) para TCP e UDP, exceto que o UDP pode oferecer desafios adicionais: se uma fonte estiver criando pacotes UDP de tamanho "maior que MTU" (o que provavelmente não deve ser feito por um cliente ou servidor), eles ficam fragmentados. tc , que funciona antes do netfilter na entrada e depois do netfilter na saída , verá os fragmentos. A porta UDP não está disponível em fragmentos, portanto, nenhum filtro poderá capturá-los e quase nenhuma limitação acontecerá. O TCP naturalmente usando MTU para limite de tamanho de pacote (e fazendo a descoberta de MTU de caminho de qualquer maneira) não sofre esse problema na maioria das configurações.

    Aqui está uma imagem ASCII de fluxo de pacotes (a imagem inteira normalmente representaria uma atividade de cliente resultando em dois fluxos, um à esquerda e outro à direita do proxy):

                  traffic controlled      TCP self-adjusting / no UDP control
                 ------------->               <-------------
               /                \           /                \
      clients |                  |  proxy  |                  |  remote  ====== real servers
               \                / (sslocal) \                / (ssserver)
                 <-------------               ------------->
                  traffic controlled       already rate limited
    

    Não há necessidade ou uso de se preocupar com o tráfego com o servidor remoto:

    • a saída do proxy para o servidor remoto será, obviamente, limitada pela entrada dos clientes,
    • entrada de remoto/servidores para proxy
      • O TCP normalmente se ajustará e se comportará como o tráfego no lado do cliente.
      • O UDP não terá essa possibilidade, a menos que o protocolo de aplicação possa fazê-lo. Por exemplo: se dois feeds de vídeo sobre UDP simples chegarem do lado do servidor e excederem o limite no lado do cliente, ambos os fluxos dos clientes provavelmente serão corrompidos. Deve haver um feedback do aplicativo para reduzir a largura de banda, isso está fora deste escopo.

    De qualquer forma, ficaria muito mais complexo, provavelmente envolvendo mudanças dentro do shadowsocks, para vincular o tráfego do lado remoto/servidor ao lado do cliente para uso do tc .

    Para clientes SOCKS5 apenas enviando dados, é necessário limitar a entrada deles para limitar a largura de banda, e para clientes SOCKS5 apenas recebendo dados, é necessário limitar a saída para limitar a largura de banda: a menos que o aplicativo em uso seja bem conhecido, ambas as formas devem ser controladas por tráfego .

    O controle de tráfego é um tema complexo, que mal consigo arranhar. Vou dar dois tipos de respostas: a simples e grosseira fazendo policiamento (soltar excesso) apenas, e uma mais complexa, fazendo modelagem (incluindo atrasar antes de ter que largar), com uma interface IFB para contornar as limitações de entrada .

    A documentação abaixo deve ser lida para entender os conceitos e a implementação do Linux:

    http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/

    Além disso, este comando implementado no script de shell (e usando mecanismos semelhantes como nesta resposta) também pode fazer maravilhas:

    https://github.com/magnific0/wondershaper

    Simples e bruto

    Uma ação de polícia é usada para descartar qualquer excesso de portas de correspondência de pacotes (que é um método bruto). Geralmente é usado na entrada , mas também funciona na saída . O tráfego é limitado por taxa, mas pode haver flutuações e compartilhamento injusto entre vários clientes com taxa limitada (especialmente se UDP vs TCP estiver envolvido).

    • saída (pacotes de saída)

      A qdisc mais simples que permite anexar filtros é a prio qdisc , cujos recursos específicos não serão realmente usados.

      tc qdisc add dev eth0 root handle 1: prio
      

      Basta adicionar o seguinte filtro (com 8 mbits/s <=> 1 MBytes/s) um por porta ( u16 at 0 layer transportsignifica "porta de origem"), para TCP e UDP (veja também a nota 2) :

      tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081)' action police rate 8mibit burst 256k
      tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
      

      Caso eu tenha entendido errado e deva haver apenas um limite comum para 1081 e 1082, use isso em vez dos dois acima, agrupando-os na mesma ação (o que é fácil com o filtro básico / ematch ), que então os tratará em um bucket de token único:

      tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081) or cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
      
    • ingresso (pacotes de entrada)

      A entrada é mais limitada que a saída (não é possível fazer modelagem ), mas não foi feita no caso simples de qualquer maneira. Usá-lo requer apenas adicionar um ingressqdisc (veja a nota 3) :

      tc qdisc add dev eth0 ingress
      

      Os filtros equivalentes ( u16 at 2 layer transportsignifica "porta de destino"):

      tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action police rate 8mibit burst 256k
      tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
      

      ou para um único limite, em vez dos dois acima:

      tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081) or cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
      

    Limpeza tc

    egress , ingress ou ambas as configurações podem ser substituídas por sua versão aprimorada abaixo. configurações anteriores devem ser limpas primeiro.

    Para remover as configurações de tc aplicadas anteriormente, basta excluir a raiz e a entrada qdiscs . Tudo abaixo deles, incluindo filtros, também será removido. A interface padrão qdisc raiz com o handle reservado 0: será colocada de volta.

    tc qdisc del dev eth0 root
    tc qdisc del dev eth0 ingress
    

    Configuração mais complexa com qdiscs classful e interface IFB

    O uso de modelagem , que pode atrasar os pacotes antes de descartá-los, deve melhorar os resultados gerais. Hierarchy Token Bucket ( HTB ), um qdisc classful lidará com a largura de banda, enquanto abaixo dele o Stochastic Fairness Queuing ( SFQ ) melhorará a justiça entre os clientes quando estiverem competindo dentro da largura de banda restrita.

    • saída

      Aqui está uma imagem ascii descrevendo as próximas configurações:

                          root 1:   HTB classful qdisc
                            |
                          / | \
                         /  |  \
                        /   |   \
                       /    |    \
                      /    1:20  1:30  HTB classes
                     /    8mibit  8mibit
                    /       |       \
                   /        |        \
                  /        20:       30:
                 /         SFQ       SFQ
           still 1:
           default         port         port
      incl. port 1080      1081         1082
      

      As larguras de banda limitadas não emprestarão tráfego extra disponível (não foi solicitado pelo OP): é por isso que elas não são uma subclasse de uma classe padrão de "toda a largura de banda disponível". O tráfego padrão restante, incluindo a porta 1080, permanece em 1:, sem tratamento especial. Em diferentes configurações em que as classes têm permissão para emprestar largura de banda disponível, essas classes devem ser colocadas abaixo de uma classe pai com sua taxa definida com um valor preciso da largura de banda máxima disponível, para saber o que emprestar. Portanto, a configuração exigiria um ajuste fino para cada caso. Eu mantive simples.

      O qdisc classful htb:

      tc qdisc add dev eth0 root handle 1: htb
      

      As classes htb, sfq anexado e filtros direcionando para eles:

      tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit
      tc class add dev eth0 parent 1: classid 1:30 htb rate 8mibit
      
      tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
      tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
      
      tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20
      tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:30
      

      ou para um único limite, em vez dos 6 comandos acima:

      tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit
      tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
      tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20
      tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:20
      
    • entrada

      O qdisc de ingresso não pode ser usado para modelagem (por exemplo, atraso de pacotes), mas apenas para que sejam descartados com filtros como no caso simples. Para ter um melhor controle, um truque está disponível: o Bloco Funcional Intermediário , que aparece como uma interface de saída artificial onde o tráfego de entrada pode ser redirecionado com filtros, mas tem pouca interação com o restante da pilha da rede. Uma vez instalados, os recursos de saída podem ser aplicados nele, mesmo que alguns deles nem sempre sejam úteis, considerando que o controle real do tráfego de entrada não está nas mãos do sistema receptor. Então aqui eu configurei a ifb0interface e dupliquei acima ( egress) nele, para ter um tipo de modelagem de entrada se comportando melhor do que apenas policiamento.

      Criando ifb0 (veja a nota 4) e aplicando as mesmas configurações da saída anterior :

      ip link add name ifb0 type ifb 2>/dev/null || :
      ip link set dev ifb0 up
      
      tc qdisc add dev ifb0 root handle 1: htb
      

      Classes e filtros direcionados a eles:

      tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit
      tc class add dev ifb0 parent 1: classid 1:30 htb rate 8mibit
      
      tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10
      tc qdisc add dev ifb0 parent 1:30 handle 30: sfq perturb 10
      
      tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20
      tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:30
      

      ou para um único limite, em vez disso, se os 6 comandos acima:

      tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit     
      tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10
      tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20
      tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:20
      

      O redirecionamento da entrada de eth0 para a saída de ifb0 é feito abaixo. Para otimizar, redirecione apenas as portas pretendidas em vez de todo o tráfego. A filtragem e a modelagem reais são feitas acima em ifb0 de qualquer maneira.

      tc qdisc add dev eth0 ingress
      tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0
      tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0
      

    Notas:

    1. Testado usando alguns namespaces de rede no Debian 10 / kernel 5.3. A sintaxe de comandos também foi testada no contêiner / kernel 5.3 do CentOS 7.6 (em vez de 3.10) .

    2. u32 match ip sport 1081 0xffffpoderia ter sido usado para corresponder à porta de origem 1081. Mas não lidaria com a presença de uma opção de IP. u32 match tcp src 1081 0xffffpoderia lidar com isso, mas na verdade requer o uso complexo de três filtros u32 , conforme explicado na página do manual . Então eu escolhi basic matchno final.

    3. ingresstem o identificador reservado ffff:especificado ou não (o valor do identificador especificado é ignorado), então prefiro não especificá-lo. A referência de entrada por parent ffff:pode ser substituída por apenas ingressisso é o que eu escolhi.

    4. Ao criar uma interface IFB pela primeira vez, o módulo ifb é carregado, que por padrão cria automaticamente as interfaces ifb0 e ifb1 no namespace inicial, resultando em erro se o nome da interface ifb0 for solicitado, enquanto na verdade foi criado como resultado do comando. Ao mesmo tempo, esta interface não aparece em um namespace de rede (por exemplo: container) se simplesmente carregar o módulo, então ainda é necessário lá. Portanto, adicionar 2>/dev/null || :resolve para ambos os casos. Claro que estou assumindo que o suporte do IFB está realmente disponível.

    • 8

relate perguntas

  • smartmontools - O teste automático é o mesmo que executar um teste curto?

  • comando systemctl não funciona no RHEL 6

  • Por que meu switch não está obtendo um endereço do pool especificado

  • Criando menus personalizados na guia do menu Aplicativos no CentOS7 GNOME

  • Roteador estranho funciona com centos 6 [fechado]

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve