Documentation ¶
Index ¶
Examples ¶
Constants ¶
const ( TLSMajor = tls.VersionTLS12 >> 8 TLSHighestMinor = tls.VersionTLS12 & 0xFF // Bump when new releases are made available TLSHandshake = 0x16 TLSClientHello = 0x01 )
TLS field constants
Variables ¶
Functions ¶
This section is empty.
Types ¶
type Chain ¶
type Chain struct { Handler func(net.Conn) (net.Conn, error) Checkers []func([]byte, []interface{}) (bool, int) Description string }
Chain allows for easy chaining of multiple checks, which all must pass before the handler is called. For performance, have the easiest checks first in the line of checkers.
func NewChain ¶
func NewChain(handler func(net.Conn) (net.Conn, error), checkers ...func([]byte, []interface{}) (bool, int)) *Chain
NewChain returns a Chain initialized with the provided handler and list of checkers.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" "github.com/joushou/serve2/utils" ) func main() { server := serve2.New() handler := func(c net.Conn) (net.Conn, error) { return nil, utils.DialAndProxy(c, "tcp", "localhost:80") } sm := proto.NewSimpleMatcher(proto.HTTPMethods, handler) tm := &proto.TLSMatcher{} cm := proto.NewChain(sm.Handle, tm.Check, sm.Check) cm.Description = "HTTPS" server.AddHandlers(cm) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func (*Chain) Check ¶
Check alls all the provided checkers in order, returning the output of the first failing check. If all checkers pass, Check returns (true, 0).
type ListenProxy ¶
type ListenProxy struct { Checker func([]byte, []interface{}) (bool, int) Description string // contains filtered or unexported fields }
ListenProxy provides a net.Listener whose Accept will only return matched protocols.
func NewHTTP ¶
func NewHTTP(handler http.Handler) *ListenProxy
NewHTTP returns a ListenProxy with a http as the listening service. This is a convenience wrapper kept in place for compatibility with older checkouts. Might be removed in the future.
Example ¶
package main import ( "fmt" "net" "net/http" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) type HTTPHandler struct{} func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" || r.Method == "HEAD" { return } fmt.Fprintf(w, "<!DOCTYPE html><html><head></head><body>Welcome to %s</body></html>", r.URL.Path) } func main() { server := serve2.New() // Insert your http.Handler here http := proto.NewHTTP(&HTTPHandler{}) server.AddHandlers(http) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func NewListenProxy ¶
func NewListenProxy(checker func([]byte, []interface{}) (bool, int), buffer int) *ListenProxy
NewListenProxy returns a fully initialized ListenProxy.
Example ¶
package main import ( "bytes" "fmt" "net" "net/http" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) type HTTPHandler struct{} func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" || r.Method == "HEAD" { return } fmt.Fprintf(w, "<!DOCTYPE html><html><head></head><body>Welcome to %s</body></html>", r.URL.Path) } func main() { server := serve2.New() checker := func(header []byte, _ []interface{}) (match bool, required int) { if len(header) < 3 { return false, 3 } if bytes.Compare(header[:3], []byte("GET")) == 0 { return true, 0 } return false, 0 } lp := proto.NewListenProxy(checker, 10) lp.Description = "HTTP" go http.Serve(lp.Listener(), &HTTPHandler{}) server.AddHandlers(lp) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func (*ListenProxy) Check ¶
func (lp *ListenProxy) Check(header []byte, hints []interface{}) (bool, int)
Check just calls the ListenChecker.
func (*ListenProxy) Listener ¶
func (lp *ListenProxy) Listener() net.Listener
Listener returns the proxy net.Listener.
func (*ListenProxy) String ¶
func (lp *ListenProxy) String() string
type SimpleMatcher ¶
type SimpleMatcher struct { Matches [][]byte Handler func(net.Conn) (net.Conn, error) Description string }
SimpleMatcher matches the provided bytes against a list of potential matches, quickly dismissing impossible matches.
func NewDiscard ¶
func NewDiscard() *SimpleMatcher
NewDiscard returns a new Discard protocol handler. Discard is a simple protocol for testing purposes. It requires that the connection is initiated by writing "DISCARD", as protocol recognition would not work otherwise, but after that, it simply reads and discards everything it receives, hence the name.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) func main() { server := serve2.New() // If we send "DISCARD" first, then everything is discarded afterwards server.AddHandlers(proto.NewDiscard()) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func NewEcho ¶
func NewEcho() *SimpleMatcher
NewEcho returns a new ECHO protocol handler. Echo is a simple protocol for testing purposes. It requires that the connection is initiated by writing "Echo", as protocol recognition would not work otherwise, but after that, it simply reads and echoes everything it receives, hence the name.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) func main() { server := serve2.New() // If we send "ECHO" first, then everything is echoed afterwards server.AddHandlers(proto.NewEcho()) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func NewMultiProxy ¶
func NewMultiProxy(matches [][]byte, proto, dest string) *SimpleMatcher
NewMultiProxy returns a SimpleMatcher set up to call DialAndProxy.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) func main() { server := serve2.New() httpMethods := [][]byte{ []byte("GET"), []byte("POST"), } mp := proto.NewMultiProxy(httpMethods, "tcp", "localhost:80") server.AddHandlers(mp) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func NewProxy ¶
func NewProxy(match []byte, proto, dest string) *SimpleMatcher
NewProxy returns a SimpleMatcher set up to call DialAndProxy.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) func main() { server := serve2.New() // SSH just so happens to send "SSH" and version number as the first thing proxy := proto.NewProxy([]byte("SSH"), "tcp", "localhost:22") server.AddHandlers(proxy) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func NewSimpleMatcher ¶
NewSimpleMatcher returns a SimpleMatcher with the provided matches and handler, matches already sorted, and Description initialized to "SimpleMatcher". Do note that this modified the provided matches slice to sort it by length.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" "github.com/joushou/serve2/utils" ) func main() { server := serve2.New() handler := func(c net.Conn) (net.Conn, error) { return nil, utils.DialAndProxy(c, "tcp", "localhost:80") } sm := proto.NewSimpleMatcher(proto.HTTPMethods, handler) sm.Description = "HTTP" server.AddHandlers(sm) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func (*SimpleMatcher) Check ¶
func (s *SimpleMatcher) Check(header []byte, _ []interface{}) (bool, int)
Check looks through the provided matches.
func (*SimpleMatcher) Sort ¶
func (s *SimpleMatcher) Sort()
Sort sorts the provided matches by length.
func (*SimpleMatcher) String ¶
func (s *SimpleMatcher) String() string
String returns the provided description.
type TLS ¶
type TLS struct { Description string // contains filtered or unexported fields }
TLS handles abstraction of TLS connections, in order to feed them back into the protocol detectors.
func NewTLS ¶
NewTLS returns an initialized TLS.
Example ¶
package main import ( "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" ) func main() { server := serve2.New() // We just set NextProto to "echo". Cert and key required! tls, err := proto.NewTLS([]string{"echo"}, "cert.pem", "key.pem") if err != nil { panic(err) } // We add the echo handler too server.AddHandlers(tls, proto.NewEcho()) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func (*TLS) Handle ¶
Handle returns a connection with TLS abstracted away. Adds the tls.Conn for the connection as a hint.
type TLSMatcher ¶
type TLSMatcher struct { ServerNames []string NegotiatedProtocols []string NegotiatedProtocolIsMutual bool PeerCertificates []*x509.Certificate CipherSuites []uint16 Versions []uint16 Checks TLSMatcherChecks Handler func(net.Conn) (net.Conn, error) Description string }
TLSMatcher is a TLS connection inspector, that will verify the tls.ConnectionState fields described by Checks. If no verifications are enabled, TLSMatcher will simply match the presence of a TLS transport.
func NewTLSMatcher ¶
NewTLSMatcher returns a *TLSMatcher configured with the provided handler.
Example ¶
package main import ( "crypto/tls" "net" "github.com/joushou/serve2" "github.com/joushou/serve2/proto" "github.com/joushou/serve2/utils" ) func main() { server := serve2.New() handler := func(c net.Conn) (net.Conn, error) { return nil, utils.DialAndProxyTLS(c, "tcp", "http2.golang.org:443", &tls.Config{ NextProtos: []string{"h2", "h2-14"}, ServerName: "http2.golang.org", }) } tls, err := proto.NewTLS([]string{"h2", "h2-14"}, "cert.pem", "key.pem") if err != nil { panic(err) } server.AddHandlers(tls) tm := proto.NewTLSMatcher(handler) tm.NegotiatedProtocols = []string{"h2", "h2-14"} tm.Checks = proto.TLSCheckNegotiatedProtocol tm.Description = "HTTP2" server.AddHandlers(tm) l, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } server.Serve(l) }
Output:
func (*TLSMatcher) Check ¶
func (tc *TLSMatcher) Check(_ []byte, hints []interface{}) (bool, int)
Check inspects the last transport hint, checking if it is a TLS transport.
func (*TLSMatcher) String ¶
func (tc *TLSMatcher) String() string
type TLSMatcherChecks ¶
type TLSMatcherChecks uint
TLSMatcherChecks is a bitmask describing what to verify.
const ( TLSCheckServerName TLSMatcherChecks = 1 << iota TLSCheckNegotiatedProtocol TLSCheckNegotiatedProtocolIsMutual TLSCheckClientCertificate TLSCheckCipherSuite TLSCheckVersion )
TLSMatcher verification flags.
func (TLSMatcherChecks) IsSet ¶
func (tcv TLSMatcherChecks) IsSet(other TLSMatcherChecks) bool
IsSet checks the bitmask for the given bit.