2 tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU
3 manager, WARC/geminispace browser
4 Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3 of the License.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 "go.cypherpunks.ru/ucspi"
30 "go.stargrave.org/tofuproxy/fifos"
33 var sessionCache = tls.NewLRUClientSessionCache(1024)
35 func DialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
36 host := strings.Split(addr, ":")[0]
37 ccg := ClientCertificateGetter{host: host}
39 VerifyPeerCertificate: func(
41 verifiedChains [][]*x509.Certificate,
43 return verifyCert(host, nil, rawCerts, verifiedChains)
45 ClientSessionCache: sessionCache,
46 NextProtos: []string{"h2", "http/1.1"},
47 GetClientCertificate: ccg.get,
49 conn, dialErr := tls.Dial(network, addr, &cfg)
51 if _, ok := dialErr.(ErrRejected); ok {
54 cfg.InsecureSkipVerify = true
55 cfg.VerifyPeerCertificate = func(
57 verifiedChains [][]*x509.Certificate,
59 return verifyCert(host, dialErr, rawCerts, verifiedChains)
62 conn, err = tls.Dial(network, addr, &cfg)
64 fifos.LogErr <- fmt.Sprintf("%s\t%s", addr, dialErr.Error())
68 connState := conn.ConnectionState()
69 if !connState.DidResume {
70 fifos.LogTLS <- fmt.Sprintf(
71 "%s\t%s %s %s\t%s\t%s",
73 ucspi.TLSVersion(connState.Version),
74 tls.CipherSuiteName(connState.CipherSuite),
75 connState.PeerCertificates[0].SignatureAlgorithm,
76 spkiHash(connState.PeerCertificates[0]),
77 connState.NegotiatedProtocol,