-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
$ go version go version go1.11.2 linux/amd64
Does this issue reproduce with the latest release?
Yes
Safely and reliably shutting down an SSL transport while keeping the underlying connection still open is not supported by the API in an intuitive way. I have posted this question on stackoverflow here: https://stackoverflow.com/questions/53825725/how-to-safely-shutdown-ssl-connection
But to repeat the question:
Using Go, how can a tls.Conn be safely shutdown without entirely closing the underlying connection? I have a working solution, but I am not sure if there is a better way.
In my application I have a non-SSL connection that is eventually 'upgraded' to an SSL connection. Then at some point the SSL connection should be closed cleanly, and the connection should return to the non-SSL version (where unencrypted traffic can be sent between the two parties).
import "crypto/tls"
func app(connection net.Conn){
// process some data on the connection, then eventually change it to SSL
ssl = tls.Client(connection, sslConfig) // sslConfig defined elsewhere
ssl.Handshake()
// process data using ssl for a while
// now shut down SSL but maintin the original connection
ssl.CloseWrite()
// at this point we have sent a closeNotify alert to the remote side and are expecting a closeNotify be sent back to us.
// the only way to read the closeNotify is to attempt to read 1 byte
b := make([]byte, 1)
ssl.Read(b)
// assuming the remote side shut down the connection properly, the SSL transport should be finished
connection.Read(...) // can go back to the unencrypted connection
}
This works because if a closeNotify alert record is received then c.readRecord
in crypto/tls/conn.go will return an error value, and will not read any bytes (so presumably the b
byte array could have been any size).
This is a bit confusing from a user's point of view. It would be preferable to have an API like ssl.Shutdown()
that internally maybe does
c.CloseWrite()
b := make([]byte, 1)
c.Read(b)
Or maybe there is a better way to cleanly shutdown, but that is for the library writer's to decide.
I realize it is a bit strange to want to shutdown an SSL transport and continue to use the underlying connection but that is the constraint I am working under.
If it is helpful I can provide a small working example.