From c0721295c9149aab3c0c19d7adc232abf9960aa4 Mon Sep 17 00:00:00 2001 From: TeoV Date: Tue, 29 May 2018 05:33:23 -0400 Subject: [PATCH] Add TLS Authentification --- cmd/cgr-console/cgr-console.go | 39 ++++++++++++++++++++ cmd/cgr-engine/cgr-engine.go | 1 + utils/server.go | 66 ++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index a7b7e3bb0..fa44b5f2b 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -19,11 +19,14 @@ along with this program. If not, see package main import ( + "crypto/tls" + "crypto/x509" "encoding/json" "flag" "fmt" "io" "log" + "net/rpc" "os" "sort" "strings" @@ -42,6 +45,7 @@ var ( server = flag.String("server", "127.0.0.1:2012", "server address host:port") rpc_encoding = flag.String("rpc_encoding", "json", "RPC encoding used ") client *rpcclient.RpcClient + client2 *rpc.Client ) func executeCommand(command string) { @@ -109,6 +113,15 @@ func executeCommand(command string) { result, _ := json.MarshalIndent(res, "", " ") fmt.Println(string(result)) } + + //TLS call + if rpcErr := client2.Call(cmd.RpcMethod(), param, res); rpcErr != nil { + fmt.Println("Error executing command: " + rpcErr.Error()) + } else { + result, _ := json.MarshalIndent(res, "", " ") + fmt.Println(string(result)) + } + // } else { fmt.Println(cmd.LocalExecute()) } @@ -128,6 +141,32 @@ func main() { log.Fatal("Could not connect to server " + *server) } + //TLS connection + cert, err := tls.LoadX509KeyPair("/home/teo/go/src/github.com/TeoV/GoRPCServerClientOverTLS/client1.crt", + "/home/teo/go/src/github.com/TeoV/GoRPCServerClientOverTLS/client.key") + if err != nil { + log.Fatalf("Error: %s when load client keys", err) + } + if len(cert.Certificate) != 2 { + log.Fatal("client1.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}, + //InsecureSkipVerify: true, + RootCAs: certPool, + } + conn, err := tls.Dial("tcp", "localhost:2022", &config) + if err != nil { + log.Fatalf("Error: %s when dialing", err) + } + client2 = rpc.NewClient(conn) + // if len(flag.Args()) != 0 { executeCommand(strings.Join(flag.Args(), " ")) return diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index e87f9de91..b8189a904 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -844,6 +844,7 @@ func startRpc(server *utils.Server, internalRaterChan, cfg.HTTPUseBasicAuth, cfg.HTTPAuthUsers, ) + go server.ServeTLS(cfg.RPCJSONListen) } func writePid() { diff --git a/utils/server.go b/utils/server.go index 6198a42b4..e1ad5d328 100644 --- a/utils/server.go +++ b/utils/server.go @@ -20,6 +20,9 @@ package utils import ( "bytes" + "crypto/rand" + "crypto/tls" + "crypto/x509" "fmt" "io" "log" @@ -275,3 +278,66 @@ func (r *rpcRequest) Call() io.Reader { <-r.done return r.rw } + +func (s *Server) ServeTLS(addr string) { + s.RLock() + enabled := s.rpcEnabled + s.RUnlock() + if !enabled { + return + } + + cert, err := tls.LoadX509KeyPair("/home/teo/go/src/github.com/TeoV/GoRPCServerClientOverTLS/server1.crt", + "/home/teo/go/src/github.com/TeoV/GoRPCServerClientOverTLS/server.key") + if err != nil { + log.Fatalf("Error: %s when load server keys", err) + } + + if len(cert.Certificate) != 2 { + log.Fatal("server1.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 := ":2022" + listener, err := tls.Listen("tcp", service, &config) + if err != nil { + log.Fatalf("Error: %s when listening", err) + } + + Logger.Info(fmt.Sprintf("Starting CGRateS TLS server at <%s>.", service)) + errCnt := 0 + var lastErrorTime time.Time + for { + conn, err := listener.Accept() + defer conn.Close() + if err != nil { + Logger.Err(fmt.Sprintf(" TLS accept error: <%s>", err.Error())) + now := time.Now() + if now.Sub(lastErrorTime) > time.Duration(5*time.Second) { + errCnt = 0 // reset error count if last error was more than 5 seconds ago + } + lastErrorTime = time.Now() + errCnt += 1 + if errCnt > 50 { // Too many errors in short interval, network buffer failure most probably + break + } + continue + } + //utils.Logger.Info(fmt.Sprintf(" New incoming connection: %v", conn.RemoteAddr())) + go rpc.ServeConn(conn) + } + +}