Last active
October 9, 2023 15:44
-
-
Save artyom/6897140 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Would it be possible to do this with certificates generated with LetsEncrypt?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'd like to know which modifications would be needed if there are intermediate certificates. How would the tls.Config change in that case?