From eb8c9e0c0381d38b53792af6ee8c50c16450b913 Mon Sep 17 00:00:00 2001 From: adnano Date: Fri, 25 Sep 2020 10:09:41 -0400 Subject: [PATCH] Update README.md --- README.md | 32 ++++++++++++++++++++++++++++++-- examples/server/server.go | 7 +++++++ gemini.go | 4 ++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 95ae18a..666f6b0 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,9 @@ A quick overview of the Gemini protocol: The way this is implemented in this package is like so: -1. Client makes a request with `gemini.Get`. - There is currently no way to validate server certificates before sending a request. +1. Client makes a request with `NewRequest`. The client can verify server + certificates in the Request options, see [Recommended TLS + configuration](#recommended-tls-configuration). 2. Server recieves the request and constructs a response. The server calls the `Serve(*ResponseWriter, *Request)` method on the `Handler` field. The handler writes the response. The server then closes @@ -41,3 +42,30 @@ The way this is implemented in this package is like so: 5. Client recieves the response as a `*Response`. The client then handles the response. The client can now verify the certificate of the server using a Trust-On-First-Use method. + +## Recommended TLS configuration + +For clients, the recommended TLS configuration is as follows: + +```go +// Accept self-signed server certificates +req.TLSConfig.InsecureSkipVerify = true +// Manually verify server certificates, using TOFU +req.TLSConfig.VerifyPeerCertificate = func(rawCerts [][]byte, chains [][]*x509.Certificate) error { + // Verify the server certificate here + // Return an error on failure, or nil on success + return nil +} +``` + +Note that `gemini.Get` does not verify server certificates. + +For servers, the recommended TLS configuration is as follows: + +```go +// Specify a certificate +// To load a certificate, use `tls.LoadX509KeyPair`. +srv.TLSConfig.Certificates = append(srv.TLSConfig.Certificates, cert) +// Request client certificates +srv.TLSConfig.ClientAuth = tls.RequestClientCert +``` diff --git a/examples/server/server.go b/examples/server/server.go index 985f33f..466d024 100644 --- a/examples/server/server.go +++ b/examples/server/server.go @@ -4,6 +4,7 @@ package main import ( "crypto/tls" + "crypto/x509" "log" "git.sr.ht/~adnano/go-gemini" @@ -24,8 +25,14 @@ func main() { } config.Certificates = append(config.Certificates, cert) config.ClientAuth = tls.RequestClientCert + config.VerifyPeerCertificate = func(rawCerts [][]byte, chains [][]*x509.Certificate) error { + return nil + } mux := &gemini.ServeMux{} + mux.HandleFunc("/cert", func(rw *gemini.ResponseWriter, req *gemini.Request) { + rw.WriteHeader(gemini.StatusClientCertificateRequired, "Certificate required") + }) mux.HandleFunc("/", func(rw *gemini.ResponseWriter, req *gemini.Request) { log.Printf("Request from %s for %s with certificates %v", req.RemoteAddr.String(), req.URL.String(), req.TLS.PeerCertificates) rw.WriteHeader(gemini.StatusSuccess, "text/gemini") diff --git a/gemini.go b/gemini.go index de2f898..f94c01e 100644 --- a/gemini.go +++ b/gemini.go @@ -165,11 +165,14 @@ type Response struct { } // Get makes a request for the provided URL. The host is inferred from the URL. +// +// Get does not verify server certificates. To verify certificates, use a Request. func Get(url string) (*Response, error) { req, err := NewRequest(url) if err != nil { return nil, err } + req.TLSConfig.InsecureSkipVerify = true return Do(req) } @@ -179,6 +182,7 @@ func ProxyGet(host, url string) (*Response, error) { if err != nil { return nil, err } + req.TLSConfig.InsecureSkipVerify = true return Do(req) }