Sinalizador TCP RST (windows vs linux)

0

Eu quebrei o cliente que precisava atender e não posso alterá-lo ou afetá-lo de nenhuma maneira. Eu coloquei o mesmo software no windows e no linux. O Windows está funcionando, o Linux não é. Depois de analisar, descobri que esse é o problema do TCP Handshaking. Aqui está um dump simplificado:

Servidor do Windows:

SYN(seq=X,ack=0)--->
    <---SYN,ACK(seq=Y,ack=X+1)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---RST(seq=Y+1,ack=X+1)
SYN(seq=Z,ack=0)--->
    <---SYN,ACK(seq=V,ack=Z+1)
ACK(seq=Z+1,ack=V+1)--->
    <---PSH,ACK(seq=V+1,ack=Z+1)

.......WORKING.........

Servidor Linux:

SYN(seq=X,ack=0)--->
    <---SYN,ACK(seq=Y,ack=X+1)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
SYN(seq=X,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)
    <---SYN,ACK(seq=Y,ack=X+1) (TCP Retransmission)

SYN(seq=Z,ack=0)--->
    <---SYN,ACK(seq=V,ack=Z+1)
SYN(seq=Z,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
SYN(seq=Z,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
SYN(seq=Z,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
SYN(seq=Z,ack=0)--->           (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)
    <---SYN,ACK(seq=V,ack=Z+1) (TCP Retransmission)

......ENDLESS LOOP.......

Note que o TCP Retransmission não é causado por timeouts de rede ou algo assim, eu acredito que este cliente quebrado simplesmente ignore, solte-os.

A chave para fazer esse handshake funcionar é enviar um pacote com apenas o sinalizador RST (RST, ACK não funciona). O Windows está fazendo isso ingenuamente, como fazer isso funcionar no linux?

Existe alguma opção / configuração do kernel do Linux para conseguir isso?

Existe algum sinalizador / opção de soquete (como SO_LINGER)?

Talvez alguma outra maneira de fazer isso funcionar no Linux?

Minha solução atual é colocar essas regras nftables:

nft 'add rule input input tcp dport > 1024 tcp flags & (fin | syn | rst | psh | ack | urg) == syn limit rate over 5/minute burst 3 packets ip protocol tcp reject with tcp reset'
nft 'add rule input output tcp sport > 1024 tcp flags & (fin | syn | rst | psh | ack | urg) == rst | ack tcp flags set rst'

Primeiro, tenta descobrir essa retransmissão de SYN e responder com a reinicialização tcp (RST, ACK). Segundo um swap que RST, ACK em RST. ..mas esta solução alternativa está suja e pode afetar outra transmissão também: - (

    
por luzik 30.08.2018 / 11:42

0 respostas