Para resumir uma longa história, esse ACK foi enviado quando o soquete não pertencia a ninguém. Em vez de permitir que os pacotes pertencentes a um soquete que pertença ao usuário x
, permita que os pacotes que pertencem a uma conexão que foi iniciada por um soquete do usuário x
.
A história mais longa.
Para entender o problema, é útil entender como wget
e solicitações HTTP funcionam em geral.
Em
wget http://cachefly.cachefly.net/10mb.test
wget
estabelece uma conexão TCP com cachefly.cachefly.net
e, uma vez estabelecido, envia uma solicitação no protocolo HTTP que diz: "Por favor, me envie o conteúdo de /10mb.test
( GET /10mb.test HTTP/1.1
) e, a propósito, você poderia por favor, não feche a conexão depois que você terminar ( Connection: Keep-alive
). A razão disso é que, caso o servidor responda com um redirecionamento para uma URL no mesmo endereço IP, ele pode reutilizar a conexão.
Agora o servidor pode responder com "Aqui vem os dados que você solicitou, cuidado com os 10MB grandes ( Content-Length: 10485760
), e sim OK, deixarei a conexão aberta". Ou se não souber o tamanho dos dados, "Aqui estão os dados, desculpe, eu não posso deixar a conexão aberta, mas vou dizer quando você pode parar de baixar os dados, fechando o meu fim da conexão".
No URL acima, estamos no primeiro caso.
Portanto, assim que wget
obtiver os cabeçalhos da resposta, ela saberá que o trabalho está concluído após o download de 10 MB de dados.
Basicamente, o que wget
faz é ler os dados até que 10MB tenham sido recebidos e saiam. Mas nesse ponto, há mais a ser feito. E quanto ao servidor? Foi dito para deixar a conexão aberta.
Antes de sair, wget
fecha ( close
chamada do sistema) o descritor de arquivo para o soquete. Após, o close
, o sistema termina de reconhecer os dados enviados pelo servidor e envia um FIN
para dizer: "Eu não estarei enviando mais dados". Nesse momento, close
retorna e wget
sai. Não há mais soquete associado à conexão TCP (pelo menos, não pertence a nenhum usuário). No entanto, ainda não está terminado. Ao receber esse FIN
, o servidor HTTP vê fim de arquivo ao ler a próxima solicitação do cliente. Em HTTP, isso significa "não mais pedido, eu vou fechar o meu fim". Então, ele envia seu FIN também, para dizer: "Eu também não vou mandar nada, essa conexão está indo embora".
Ao receber esse FIN, o cliente envia um "ACK". Mas, nesse ponto, wget
desapareceu há muito tempo, de modo que o ACK não é de nenhum usuário. É por isso que é bloqueado pelo seu firewall. Como o servidor não recebe o ACK, ele enviará o FIN repetidamente até que ele desista e você verá mais ACKs descartados. Isso também significa que, ao descartar esses ACKs, você está desnecessariamente usando recursos do servidor (que precisa manter um soquete no estado LAST-ACK) por algum tempo.
O comportamento teria sido diferente se o cliente não tivesse solicitado "Keep-alive" ou o servidor não tivesse respondido com "Keep-alive".
Como já foi mencionado, se você estiver usando o rastreador de conexão, o que você quer fazer é deixar todos os pacotes no ESTABLISHED e RELATED aparecerem e se preocupar apenas com NEW
pacotes.
Se você permitir que NEW
pacotes do usuário x
mas não pacotes do usuário y
, outros pacotes para conexões estabelecidas pelo usuário x
serão processados e porque não pode haver conexões estabelecidas pelo usuário y
(já que estamos bloqueando os pacotes NEW
que estabeleceriam a conexão), não haverá nenhum pacote para o usuário y
conexões passando.