4 pontos por GN⁺ 2024-01-17 | 1 comentários | Compartilhar no WhatsApp
  • Speedbump é um proxy TCP escrito em Go que adiciona latência de rede variável ao tráfego TCP encaminhado pelo proxy para simular cenários de atraso
  • É possível somar à latência base componentes de latência em forma de onda senoidal, dente de serra, onda quadrada e onda triangular, e vários componentes podem ser combinados ao mesmo tempo
  • O exemplo mostra uma configuração que faz proxy do tráfego para localhost:80 na porta 2000, aplicando atraso base de 100ms, amplitude senoidal de 100ms e período de 1m
  • A instalação pode ser feita baixando os binários pré-compilados de cada release, compilando do código-fonte com go build, ou executando a imagem de contêiner kffl/speedbump
  • Além da CLI, também pode ser usado como biblioteca por meio do pacote Go lib, com ajuste de parâmetros como tamanho de buffer, tamanho da fila de atraso, nível de log, host de escuta e porta

Proxy para simulação de latência TCP

  • Speedbump é um proxy TCP escrito em Go e pode simular latência de rede variável
  • O destino do proxy é especificado pelo argumento <destination> da CLI, no formato host:post
  • O funcionamento padrão é encaminhar o tráfego TCP ao destino enquanto adiciona o atraso configurado

Instalação e formas de execução

  • A forma mais fácil de instalar é baixar os binários pré-compilados anexados automaticamente em Assets de cada release
  • Para compilar a partir do código-fonte, clone o repositório e execute go build
  • Para executar em contêiner, é possível usar a imagem kffl/speedbump

Exemplo básico de uso

  • É possível escutar na porta 2000 e encaminhar o tráfego TCP para localhost:80, aplicando latência base de 100ms, amplitude senoidal de 100ms e período de 1m
    • Essa configuração gera latência adicional máxima de 200ms e mínima de 0
    • Exemplo de execução: speedbump --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • A mesma configuração também pode ser executada com a imagem de contêiner
    • Exemplo: docker run --net=host kffl/speedbump:latest --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • Também é possível configurar um componente de latência em dente de serra
    • O exemplo usa latência base de 300ms, amplitude em dente de serra de 200ms, período de 2m, porta 2000 e destino localhost:80
    • O comando é speedbump --latency=300ms --saw-amplitude=200ms --saw-period=2m --port=2000 localhost:80

Combinação de componentes de latência

  • Speedbump pode aplicar vários componentes de latência ao mesmo tempo
  • O README inclui um exemplo de gráfico de atraso combinando dente de serra e senoide

Argumentos da CLI e uso como biblioteca

  • speedbump --help mostra o uso no formato speedbump [<flags>] <destination>
  • As principais configurações de rede são as seguintes
    • --host: IP ou nome de host para escuta; se não for especificado, faz bind em todas as interfaces de rede
    • --port: porta de escuta; o padrão é 8000
    • --buffer: tamanho do buffer usado na leitura TCP; o padrão é 64KB
    • --queue-size: tamanho da fila de atraso que armazena os buffers lidos; o padrão é 1024
  • Há valores padrão relacionados à latência e opções de forma de onda
    • --latency: latência base adicionada ao tráfego encaminhado; o padrão é 5ms
    • --sine-amplitude, --sine-period: amplitude e período da latência senoidal
    • --saw-amplitude, --saw-period: amplitude e período da latência em dente de serra
    • --square-amplitude, --square-period: amplitude e período da latência em onda quadrada
    • --triangle-amplitude, --triangle-period: amplitude e período da latência em onda triangular
  • Também há opções operacionais
    • --log-level: nível de log; os valores possíveis são DEBUG, TRACE, INFO, WARN, ERROR
    • --version: exibe a versão da aplicação
  • Speedbump também pode ser usado como biblioteca Go, fornecida por meio do pacote lib
  • A licença é a Apache 2.0 License

1 comentários

 
GN⁺ 2024-01-17
Opiniões no Hacker News
  • Eu estava procurando algo parecido para testar várias implementações de ActivityPub em diferentes escalas e condições de rede, mas já tinha tudo de que precisava instalado na minha máquina com tc
    Na minha distribuição, ele vinha incluído no pacote iproute2, e há uma explicação aqui também: https://wiki.archlinux.org/title/advanced_traffic_control
    Para adicionar atraso a uma interface específica, basta executar algo como tc qdisc add dev eth0 root netem delay 100ms
    É fácil de usar, funciona bem também em contêineres Docker, permite aplicar condições como atraso, perda e duplicação de pacotes, e é bem possível que já esteja instalado

    • tc/netem/tbf são realmente ótimos. Fiz uma GUI simples em Python por cima disso e rodei em um Pi dentro de uma case com tela sensível ao toque; era uma caixinha preta com opções como “queda de pacotes: [0%] [1%] [10%] [50%] / corrupção de pacotes: ...”, e os clientes ficavam bem impressionados
      Achei curioso que front-ends parecidos não pareçam existir como produtos comerciais de hardware; se eu não deixei passar na busca, parece que não há isso no mercado
    • A desvantagem do tc é que aplicá-lo a pacotes recebidos é meio estranho e trabalhoso
      Antigamente, criei meu próprio emulador para imitar um terminal comercial específico de satélite. Esse terminal acumulava pacotes em uma fila e, quando atingia um certo limite ou passava de um timeout, despejava tudo de uma vez; ele ainda tentava “gentilmente” reordenar pacotes pequenos para o início da fila a fim de reduzir a latência, mas a pilha TCP detestava isso
    • O ponto bom do speedbump é que ele permite ajustar as condições de falha ao longo do tempo. O tc não faz isso
      Pode ser bem útil para simular os efeitos climáticos sobre satélite/RF variando com o tempo
  • A Netflix fez exatamente isso, e o nome era latency monkey
    Descobrimos que determinar se um subserviço está “lento” é muito mais difícil do que determinar se está “indisponível”, então essa era uma forma importante de testar como o serviço lidava com lentidão e problemas de rede
    A implementação era muito simples: descartava pacotes em uma taxa configurável, o que forçava retransmissões e fazia com que, do outro lado, os pacotes chegassem atrasados e fora de ordem
    No fim, isso revelou muitos problemas no código de tratamento de erros relacionado a acesso à rede

  • Acho que todo engenheiro de software que cria aplicações interativas para a internet deveria usar ferramentas assim no trabalho diário. Não só para TCP, mas também para QUIC; e, para cobrir DNS, idealmente todo UDP também
    Tenho certeza de que 90% do inchaço das aplicações web desapareceria se quem as cria não usasse apenas ambientes de computação tipo Cadillac banhado a ouro

  • Muitos apps funcionam muito mal em ambientes em que a conectividade de rede cai de forma intermitente, como em situações de ajuda em desastres
    Seria útil para outras pessoas se mais desenvolvedores de apps testassem simulando conectividade intermitente
    Do tópico “Toxiproxy is a framework for simulating network conditions” (2021) https://news.ycombinator.com/item?id=29084277#29088775:

    Muitos apps não têm, por exemplo, o recurso de “manter na caixa de saída” que se espera de um cliente de e-mail

    • [ ] Será que alguém poderia criar um conjunto de “mutadores de casos de teste” de referência para o toxiproxy que simule problemas comuns de conectividade em #DisasterRelief?
    • O que eu mais odeio é quando não preenchem o buffer antes de enviar pacotes. Aí, numa conexão de internet ruim — ou seja, com perda de pacotes e alta latência causando retransmissões TCP — de repente você só consegue 120 kps
      Porque estão enviando apenas pacotes de 50 bytes, e 1 em cada 10 deles se perde. Enquanto isso, uma thread do servidor fica sem fazer nada útil
  • No Mac, dá para fazer a mesma coisa só com ferramentas integradas

    # Setup pipe  
    sudo dnctl pipe 1 config bw 1Kbit/s delay 800
    
    # Setup matching pf rule  
    echo "dummynet out proto tcp from any to 127.0.0.1 port 11211 pipe 1" | sudo pfctl -f -
    
    # Turn on firewall  
    sudo pfctl -e
    
    # Test  
    time nc -vz 127.0.0.1 11211  
    Connection to 127.0.0.1 port 11211 [tcp/*] succeeded!  
    nc -vz 127.0.0.1 11211 0.01s user 0.00s system 0% cpu 1.333 total  
    
    • O Dummynet e esses recursos vieram do FreeBSD, onde existem há muito tempo. Usei isso para testar perda de pacotes há mais de 15 anos e funcionava bem
  • Há um projeto que está inativo há algum tempo, mas cujo nome já diz muita coisa: https://github.com/tylertreat/comcast

  • Recentemente, ao tentar simular uma rede lenta no Mac, encontrei o Network Link Conditioner, que é bem bom. Não é preciso configurar nada como um proxy
    É necessário instalá-lo a partir das ferramentas adicionais do Xcode
    https://nshipster.com/network-link-conditioner/

  • Também vale conferir a excelente ferramenta toxiproxy, da Shopify: https://github.com/Shopify/toxiproxy
    É também uma forma muito boa de testar implementações próprias de bibliotecas de rede, porque a pilha precisa lidar corretamente com a maioria das situações adversas
    A ideia de “engenharia do caos” é ótima

    • Eu também procurei primeiro o toxiproxy, mas o modelo cliente-servidor não se encaixava no meu caso, e o speedbump serviu exatamente para meu uso de simular latência HTTP
      Estou desenvolvendo uma barra de progresso para um web crawler, mas, testando em localhost, é rápido demais para perceber se há algum problema
      Com o speedbump, basta executar podman run --net=host kffl/speedbump:latest --latency=1s --port=8001 localhost:8000 e testar o crawler em http://localhost:8001
      É uma ferramenta limpa
  • Usei uma ferramenta parecida no Windows
    https://jagt.github.io/clumsy/

    • Usei há uns 10 anos para testar várias condições de rede entre continentes, e os resultados bateram bem com a realidade. Recomendo
    • Parece legal, mas, só pelas capturas de tela, parece uma aplicação no sistema inteiro com filtros, e não por adaptador
  • O FreeBSD também tem o dummynet como parte do ipfw, permitindo injetar atraso, limitação de largura de banda, tamanho de fila e perda de pacotes. É o mesmo recurso que existe no MacOS

    • É como o tc no Linux?