Skip to content

Instantly share code, notes, and snippets.

@junftnt
Forked from artyom/rpc-tls-client.go
Created July 30, 2019 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save junftnt/beaadca3925aa350f606190e8e293d54 to your computer and use it in GitHub Desktop.
Save junftnt/beaadca3925aa350f606190e8e293d54 to your computer and use it in GitHub Desktop.
Go RPC over TLS.You have to create the following keys: certs/client.crt, certs/client.key, certs/server.crt, certs/server.key. client.crt and server.crt should be signed with ca.crt, which should be concatenated to both client.crt and server.crt. It's easier to do with easy-rsa: http://openvpn.net/index.php/open-source/documentation/howto.html#pki
package main
import (
"crypto/tls"
"crypto/x509"
"log"
"net/rpc"
)
func main() {
cert, err := tls.LoadX509KeyPair("certs/client.crt", "certs/client.key")
if err != nil {
log.Fatalf("client: loadkeys: %s", err)
}
if len(cert.Certificate) != 2 {
log.Fatal("client.crt should have 2 concatenated certificates: client + CA")
}
ca, err := x509.ParseCertificate(cert.Certificate[1])
if err != nil {
log.Fatal(err)
}
certPool := x509.NewCertPool()
certPool.AddCert(ca)
config := tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: certPool,
}
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())
rpcClient := rpc.NewClient(conn)
res := new(Result)
if err := rpcClient.Call("Foo.Bar", "twenty-three", &res); err != nil {
log.Fatal("Failed to call RPC", err)
}
log.Printf("Returned result is %d", res.Data)
}
type Result struct {
Data int
}
package main
import (
"crypto/rand"
"crypto/tls"
"crypto/x509"
//"fmt"
"log"
"net"
"net/rpc"
)
func main() {
if err := rpc.Register(new(Foo)); err != nil {
log.Fatal("Failed to register RPC method")
}
cert, err := tls.LoadX509KeyPair("certs/server.crt", "certs/server.key")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
if len(cert.Certificate) != 2 {
log.Fatal("server.crt should have 2 concatenated certificates: server + CA")
}
ca, err := x509.ParseCertificate(cert.Certificate[1])
if err != nil {
log.Fatal(err)
}
certPool := x509.NewCertPool()
certPool.AddCert(ca)
config := tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
}
config.Rand = rand.Reader
service := "127.0.0.1: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
}
log.Printf("server: accepted from %s", conn.RemoteAddr())
go handleClient(conn)
}
}
func handleClient(conn net.Conn) {
defer conn.Close()
rpc.ServeConn(conn)
log.Println("server: conn: closed")
}
type Foo bool
type Result struct {
Data int
}
func (f *Foo) Bar(args *string, res *Result) error {
res.Data = len(*args)
log.Printf("Received %q, its length is %d", *args, res.Data)
//return fmt.Errorf("Whoops, error happened")
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment