tcpproxy doesn't do a graceful shutdown of the tcp connections
databus23 opened this issue · 0 comments
Hi,
reading through the code it seems to me the teardown of tcp connections is not graceful and might close connections to early.
HandleConn
calls Close()
on both tcp connections when it returns (using defer
) and
HandleConn returns as soon as a one of the two proxyCopy
goroutines exits.
This will shutdown the second proxyCopy
goroutine which still might want to transfer data in the opposite direction.
I wrote a little contrived rpc scenario where a tcp client closes its write stream to signal an EOF
and waits for a reply:
Client:
tcpConn.Write([]byte(`ping`))
tcpConn.CloseWrite()
// Wait for response
response, err := ioutil.ReadAll(tcpConn)
fmt.Println("response:", string(response), "err:", err)
Server:
request, err := ioutil.ReadAll(conn)
time.Sleep(100 * time.Millisecond)
conn.Write([]byte(`pong`))
When I connect the client and server directly this works but when putting tcpproxy
in the middle the client gets an empty response because the tcp connections are closed as soon as the client issues CloseWrite
. So in this case tcpproxy
causes different behaviour as when connecting directly.
Looking at the manpage of socat I can find this section which seems related:
When one of the streams effectively reaches EOF, the closing phase begins. Socat transfers the EOF condition to the other stream, i.e. tries to shutdown only its write stream, giving it a chance to terminate gracefully. For a defined time socat continues to transfer data in the other direction, but then closes all remaining channels and terminates.
So my question would be if it would be better to propagate the WriteClose()
instead of just closing the tcp connection.