-
Star
(170)
You must be signed in to star a gist -
Fork
(71)
You must be signed in to fork a gist
-
-
Save spikebike/2232102 to your computer and use it in GitHub Desktop.
| package main | |
| import ( | |
| "crypto/tls" | |
| "crypto/x509" | |
| "fmt" | |
| "io" | |
| "log" | |
| ) | |
| func main() { | |
| cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key") | |
| if err != nil { | |
| log.Fatalf("server: loadkeys: %s", err) | |
| } | |
| config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} | |
| conn, err := tls.Dial("tcp", "127.0.0.1:8000", &config) | |
| if err != nil { | |
| log.Fatalf("client: dial: %s", err) | |
| } | |
| defer conn.Close() | |
| log.Println("client: connected to: ", conn.RemoteAddr()) | |
| state := conn.ConnectionState() | |
| for _, v := range state.PeerCertificates { | |
| fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey)) | |
| fmt.Println(v.Subject) | |
| } | |
| log.Println("client: handshake: ", state.HandshakeComplete) | |
| log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual) | |
| message := "Hello\n" | |
| n, err := io.WriteString(conn, message) | |
| if err != nil { | |
| log.Fatalf("client: write: %s", err) | |
| } | |
| log.Printf("client: wrote %q (%d bytes)", message, n) | |
| reply := make([]byte, 256) | |
| n, err = conn.Read(reply) | |
| log.Printf("client: read %q (%d bytes)", string(reply[:n]), n) | |
| log.Print("client: exiting") | |
| } |
| #!/bin/bash | |
| # call this script with an email address (valid or not). | |
| # like: | |
| # ./makecert.sh [email protected] | |
| mkdir certs | |
| rm certs/* | |
| echo "make server cert" | |
| openssl req -new -nodes -x509 -out certs/server.pem -keyout certs/server.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1" | |
| echo "make client cert" | |
| openssl req -new -nodes -x509 -out certs/client.pem -keyout certs/client.key -days 3650 -subj "/C=DE/ST=NRW/L=Earth/O=Random Company/OU=IT/CN=www.random.com/emailAddress=$1" |
| package main | |
| import ( | |
| "crypto/rand" | |
| "crypto/tls" | |
| "log" | |
| "net" | |
| "crypto/x509" | |
| ) | |
| func main() { | |
| cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key") | |
| if err != nil { | |
| log.Fatalf("server: loadkeys: %s", err) | |
| } | |
| config := tls.Config{Certificates: []tls.Certificate{cert}} | |
| config.Rand = rand.Reader | |
| service := "0.0.0.0:8000" | |
| listener, err := tls.Listen("tcp", service, &config) | |
| if err != nil { | |
| log.Fatalf("server: listen: %s", err) | |
| } | |
| log.Print("server: listening") | |
| for { | |
| conn, err := listener.Accept() | |
| if err != nil { | |
| log.Printf("server: accept: %s", err) | |
| break | |
| } | |
| defer conn.Close() | |
| log.Printf("server: accepted from %s", conn.RemoteAddr()) | |
| tlscon, ok := conn.(*tls.Conn) | |
| if ok { | |
| log.Print("ok=true") | |
| state := tlscon.ConnectionState() | |
| for _, v := range state.PeerCertificates { | |
| log.Print(x509.MarshalPKIXPublicKey(v.PublicKey)) | |
| } | |
| } | |
| go handleClient(conn) | |
| } | |
| } | |
| func handleClient(conn net.Conn) { | |
| defer conn.Close() | |
| buf := make([]byte, 512) | |
| for { | |
| log.Print("server: conn: waiting") | |
| n, err := conn.Read(buf) | |
| if err != nil { | |
| if err != nil { | |
| log.Printf("server: conn: read: %s", err) | |
| } | |
| break | |
| } | |
| log.Printf("server: conn: echo %q\n", string(buf[:n])) | |
| n, err = conn.Write(buf[:n]) | |
| n, err = conn.Write(buf[:n]) | |
| log.Printf("server: conn: wrote %d bytes", n) | |
| if err != nil { | |
| log.Printf("server: write: %s", err) | |
| break | |
| } | |
| } | |
| log.Println("server: conn: closed") | |
| } |
In server.go, conn.Close() is called twice - in main() (line 30), and in handleClient() (line 45).
I think the purpose of this snippet is also to have the server require and verify the client's certificate, which must be configured in the server's TLS config:
ClientAuth: tls.RequireAndVerifyClientCert
Thank you, it's really help!
I'm using go version go1.5.1 linux/amd64 , the conversion on line 32 of server.go works but tlscon is always empty. Any ideas why?
In server.go file after the line: log.Print("ok=true"), insert
err = tlscon.Handshake()
if err != nil {
log.Fatalf("Handshake error: %s", err)
}
server.go:17: config.Rand = rand.Reader is not necessary from go1.19 or later at least (and likely not necessary in earlier go versions either). Note that the documentation for tls.Config.Rand says:
If Rand is nil, TLS uses the cryptographic random reader in package crypto/rand.
you do not want to have the defer in the loop