KarpelesLab / magictls

Automatic support of PROXY PROXYv2 and TLS support on TCP streams

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MagicTLS

Build Status GoDoc

A simple Go library that detects protocol automatically:

  • Support for PROXY and PROXYv2 allows detecting the real user's IP when, for example, using AWS elastic load balancers. The fact the protocol is detected automatically allows the daemon to work even before ELB is properly configured, and avoid rejecting requests by mistake.
  • Automatic TLS support allows using a single port for SSL and non-SSL traffic, and simplifies configuration.
  • Allows creating listener for specific TLS negociated protocols, allowing a single port to be used for many things easily.

This library was used in some of my projects, I've cleaned it up and licensed it under the MIT License since it's small and useful. Pull requests welcome.

It is written to work with protocols where the client sends the first data, and it expects the client to send at least 16 bytes. This works nicely with HTTP (GET / HTTP/1.0\r\n is exactly 16 bytes), SSL, etc. but may not work with protocols such as POP3, IMAP or SMTP where the server is expected to send the first bytes unless TLS is required. In this case using the ForceTLS filter only allows to still benefit from the TLS NextProto routing.

Usage

Use magictls.Listen() to create sockets the same way you would use tls.Listen().

socket, err := magictls.Listen("tcp", ":8080", tlsConfig)
if err != nil {
	...
}
log.Fatal(http.Serve(socket, handler))

The created listener can receive various configurations. For example if you need to force all connections to be TLS and only want to use PROXY protocol detection:

socket, err := magictls.Listen("tcp", ":8443", tlsConfig)
if err != nil {
	...
}
socket.Filters = []magictls.Filter{magictls.DetectProxy, magictls.ForceTLS}
log.Fatal(http.Serve(socket, handler))

It is also possible to implement your own filters.

autocert

This can be used with autocert too for automatic TLS certificates. Note that in this case you are required to have a listener on port 443.

// initialize autocert structure
m := &autocert.Manager{
	Prompt: autocert.AcceptTOS,
	HostPolicy: autocert.HostWhitelist("domain", "domain2"),
	Cache: autocert.DirCache("/tmp"), // use os.UserCacheDir() to find where to put that
}
// grab autocert TLS config
cfg := m.TLSConfig()
// you may want to add to cfg.NextProtos any protocol you want to handle with ProtoListener. Be careful to not overwrite it.
cfg.NextProtos = append(cfg.NextProtos, "my-proto")
// standard listen
socket, err := magictls.Listen("tcp", ":443", cfg)
if err != nil {
	...
}
...

About

Automatic support of PROXY PROXYv2 and TLS support on TCP streams

License:MIT License


Languages

Language:Go 98.9%Language:Makefile 1.1%