Ravat Tailor
Ravat Tailor

Reputation: 1263

NATS Client: An error occurred during encode or decode operation

I am creating the certificate and starting nats server with those certificates for tls connection.

But when I am trying to connect nats with InsucreSkipVerify: false, I am getting an error.

An error occurred during encode or decode operation.

Generating certificate: https://go.dev/src/crypto/tls/generate_cert.go

I tried to debug the nats code, I am getting an error while handshake but not able to find from where exactly the above error is comming.

NATS Server.

serverCert, serverErr := tls.LoadX509KeyPair("certfile", "keyfile")
opts.TLSConfig = &tls.Config{
        Certificates: []tls.Certificate{serverCert},
 }
ns, err = server.NewServer(opts)
go ns.Start()

NATS Client:

conn, err := nats.Connect("tls://127.0.0.1:4222", nats.Secure(&tls.Config{
    //Certificates:       []tls.Certificate{clientCert},
    InsecureSkipVerify: false,
  }))
fmt.Println(err)

I am able to start nats server successfully, but when trying to make client connection getting an error:

An error occurred during encode or decode operation.

Upvotes: 1

Views: 466

Answers (1)

Byron Ruth
Byron Ruth

Reputation: 987

here is an example on how to setup mTLS with an embedded server and a client (source here).

package main

import (
    "flag"
    "fmt"
    "log"
    "time"

    "github.com/nats-io/nats-server/v2/server"
    "github.com/nats-io/nats.go"
)

func main() {
    var (
        host           string
        port           int
        certFile       string
        keyFile        string
        clientCertFile string
        clientKeyFile  string
        caFile         string
    )

    flag.StringVar(&host, "host", "localhost", "Client connection host/IP.")
    flag.IntVar(&port, "port", 4222, "Client connection port.")
    flag.StringVar(&certFile, "tls.cert.server", "cert.pem", "TLS cert file.")
    flag.StringVar(&keyFile, "tls.key.server", "key.pem", "TLS key file.")
    flag.StringVar(&caFile, "tls.ca", "ca.pem", "TLS CA file.")
    flag.StringVar(&clientCertFile, "tls.cert.client", "client-cert.pem", " Client TLS cert file.")
    flag.StringVar(&clientKeyFile, "tls.key.client", "client-key.pem", "Client TLS key file.")

    flag.Parse()

    serverTlsConfig, err := server.GenTLSConfig(&server.TLSConfigOpts{
        CertFile: certFile,
        KeyFile:  keyFile,
        CaFile:   caFile,
        Verify:   true,
        Timeout:  2,
    })
    if err != nil {
        log.Fatalf("tls config: %v", err)
    }

    // Setup the embedded server options.
    opts := server.Options{
        Host:      host,
        Port:      port,
        TLSConfig: serverTlsConfig,
    }

    // Initialize a new server with the options.
    ns, err := server.NewServer(&opts)
    if err != nil {
        log.Fatalf("server init: %v", err)
    }

    // Start the server.
    go ns.Start()
    defer ns.Shutdown()

    // Allow the server to startup before creating the connection.
    time.Sleep(time.Second)

    // Create a client connection.
    nc, err := nats.Connect(
        fmt.Sprintf("tls://%s:%d", host, port),
        nats.RootCAs(caFile),
        nats.ClientCert(clientCertFile, clientKeyFile),
    )
    if err != nil {
        log.Fatalf("client connect: %v", err)
    }
    defer nc.Drain()

    // Setup a basic subscription, publish, and print it.
    sub, _ := nc.SubscribeSync("hello")
    defer sub.Drain()

    nc.Publish("hello", []byte("world"))

    msg, _ := sub.NextMsg(time.Second)
    fmt.Println(string(msg.Data))
}

For this example, I used mkcert and ran the following commands:

mkcert \
  -key-file key.pem \
  -cert-file cert.pem \
  localhost

mkcert \
  -client \
  -key-file client-key.pem \
  -cert-file client-cert.pem \
  localhost

# For convenience of the example.
ln -s ~/.local/share/mkcert/rootCA.pem ca.pem

Upvotes: 0

Related Questions