Support SNI routing with Postgres STARTTLS connections

Co-authored-by: Michael Kuhnt <michael.kuhnt@daimler.com>
Co-authored-by: Julien Salleyron <julien@containo.us>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Romain 2022-11-16 15:34:10 +01:00 committed by GitHub
parent fadee5e87b
commit 630de7481e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 295 additions and 13 deletions

View file

@ -922,3 +922,89 @@ func checkHTTPSTLS10(addr string, timeout time.Duration) error {
func checkHTTPSTLS12(addr string, timeout time.Duration) error {
return checkHTTPS(addr, timeout, tls.VersionTLS12)
}
func TestPostgres(t *testing.T) {
router, err := NewRouter()
require.NoError(t, err)
// This test requires to have a TLS route, but does not actually check the
// content of the handler. It would require to code a TLS handshake to
// check the SNI and content of the handlerFunc.
err = router.AddRouteTLS("HostSNI(`test.localhost`)", 0, nil, &tls.Config{})
require.NoError(t, err)
err = router.AddRoute("HostSNI(`*`)", 0, tcp2.HandlerFunc(func(conn tcp2.WriteCloser) {
_, _ = conn.Write([]byte("OK"))
_ = conn.Close()
}))
require.NoError(t, err)
mockConn := NewMockConn()
go router.ServeTCP(mockConn)
mockConn.dataRead <- PostgresStartTLSMsg
b := <-mockConn.dataWrite
require.Equal(t, PostgresStartTLSReply, b)
mockConn = NewMockConn()
go router.ServeTCP(mockConn)
mockConn.dataRead <- []byte("HTTP")
b = <-mockConn.dataWrite
require.Equal(t, []byte("OK"), b)
}
func NewMockConn() *MockConn {
return &MockConn{
dataRead: make(chan []byte),
dataWrite: make(chan []byte),
}
}
type MockConn struct {
dataRead chan []byte
dataWrite chan []byte
}
func (m *MockConn) Read(b []byte) (n int, err error) {
temp := <-m.dataRead
copy(b, temp)
return len(temp), nil
}
func (m *MockConn) Write(b []byte) (n int, err error) {
m.dataWrite <- b
return len(b), nil
}
func (m *MockConn) Close() error {
close(m.dataRead)
close(m.dataWrite)
return nil
}
func (m *MockConn) LocalAddr() net.Addr {
return nil
}
func (m *MockConn) RemoteAddr() net.Addr {
return &net.TCPAddr{}
}
func (m *MockConn) SetDeadline(t time.Time) error {
return nil
}
func (m *MockConn) SetReadDeadline(t time.Time) error {
return nil
}
func (m *MockConn) SetWriteDeadline(t time.Time) error {
return nil
}
func (m *MockConn) CloseWrite() error {
close(m.dataRead)
close(m.dataWrite)
return nil
}