@@ -21,18 +21,13 @@ import (
2121 "crypto/tls"
2222 "io"
2323 "net"
24- "strings"
2524)
2625
2726// AddSNIRoute appends a route to the ipPort listener that routes to
2827// dest if the incoming TLS SNI server name is sni. If it doesn't
2928// match, rule processing continues for any additional routes on
3029// ipPort.
3130//
32- // By default, the proxy will route all ACME tls-sni-01 challenges
33- // received on ipPort to all SNI dests. You can disable ACME routing
34- // with AddStopACMESearch.
35- //
3631// The ipPort is any valid net.Listen TCP address.
3732func (p * Proxy ) AddSNIRoute (ipPort , sni string , dest Target ) {
3833 p .AddSNIMatchRoute (ipPort , equals (sni ), dest )
@@ -43,20 +38,8 @@ func (p *Proxy) AddSNIRoute(ipPort, sni string, dest Target) {
4338// matcher. If it doesn't match, rule processing continues for any
4439// additional routes on ipPort.
4540//
46- // By default, the proxy will route all ACME tls-sni-01 challenges
47- // received on ipPort to all SNI dests. You can disable ACME routing
48- // with AddStopACMESearch.
49- //
5041// The ipPort is any valid net.Listen TCP address.
5142func (p * Proxy ) AddSNIMatchRoute (ipPort string , matcher Matcher , dest Target ) {
52- cfg := p .configFor (ipPort )
53- if ! cfg .stopACME {
54- if len (cfg .acmeTargets ) == 0 {
55- p .addRoute (ipPort , & acmeMatch {cfg })
56- }
57- cfg .acmeTargets = append (cfg .acmeTargets , dest )
58- }
59-
6043 p .addRoute (ipPort , sniMatch {matcher : matcher , target : dest })
6144}
6245
@@ -69,14 +52,6 @@ func (p *Proxy) AddSNIRouteFunc(ipPort string, fn SNITargetFunc) {
6952 p .addRoute (ipPort , sniMatch {targetFunc : fn })
7053}
7154
72- // AddStopACMESearch prevents ACME probing of subsequent SNI routes.
73- // Any ACME challenges on ipPort for SNI routes previously added
74- // before this call will still be proxied to all possible SNI
75- // backends.
76- func (p * Proxy ) AddStopACMESearch (ipPort string ) {
77- p .configFor (ipPort ).stopACME = true
78- }
79-
8055type sniMatch struct {
8156 matcher Matcher
8257 target Target
@@ -102,79 +77,6 @@ func (m sniMatch) match(br *bufio.Reader) (Target, string) {
10277 return nil , ""
10378}
10479
105- // acmeMatch matches "*.acme.invalid" ACME tls-sni-01 challenges and
106- // searches for a Target in cfg.acmeTargets that has the challenge
107- // response.
108- type acmeMatch struct {
109- cfg * config
110- }
111-
112- func (m * acmeMatch ) match (br * bufio.Reader ) (Target , string ) {
113- sni := clientHelloServerName (br )
114- if ! strings .HasSuffix (sni , ".acme.invalid" ) {
115- return nil , ""
116- }
117-
118- // TODO: cache. ACME issuers will hit multiple times in a short
119- // burst for each issuance event. A short TTL cache + singleflight
120- // should have an excellent hit rate.
121- // TODO: maybe an acme-specific timeout as well?
122- // TODO: plumb context upwards?
123- ctx , cancel := context .WithCancel (context .Background ())
124- defer cancel ()
125-
126- ch := make (chan Target , len (m .cfg .acmeTargets ))
127- for _ , target := range m .cfg .acmeTargets {
128- go tryACME (ctx , ch , target , sni )
129- }
130- for range m .cfg .acmeTargets {
131- if target := <- ch ; target != nil {
132- return target , sni
133- }
134- }
135-
136- // No target was happy with the provided challenge.
137- return nil , ""
138- }
139-
140- func tryACME (ctx context.Context , ch chan <- Target , dest Target , sni string ) {
141- var ret Target
142- defer func () { ch <- ret }()
143-
144- conn , targetConn := net .Pipe ()
145- defer conn .Close ()
146- go dest .HandleConn (targetConn )
147-
148- deadline , ok := ctx .Deadline ()
149- if ok {
150- conn .SetDeadline (deadline )
151- }
152-
153- client := tls .Client (conn , & tls.Config {
154- ServerName : sni ,
155- InsecureSkipVerify : true ,
156- })
157- if err := client .Handshake (); err != nil {
158- // TODO: log?
159- return
160- }
161- certs := client .ConnectionState ().PeerCertificates
162- if len (certs ) == 0 {
163- // TODO: log?
164- return
165- }
166- // acme says the first cert offered by the server must match the
167- // challenge hostname.
168- if err := certs [0 ].VerifyHostname (sni ); err != nil {
169- // TODO: log?
170- return
171- }
172-
173- // Target presented what looks like a valid challenge
174- // response, send it back to the matcher.
175- ret = dest
176- }
177-
17880// clientHelloServerName returns the SNI server name inside the TLS ClientHello,
17981// without consuming any bytes from br.
18082// On any error, the empty string is returned.
0 commit comments