-
Star
(168)
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") | |
} |
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.
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.
looks likes it is duplicated.