From c37412b58cfe183284eeffef962dd08bf63ff025 Mon Sep 17 00:00:00 2001 From: Garionion Date: Thu, 19 Jan 2023 00:18:34 +0100 Subject: [PATCH] initial commit --- fly.toml | 41 +++++++++++++++++++++++++++++++++++++++++ go.mod | 10 ++++++++++ go.sum | 18 ++++++++++++++++++ main.go | 42 ++++++++++++++++++++++++++++++++++++++++++ sni-preread.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 fly.toml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 sni-preread.go diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..9ee5486 --- /dev/null +++ b/fly.toml @@ -0,0 +1,41 @@ +# fly.toml file generated for fly-tls-proxy on 2023-01-18T21:56:58+01:00 + +app = "fly-tls-proxy" +kill_signal = "SIGINT" +kill_timeout = 5 +processes = [] + +[build] + builder = "paketobuildpacks/builder:base" + buildpacks = ["gcr.io/paketo-buildpacks/go"] + +[env] + PORT = "8443" + +[experimental] + auto_rollback = true + +[[services]] + http_checks = [] + internal_port = 8443 + processes = ["app"] + protocol = "tcp" + script_checks = [] + [services.concurrency] + hard_limit = 25 + soft_limit = 20 + type = "connections" + + [[services.ports]] + force_https = true + handlers = ["http"] + port = 80 + + [[services.ports]] + port = 443 + + [[services.tcp_checks]] + grace_period = "1s" + interval = "15s" + restart_limit = 0 + timeout = "2s" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5d224c7 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module fly-tls-proxy + +go 1.19 + +require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/rs/zerolog v1.28.0 // indirect + golang.org/x/sys v0.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0aeebd2 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= +github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go new file mode 100644 index 0000000..c91c6da --- /dev/null +++ b/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "net" + "os" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + + // Create a new listener + listener, err := net.Listen("tcp", ":8443") + if err != nil { + log.Panic().Err(err).Msg("Failed to create listener") + } + + // Accept connections + for { + conn, err := listener.Accept() + if err != nil { + log.Err(err).Msg("Failed to accept connection") + continue + } + go func(conn net.Conn) { + defer conn.Close() + + serverName, _, err := getServerNameExtension(conn) + if err != nil { + log.Err(err).Msg("Failed to read client hello") + return + } + + log.Info().Str("SNI", serverName).Msg("Accepted connection") + + }(conn) + + } + +} diff --git a/sni-preread.go b/sni-preread.go new file mode 100644 index 0000000..96bf640 --- /dev/null +++ b/sni-preread.go @@ -0,0 +1,47 @@ +package main + +import ( + "bytes" + "crypto/tls" + "io" + "net" + "time" +) + +func getServerNameExtension(connection net.Conn) (string, io.Reader, error) { + peekedBytes := new(bytes.Buffer) + sni, err := readServerNameExtension(io.TeeReader(connection, peekedBytes)) + if err != nil { + return "", nil, err + } + + return sni, io.MultiReader(peekedBytes, connection), nil +} + +type readOnlyConn struct { + reader io.Reader +} + +func (conn readOnlyConn) Read(p []byte) (int, error) { return conn.reader.Read(p) } +func (conn readOnlyConn) Write(p []byte) (int, error) { return 0, io.ErrClosedPipe } +func (conn readOnlyConn) Close() error { return nil } +func (conn readOnlyConn) LocalAddr() net.Addr { return nil } +func (conn readOnlyConn) RemoteAddr() net.Addr { return nil } +func (conn readOnlyConn) SetDeadline(t time.Time) error { return nil } +func (conn readOnlyConn) SetReadDeadline(t time.Time) error { return nil } +func (conn readOnlyConn) SetWriteDeadline(t time.Time) error { return nil } + +func readServerNameExtension(reader io.Reader) (string, error) { + var sni string + + if err := tls.Server(readOnlyConn{reader: reader}, &tls.Config{ + GetConfigForClient: func(clientHello *tls.ClientHelloInfo) (*tls.Config, error) { + sni = clientHello.ServerName + return nil, nil + }, + }).Handshake(); sni == "" { + return "", err + } + + return sni, nil +}