summaryrefslogtreecommitdiff
path: root/sni.go
diff options
context:
space:
mode:
Diffstat (limited to 'sni.go')
-rw-r--r--sni.go98
1 files changed, 0 insertions, 98 deletions
diff --git a/sni.go b/sni.go
index eb826d4..c2d37e0 100644
--- a/sni.go
+++ b/sni.go
@@ -21,7 +21,6 @@ import (
"crypto/tls"
"io"
"net"
- "strings"
)
// AddSNIRoute appends a route to the ipPort listener that routes to
@@ -29,10 +28,6 @@ import (
// match, rule processing continues for any additional routes on
// ipPort.
//
-// By default, the proxy will route all ACME tls-sni-01 challenges
-// received on ipPort to all SNI dests. You can disable ACME routing
-// with AddStopACMESearch.
-//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddSNIRoute(ipPort, sni string, dest Target) {
p.AddSNIMatchRoute(ipPort, equals(sni), dest)
@@ -43,20 +38,8 @@ func (p *Proxy) AddSNIRoute(ipPort, sni string, dest Target) {
// matcher. If it doesn't match, rule processing continues for any
// additional routes on ipPort.
//
-// By default, the proxy will route all ACME tls-sni-01 challenges
-// received on ipPort to all SNI dests. You can disable ACME routing
-// with AddStopACMESearch.
-//
// The ipPort is any valid net.Listen TCP address.
func (p *Proxy) AddSNIMatchRoute(ipPort string, matcher Matcher, dest Target) {
- cfg := p.configFor(ipPort)
- if !cfg.stopACME {
- if len(cfg.acmeTargets) == 0 {
- p.addRoute(ipPort, &acmeMatch{cfg})
- }
- cfg.acmeTargets = append(cfg.acmeTargets, dest)
- }
-
p.addRoute(ipPort, sniMatch{matcher: matcher, target: dest})
}
@@ -69,14 +52,6 @@ func (p *Proxy) AddSNIRouteFunc(ipPort string, fn SNITargetFunc) {
p.addRoute(ipPort, sniMatch{targetFunc: fn})
}
-// AddStopACMESearch prevents ACME probing of subsequent SNI routes.
-// Any ACME challenges on ipPort for SNI routes previously added
-// before this call will still be proxied to all possible SNI
-// backends.
-func (p *Proxy) AddStopACMESearch(ipPort string) {
- p.configFor(ipPort).stopACME = true
-}
-
type sniMatch struct {
matcher Matcher
target Target
@@ -102,79 +77,6 @@ func (m sniMatch) match(br *bufio.Reader) (Target, string) {
return nil, ""
}
-// acmeMatch matches "*.acme.invalid" ACME tls-sni-01 challenges and
-// searches for a Target in cfg.acmeTargets that has the challenge
-// response.
-type acmeMatch struct {
- cfg *config
-}
-
-func (m *acmeMatch) match(br *bufio.Reader) (Target, string) {
- sni := clientHelloServerName(br)
- if !strings.HasSuffix(sni, ".acme.invalid") {
- return nil, ""
- }
-
- // TODO: cache. ACME issuers will hit multiple times in a short
- // burst for each issuance event. A short TTL cache + singleflight
- // should have an excellent hit rate.
- // TODO: maybe an acme-specific timeout as well?
- // TODO: plumb context upwards?
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- ch := make(chan Target, len(m.cfg.acmeTargets))
- for _, target := range m.cfg.acmeTargets {
- go tryACME(ctx, ch, target, sni)
- }
- for range m.cfg.acmeTargets {
- if target := <-ch; target != nil {
- return target, sni
- }
- }
-
- // No target was happy with the provided challenge.
- return nil, ""
-}
-
-func tryACME(ctx context.Context, ch chan<- Target, dest Target, sni string) {
- var ret Target
- defer func() { ch <- ret }()
-
- conn, targetConn := net.Pipe()
- defer conn.Close()
- go dest.HandleConn(targetConn)
-
- deadline, ok := ctx.Deadline()
- if ok {
- conn.SetDeadline(deadline)
- }
-
- client := tls.Client(conn, &tls.Config{
- ServerName: sni,
- InsecureSkipVerify: true,
- })
- if err := client.Handshake(); err != nil {
- // TODO: log?
- return
- }
- certs := client.ConnectionState().PeerCertificates
- if len(certs) == 0 {
- // TODO: log?
- return
- }
- // acme says the first cert offered by the server must match the
- // challenge hostname.
- if err := certs[0].VerifyHostname(sni); err != nil {
- // TODO: log?
- return
- }
-
- // Target presented what looks like a valid challenge
- // response, send it back to the matcher.
- ret = dest
-}
-
// clientHelloServerName returns the SNI server name inside the TLS ClientHello,
// without consuming any bytes from br.
// On any error, the empty string is returned.