Created
July 20, 2024 11:57
-
-
Save BhautikChudasama/fb264c6f6e683aa09563493fe1e6048a to your computer and use it in GitHub Desktop.
mTLS and get connection information at server side with RPC
This file contains hidden or 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" | |
| "os" | |
| ) | |
| type Args struct { | |
| A, B int | |
| } | |
| func main() { | |
| // Load client's certificate and private key | |
| cert, err := tls.LoadX509KeyPair("/Users/bhautik/workspace/src/ca-cert/certs/client.a.crt", "/Users/bhautik/workspace/src/ca-cert/certs/client.a.key") | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // Load CA certificate | |
| caCert, err := os.ReadFile("/Users/bhautik/workspace/src/ca-cert/certs/ca.crt") | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| caCertPool := x509.NewCertPool() | |
| caCertPool.AppendCertsFromPEM(caCert) | |
| // Create TLS configuration | |
| tlsConfig := &tls.Config{ | |
| RootCAs: caCertPool, | |
| Certificates: []tls.Certificate{cert}, | |
| } | |
| // Connect to server | |
| conn, err := tls.Dial("tcp", "localhost:12345", tlsConfig) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| defer conn.Close() | |
| // Log TLS connection state | |
| state := conn.ConnectionState() | |
| log.Println("Client-side connection state:") | |
| for i, cert := range state.PeerCertificates { | |
| log.Printf("Peer Certificate %d: %s", i+1, cert.Subject) | |
| } | |
| // Create new RPC client | |
| client := rpc.NewClient(conn) | |
| // Perform RPC call | |
| args := Args{A: 7, B: 8} | |
| var reply int | |
| err = client.Call("Arith.Multiply", args, &reply) | |
| if err != nil { | |
| log.Fatal("arith error:", err) | |
| } | |
| log.Printf("Arith: %d*%d=%d", args.A, args.B, reply) | |
| } |
This file contains hidden or 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 provider_server | |
| import ( | |
| "crypto/tls" | |
| "crypto/x509" | |
| "fmt" | |
| "log" | |
| "net" | |
| "net/rpc" | |
| "os" | |
| "..." | |
| "gopkg.in/yaml.v3" | |
| ) | |
| type ProviderServer struct { | |
| Config config.ProviderServerConfig | |
| Logger sdklogging.Logger | |
| } | |
| func NewProviderServer(configFilePath string) (*ProviderServer, error) { | |
| return &ProviderServer{}, err | |
| } | |
| type Arith struct { | |
| conn net.Conn | |
| } | |
| func (t *Arith) Multiply(args *Args, reply *int) error { | |
| state, bool := GetTLSState(t.conn) | |
| if !bool { | |
| log.Printf("Connection is not a TLS connection") | |
| return nil | |
| } | |
| for _, v := range state.PeerCertificates { | |
| fmt.Printf("Client certificate: %v\n", v.Subject) | |
| } | |
| *reply = args.A * args.B | |
| return nil | |
| } | |
| type Args struct { | |
| A, B int | |
| } | |
| type ConnWrapper struct { | |
| net.Conn | |
| TLSState tls.ConnectionState | |
| } | |
| func WrapConn(conn net.Conn, tlsState tls.ConnectionState) net.Conn { | |
| return &ConnWrapper{ | |
| Conn: conn, | |
| TLSState: tlsState, | |
| } | |
| } | |
| func GetTLSState(conn net.Conn) (tls.ConnectionState, bool) { | |
| if wrapper, ok := conn.(*ConnWrapper); ok { | |
| return wrapper.TLSState, true | |
| } | |
| return tls.ConnectionState{}, false | |
| } | |
| func (ps *ProviderServer) StartRPCServer() error { | |
| cert, err := tls.LoadX509KeyPair("/Users/bhautik/workspace/src/ca-cert/certs/server.crt", "/Users/bhautik/workspace/src/ca-cert/certs/server.key") | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // Load CA certificate | |
| caCert, err := os.ReadFile("/Users/bhautik/workspace/src/ca-cert/certs/ca.crt") | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| caCertPool := x509.NewCertPool() | |
| caCertPool.AppendCertsFromPEM(caCert) | |
| tlsConfig := &tls.Config{ | |
| Certificates: []tls.Certificate{cert}, | |
| ClientCAs: caCertPool, | |
| ClientAuth: tls.RequireAndVerifyClientCert, | |
| VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { | |
| // Write logic to verify the client certificate | |
| return nil | |
| }, | |
| } | |
| listener, err := tls.Listen("tcp", ":12345", tlsConfig) | |
| if err != nil { | |
| log.Fatal("Listen error:", err) | |
| } | |
| defer listener.Close() | |
| for { | |
| conn, err := listener.Accept() | |
| if err != nil { | |
| log.Printf("Accept error: %v", err) | |
| continue | |
| } | |
| tlsConn, ok := conn.(*tls.Conn) | |
| if !ok { | |
| log.Printf("Connection is not a TLS connection") | |
| conn.Close() | |
| continue | |
| } | |
| if err := tlsConn.Handshake(); err != nil { | |
| continue | |
| } | |
| state := tlsConn.ConnectionState() | |
| wrappedConn := WrapConn(tlsConn, state) | |
| go func() { | |
| arith := &Arith{conn: wrappedConn} | |
| rpc.Register(arith) | |
| rpc.ServeConn(wrappedConn) | |
| }() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment