/*
-tofuproxy -- HTTP proxy with TLS certificates management
-Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU
+ manager, WARC/geminispace browser
+Copyright (C) 2021-2023 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
package tofuproxy
import (
- "context"
"crypto"
"crypto/tls"
"crypto/x509"
"fmt"
"log"
- "net"
"net/http"
- "strings"
"time"
- "go.cypherpunks.ru/ucspi"
- "go.stargrave.org/tofuproxy/fifos"
+ ttls "go.stargrave.org/tofuproxy/tls"
)
var (
log.Fatalln(err)
}
defer conn.Close()
- conn.Write([]byte(fmt.Sprintf(
- "%s %d %s\r\n\r\n",
- req.Proto,
- http.StatusOK, http.StatusText(http.StatusOK),
- )))
- host := strings.Split(req.Host, ":")[0]
+ fmt.Fprintf(
+ conn, "%s %d %s\r\n\r\n",
+ req.Proto, http.StatusOK, http.StatusText(http.StatusOK),
+ )
+ host, _, _ := ttls.SplitHostPort(req.Host)
hostCertsM.Lock()
keypair, ok := hostCerts[host]
if !ok || !keypair.cert.NotAfter.After(time.Now().Add(time.Hour)) {
- keypair = newKeypair(host, CACert, CAPrv)
+ keypair = newX509Keypair(host, CACert, CAPrv)
hostCerts[host] = keypair
}
hostCertsM.Unlock()
req.URL.Host = h.host
roundTrip(w, req)
}
-
-func dialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
- host := strings.Split(addr, ":")[0]
- ccg := ClientCertificateGetter{host: host}
- cfg := tls.Config{
- VerifyPeerCertificate: func(
- rawCerts [][]byte,
- verifiedChains [][]*x509.Certificate,
- ) error {
- return verifyCert(host, nil, rawCerts, verifiedChains)
- },
- ClientSessionCache: sessionCache,
- NextProtos: []string{"h2", "http/1.1"},
- GetClientCertificate: ccg.get,
- }
- conn, dialErr := tls.Dial(network, addr, &cfg)
- if dialErr != nil {
- if _, ok := dialErr.(ErrRejected); ok {
- return nil, dialErr
- }
- cfg.InsecureSkipVerify = true
- cfg.VerifyPeerCertificate = func(
- rawCerts [][]byte,
- verifiedChains [][]*x509.Certificate,
- ) error {
- return verifyCert(host, dialErr, rawCerts, verifiedChains)
- }
- var err error
- conn, err = tls.Dial(network, addr, &cfg)
- if err != nil {
- fifos.LogErr <- fmt.Sprintf("%s\t%s", addr, dialErr.Error())
- return nil, err
- }
- }
- connState := conn.ConnectionState()
- if !connState.DidResume {
- fifos.LogTLS <- fmt.Sprintf(
- "%s\t%s %s %s\t%s\t%s",
- addr,
- ucspi.TLSVersion(connState.Version),
- tls.CipherSuiteName(connState.CipherSuite),
- connState.PeerCertificates[0].SignatureAlgorithm,
- spkiHash(connState.PeerCertificates[0]),
- connState.NegotiatedProtocol,
- )
- }
- return conn, nil
-}