-
-
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 joe@random.com | |
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") | |
} |
You might want to remove line 30 in server.go, it will cause memory leak.
to add on this, the defer will not terminate because it is within a for loop. Indeed it is preferable to either undefer the statement, or wrap the for body loop within a func(){}() call.
What's with line 57 and 59 in the server code?
looks likes it is duplicated.
you do not want to have the defer in the loop
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.
What's with line 57 and 59 in the server code?