2 tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU
3 manager, WARC/geminispace browser
4 Copyright (C) 2021-2023 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/>.
28 "go.cypherpunks.ru/ucspi"
29 "go.stargrave.org/tofuproxy/fifos"
32 var sessionCache = tls.NewLRUClientSessionCache(1024)
34 func DialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
35 host, _, _ := SplitHostPort(addr)
36 ccg := ClientCertificateGetter{host: host}
38 VerifyPeerCertificate: func(
40 verifiedChains [][]*x509.Certificate,
42 return verifyCert(host, nil, rawCerts, verifiedChains)
44 ClientSessionCache: sessionCache,
45 NextProtos: []string{"h2", "http/1.1"},
46 GetClientCertificate: ccg.get,
48 conn, dialErr := tls.Dial(network, addr, &cfg)
50 if _, ok := dialErr.(ErrRejected); ok {
53 cfg.InsecureSkipVerify = true
54 cfg.VerifyPeerCertificate = func(
56 verifiedChains [][]*x509.Certificate,
58 return verifyCert(host, dialErr, rawCerts, verifiedChains)
61 conn, err = tls.Dial(network, addr, &cfg)
63 fifos.LogErr <- fmt.Sprintf("%s\t%s", addr, dialErr.Error())
67 connState := conn.ConnectionState()
68 if !connState.DidResume {
69 fifos.LogTLS <- fmt.Sprintf(
70 "%s\t%s %s %s\t%s\t%s",
72 ucspi.TLSVersion(connState.Version),
73 tls.CipherSuiteName(connState.CipherSuite),
74 connState.PeerCertificates[0].SignatureAlgorithm,
75 spkiHash(connState.PeerCertificates[0]),
76 connState.NegotiatedProtocol,