I want to increase the keep alive period of my TCP connection for both HTTP and HTTPS requests.
For HTTP requests this can be done like this:
package main
import (
"fmt"
"io"
"log"
"net"
"net/http"
"time"
)
func main() {
server := &http.Server{Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello, World!")
})}
server.ConnState = func(conn net.Conn, state http.ConnState) {
if state == http.StateNew {
if err := conn.(*net.TCPConn).SetKeepAlivePeriod(1000 * time.Second); err != nil {
fmt.Println("Could not set keep alive period", err)
} else {
fmt.Println("update keep alive period")
}
}
}
log.Fatal(server.ListenAndServe())
}
For HTTPS requests this cannot be done via server.ConnState
because the net.Conn
that will be passed inside the function is a *tls.Conn
. This connection does not expose a function like SetKeepAlivePeriod
or gives access to the underlying *net.TCPConn
.
func main() {
server := &http.Server{Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello, World!")
})}
server.ConnState = func(conn net.Conn, state http.ConnState) {
if state == http.StateNew {
tlsConn := conn.(*tls.Conn)
// how to set SetKeepAlivePeriod
}
}
log.Fatal(server.ListenAndServeTLS("../example.crt", "../example.key"))
}
How can I set the keep alive period for tls connections?
There are (at least) two ways to do it:
The net.ListenConfig
object has a KeepAlive time.Duration
field. When non-zero, this will be used to set the keep-alive on accepted connections (eg: for TCP on posix).
You can pass the listener to ServeTLS
:
server := &http.Server{...}
lc := net.ListenConfig{KeepAlive: 1000 * time.Second}
ln, err := lc.Listen(context.Background(), "tcp", ":8080")
if err != nil {
panic(err)
}
defer ln.Close()
log.Fatal(server.ServeTLS(ln, "../example.crt", "../example.key"))
As mentioned, accepted TCP connections will automatically have keep-alive enabled and the period set to the specified value.
You can access the net.Conn
underlying the tls.Conn
by setting the tls.Config GetConfigForClient
or GetCertificate
callback.
It does not matter which one you're using as long as you return nil
to make the TLS code fall back to the default behavior. The important part is to get access to the tls.ClientHelloInfo which has a .Conn
field pointing to the underlying connection. This will the net.TCPConn
.
setTCPKeepAlive := func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) {
// Check that the underlying connection really is TCP.
if tcpConn, ok := clientHello.Conn.(*net.TCPConn); ok {
if err := tcpConn.SetKeepAlivePeriod(1000 * time.Second); err != nil {
fmt.Println("Could not set keep alive period", err)
} else {
fmt.Println("update keep alive period")
}
} else {
fmt.Println("TLS over non-TCP connection")
}
// Make sure to return nil, nil to let the caller fall back on the default behavior.
return nil, nil
}
tlsConfig := &tls.Config{
...
GetConfigForClient: setTCPKeepAlive,
...
}
server := &http.Server{
Addr: ":8080",
TLSConfig: tlsConfig,
}
server.ListenAndServeTLS("../example.crt", "../example.key")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With