Remote error tls unknown certificate

I have made my cert and key using the following openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem And configured it in my Golang code log.Fatal(http.

«Remote error» means error sent from client (firefox in this case).

Solution is to figure out why firefox doesn’t like the certificate and fix it.

There is something that firefox doesn’t like about the certificate. Open up firefox dev tools and see if you can find any warnings regarding the certificate. If you had to manually accept the certificate in Firefox then it is possible that Firefox is still reporting to the server that it doesn’t like the certificate even though you have told firefox to load the page anyway (see chrome example below).

However as this is a self generated/signed certificate the warning is probably because firefox doesn’t trust this certificate. Solution is to either add this certificate to firefox’s trusted certificates if this server is only for your own personal use…or to get a certificate signed by a commercial CA or letsencrypt.

«Fixing this server-side» means fixing whatever it is about how your certificate/app is served in order to make it trusted by firefox. Or I suppose ignoring the errors if you are just doing development.

More details…

Key thing here is that this is a «remote error» meaning it is an error from the tls CLIENT connecting to your server. In your case it is Firefox complaining during the TLS handshake that the certificate is invalid in some way.

I noticed the same thing with chrome. Cert is signed by a public CA (ie a CA that should be trusted by most browsers) but as I am developing on my local machine, the certificate is invalid because hostname (localhost) doesn’t match the certificate CommonName (CN) or Subject Alternative Names (SAN).

Easiest thing to do is just look at the TLS handshake in wireshark.

wireshark handshake capture

I told chrome to accept the certificate, started capture and did a SINGLE refresh of the page (https://localhost:8081 in this case). Chrome does not present me with a warning page and shows the content. There is a red warning in the address bar however.

The interesting thing (to me) is that it appears (I’m no TLS expert) that there are two TLS handshakes.

Client Hello
Server Hello
Alert (client error)
Client Hello
Server Hello
Client complete handshake
…encrypted application data…

Since chrome doesn’t interrupt my refresh of the page I am not sure why chrome does the handshake twice (first time with Alert/failure) for a single page refresh.

The interesting bit I learned here (obvious in hindsight) is that it is possible to get reporting from browsers/clients when they reject your certificate. This can be used on the server side (if monitored) to discover subtle certificate mis-configurations in production that your test cases might not cover. Unfortunately as this is pre-http you won’t get user-agent or anything useful to help with reproducing….but a large number of these errors as a percentage of server traffic indicates you need to do some serious cross browser/os/device testing

I been bashing my head on this problem but both my pacience and google-fu failed me … so i m turning to anyone out there who might encountered this issue.

I had this working on a previous server (before anyone says, then go get the old files from it, the disk died and i failed at backups … lesson learned) and i m trying rebuild my server from scratch and trying to make Traefik 2.0 working with Letsencrypt DNS challenge, used the documentation page over here as reference to build this configuration file.

So far i m out of luck, i cannot get any certificate from letsencrypt and resulting traefik starting to use a self sign certificate (and that’s why i get the error on the title and in the container log):

time="2019-12-30T00:49:54Z" level=info msg="Configuration loaded from flags."
time="2019-12-30T00:49:54Z" level=info msg="Traefik version 2.1.1 built on 2019-12-12T19:01:37Z"
time="2019-12-30T00:49:54Z" level=debug msg="Static configuration loaded {"global":{"checkNewVersion":true},"serversTransport":{"maxIdleConnsPerHost":200},"entryPoints":{"web":{"address":":80","transport":{"lifeCycle":{"graceTimeOut":10000000000},"respondingTimeouts":{"idleTimeout":180000000000}},"forwardedHeaders":{}},"websecure":{"address":":443","transport":{"lifeCycle":{"graceTimeOut":10000000000},"respondingTimeouts":{"idleTimeout":180000000000}},"forwardedHeaders":{}}},"providers":{"providersThrottleDuration":2000000000},"api":{"dashboard":true},"log":{"level":"DEBUG","format":"common"},"certificatesResolvers":{"le":{"acme":{"email":"username@domain.com","caServer":"https://acme-v02.api.letsencrypt.org/directory","storage":"/letsencrypt/acme.json","keyType":"RSA4096","dnsChallenge":{"provider":"provider","resolvers":["1.1.1.1:53","8.8.8.8:53"]},"httpChallenge":{"entryPoint":"web"},"tlsChallenge":{}}}}}"
time="2019-12-30T00:49:54Z" level=info msg="nStats collection is disabled.nHelp us improve Traefik by turning this feature on :)nMore details on: https://docs.traefik.io/v2.0/contributing/data-collection/n"
time="2019-12-30T00:49:54Z" level=info msg="Starting provider aggregator.ProviderAggregator {}"
time="2019-12-30T00:49:54Z" level=debug msg="Start TCP Server" entryPointName=websecure
time="2019-12-30T00:49:54Z" level=debug msg="Start TCP Server" entryPointName=web
time="2019-12-30T00:49:54Z" level=info msg="Starting provider *acme.Provider {"email":"username@domain.com","caServer":"https://acme-v02.api.letsencrypt.org/directory","storage":"/letsencrypt/acme.json","keyType":"RSA4096","dnsChallenge":{"provider":"provider","resolvers":["1.1.1.1:53","8.8.8.8:53"]},"httpChallenge":{"entryPoint":"web"},"tlsChallenge":{},"ResolverName":"le","store":{},"ChallengeStore":{}}"
time="2019-12-30T00:49:54Z" level=info msg="Testing certificate renew..." providerName=le.acme
time="2019-12-30T00:49:54Z" level=info msg="Starting provider *traefik.Provider {}"
time="2019-12-30T00:49:54Z" level=debug msg="Configuration received from provider le.acme: {"http":{},"tls":{}}" providerName=le.acme
time="2019-12-30T00:49:54Z" level=debug msg="Configuration received from provider internal: {"http":{"services":{"api":{},"dashboard":{}}},"tcp":{},"tls":{}}" providerName=internal
time="2019-12-30T00:49:54Z" level=debug msg="No default certificate, generating one"
time="2019-12-30T00:51:03Z" level=debug msg="http: TLS handshake error from 192.168.0.253:54501: remote error: tls: bad certificate"
time="2019-12-30T00:51:05Z" level=debug msg="Serving default certificate for request: "domain.com""

My docker-compose for traefik is the following:

  traefik:
    image: "traefik:latest"
    container_name: traefik
    hostname: traefik
    restart: always
    command:
      - --log.level=DEBUG
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --api
      # Stating server - --certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
      # Prod Server
      - --certificatesResolvers.le.acme.caServer=https://acme-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.le.acme.email=username@domain.com
      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json
      - --certificatesResolvers.le.acme.httpChallenge.entryPoint=web
      - --certificatesresolvers.le.acme.tlschallenge=true
      - --certificatesResolvers.le.acme.keyType=RSA4096
      - --certificatesResolvers.le.acme.dnsChallenge=true
      - --certificatesResolvers.le.acme.dnsChallenge.provider=dreamhost
      - --certificatesResolvers.le.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53
      - --certificatesResolvers.le.acme.dnsChallenge.delayBeforeCheck=0
    labels:
      - traefik.http.routers.blog.rule=Host('domain.com')
      - traefik.http.routers.blog.tls=true
      - traefik.http.routers.blog.tls.certresolver=le
      - traefik.http.routers.blog.tls.domains[0].main=domain.com
      - traefik.http.routers.blog.tls.domains[0].sans=*.domain.com
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - ${DOCKERDIR}/traefik/config:/etc/traefik
      - ${DOCKERDIR}/traefik/letsencrypt:/letsencrypt
      - ${DOCKERDIR}/shared:/shared
    environment:
      - DREAMHOST_API_KEY=${DREAMHOST_API_KEY}

Anyone can point me to the right way to enable traefik to get the certificates from Letsencrypt? thank you …

UPDATE: Got tired of getting nowhere, i really enjoyed Traefik was but i prefer something that i can manage and not spend 3 days bashing my head and trying to make it to work. Moved back to nginx, but not the way i used to do it (editing files) for anyone interested i m using Nginx Proxy Manager, Pros dead simple to use takes 10 min to set up.. Cons for me, unable to set letsencrypt wildcard certificate, need to ask 1 certificate for all my sub domains

Cover image for 🔐 Building a self signed server in golang

Luiz Lelis

This article will be useful to you if you want to create a self signed server in golang. There are many ways to use certificates to build and run a https server, this article will approach one of them: self-signed using openssl tool. You can see all the source code used in the current article in the public github repository.

Why https?

Firstly let’s remember some concepts. The Hypertext Transfer Protocol (Http) specifies a standard track protocol for the internet community and has been in use since 1990. The problem with the use of only http is that the exchanged messages between server and client will not be encrypted, so everyone who intercepts those messages will know exactly what that messages means and also can modify the data to masquerade as one of the peers involved. To avoid attacks like man-in-the-middle and to provide private communication, the Secure Sockets Layer (SSL) was first introduced by Netscape in 1994 being the pioneer in secure communications protocols, but it was succeeded later by the Transport Layer Security (TLS). TLS is the channel-oriented security protocol currently in use on the internet and it’s composed basically by two protocols: the handshake and the record protocol.

The TLS Handshake protocol is responsible to authenticate two end-points, besides that, it also negotiates cryptographic parameters and generates keying material. The record protocol uses the parameters established by the handshake protocol to protect traffic between the end-points.

Why self signed?

By default your operation system trusts in a set of certification authorities (CA) like GlobalSign, Let’s Encrypt, Digicert, GoDaddy, etc. The self-signed certificates are those that aren’t signed by any CA, in this case, the certificate is signed with its own private key, instead of requesting it from a CA. So in that case, the client should trust in the certificate issued by the server.

The first thing you need to ask yourself is: why do I need a self signed certificate? There are few reasons for that and I’ve never faced a reason to use it in a production environment. So maybe you’re thinking: so on, what is this article for? There are some scenarios which demands you to provide a https endpoint (to run your application locally for example). In my case, I needed it to run an application locally to integrate it with a cloud service that requires a https endpoint. There are some frameworks, SDKs or tool kits written in other languages that provides to you an https endpoint natively with self-signed certificates (it’s the case of JDK and .NET Core), but I didn’t find anything like that in golang.

NOTE: if you’re gonna use https in production, I strongly recommend you to use a certificate signed by a CA (try to use a cloud solution like AWS Certificate Manager, or an open source tool like certbot). There are some security risks that you should be aware of when using self-signed, you can see more about it here.

Running the project

«Talk is cheap, show me the code» — Linus Torvalds

To proceed with the next steps, you’re gonna need to clone this github repo. The current example is composed by a server and a client called https-server and https-client respectively. Each one runs in its specific container, the server provides a REST API written in golang and is responsible to create the self signed certificate. That certificate protects two hostnames: localhost and https-server, that multi-domain approach is possible thanks to the Subject Alternative Names (SANs). Take a look at the diagram below that represents the current example:

certificate-diagram

As you can see above, the server generates the certificate and the clients trust that certificate (client container or a client running in the host). So, to up the client and server containers, run the command below:

docker-compose up

Enter fullscreen mode

Exit fullscreen mode

Server

The command above will firstly up the server container and run some commands from a file called generate-certificate.sh. That bash file contains some openssl commands to create the self signed certificate. First, it generates a servercert.key and servercert.csr which are respectively: the private key and the certificate signing request (CSR) that contains the public key. The CN field in -subj is very important because some browsers like chrome require that information (CN means Common Name, that’s the domain name you would like to have SSL secured). Then, the certificate file will be generated also, this file, named servercert.crt, is generated by the last command in the bash file. That’s the self-signed certificate signed by your own servercert.key private key. The x509 flag states the standard format of an SSL/TLS certificate, the X.509 format. Finally, the https server are gonna get up by the go run main.go command. Take a look at the bash commands bellow:

apk update && apk add openssl && rm -rf /var/cache/apk/*
openssl req -new -subj "/C=US/ST=California/CN=localhost" 
    -newkey rsa:2048 -nodes -keyout "$FILE_CERT_NAME.key" -out "$FILE_CERT_NAME.csr"
openssl x509 -req -days 365 -in "$FILE_CERT_NAME.csr" -signkey "$FILE_CERT_NAME.key" -out "certificates/$FILE_CERT_NAME.crt" -extfile "self-signed-cert.ext"

Enter fullscreen mode

Exit fullscreen mode

the ext file has all tha SANs protected by the certificate:

subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = https-server

Enter fullscreen mode

Exit fullscreen mode

Now that you already have the certificate, you need to serve your https server. Inside the main.go file, the ListenAndServeTLS method is responsible for use the cert and key to serve the https self signed server:

func handleRequests() {

  tlsCert := os.Getenv("tls-certificate")
  tlsKey := os.Getenv("tls-key")
  serverPort := os.Getenv("server-port")

  router := mux.NewRouter().StrictSlash(true)
  controllers.HandleHomeRoutes(router, "https")

  log.Fatal(http.ListenAndServeTLS(serverPort, tlsCert, tlsKey, router))
}

Enter fullscreen mode

Exit fullscreen mode

Along with that, as the cert and key was gotten from the .env file, you should declare both paths:

tls-certificate="certificates/servercert.crt"
tls-key="servercert.key"

Enter fullscreen mode

Exit fullscreen mode

Client

The client container has a volume with the path where the server certificate was generated: ./server/certificates:/certificates. That’s because the client needs to trust that certificate to make https calls to the server. The command update-ca-certificates is responsible to add that certificate to the system’s trust store, it was executed in trust-server-certificate.sh bash file. After that, the client will be able to call the server with https (the handshake will happen normally). The https-client container calls the /home endpoint from the server with https two times after trusting its certificate, take a look at the curl calls in get-server-home.sh file:

#!/bin/ash
echo "Installing curl package"
apk update && apk add curl && rm -rf /var/cache/apk/*
echo "Two requests below to get https server home"
sleep 10
curl https://https-server:8081/home
sleep 20
curl https://https-server:8081/home

Enter fullscreen mode

Exit fullscreen mode

Call the server with a client running locally (localhost)

As mentioned before, you need to trust the server certificate in your local trust store if you want to use https. If you’re using a linux based OS, you should run the commands shown in trust-server-certificate.sh file. Otherwise, follow one of the steps below:

  • Mac Os

  • Windows

  • Linux

If you call a server endpoint before trusting the server certificate, you’ll get an error like the following in your browser:

before-trust

after trusting the certificate locally, you’ll get the response with a 200 Ok status code:

after-trust

if you expand the certificate, you will see all the domains secured by the self-signed certificate:

certificate-sans

that behavior is also shown in the server stdout, before trusting the certificate there is a handshake error, but after trusting it, the handshake is successful:

https-server | 2022/02/07 00:59:53 http: TLS handshake error from 172.19.0.1:55672: remote error: tls: unknown certificate
https-server | Home page endepoint hit

Enter fullscreen mode

Exit fullscreen mode

References

Digicert; Multi-Domain (SAN) Certificates — Using Subject Alternative Names

Globalsign; The Dangers of Self-Signed SSL Certificates

Keyfactor; What is a Self-Signed Certificate? Advantages, Risks & Alternatives

OpenSSL; Cryptography and SSL/TLS Toolkit

RFC 2616; Hypertext Transfer Protocol — HTTP/1.1

RFC 4949; Internet Security Glossary, Version 2

RFC 6101; The Secure Sockets Layer (SSL) Protocol Version 3.0

RFC 8446; The Transport Layer Security (TLS) Protocol Version 1.3

Trying to get the Dashboard UI working in a kubeadm cluster using kubectl proxy for remote access. Getting

Error: 'dial tcp 192.168.2.3:8443: connect: connection refused'
Trying to reach: 'https://192.168.2.3:8443/'

when accessing http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ via remote browser.

Looking at API logs, I see that I’m getting the following errors:

I1215 20:18:46.601151       1 log.go:172] http: TLS handshake error from 10.21.72.28:50268: remote error: tls: unknown certificate authority
I1215 20:19:15.444580       1 log.go:172] http: TLS handshake error from 10.21.72.28:50271: remote error: tls: unknown certificate authority
I1215 20:19:31.850501       1 log.go:172] http: TLS handshake error from 10.21.72.28:50275: remote error: tls: unknown certificate authority
I1215 20:55:55.574729       1 log.go:172] http: TLS handshake error from 10.21.72.28:50860: remote error: tls: unknown certificate authority
E1215 21:19:47.246642       1 watch.go:233] unable to encode watch object *v1.WatchEvent: write tcp 134.84.53.162:6443->134.84.53.163:38894: write: connection timed out (&streaming.encoder{writer:(*metrics.fancyResponseWriterDelegator)(0xc42d6fecb0), encoder:(*versioning.codec)(0xc429276990), buf:(*bytes.Buffer)(0xc42cae68c0)})

I presume this is related to not being able to get the Dashboard working, and if so am wondering what the issue with the API server is. Everything else in the cluster appears to be working.

NB, I have admin.conf running locally and am able to access the cluster via kubectl with no issue.

Also, of note is that this had been working when I first got the cluster up. However, I was having networking issues, and had to apply this in order to get CoreDNS to work Coredns service do not work,but endpoint is ok the other SVCs are normal only except dns, so I am wondering if this maybe broke the proxy service?

* EDIT *

Here is output for the dashboard pod:

[gms@thalia0 ~]$ kubectl describe pod kubernetes-dashboard-77fd78f978-tjzxt --namespace=kube-system
Name:               kubernetes-dashboard-77fd78f978-tjzxt
Namespace:          kube-system
Priority:           0
PriorityClassName:  <none>
Node:               thalia2.hostdoman/hostip<redacted>
Start Time:         Sat, 15 Dec 2018 15:17:57 -0600
Labels:             k8s-app=kubernetes-dashboard
                    pod-template-hash=77fd78f978
Annotations:        cni.projectcalico.org/podIP: 192.168.2.3/32
Status:             Running
IP:                 192.168.2.3
Controlled By:      ReplicaSet/kubernetes-dashboard-77fd78f978
Containers:
  kubernetes-dashboard:
    Container ID:  docker://ed5ff580fb7d7b649d2bd1734e5fd80f97c80dec5c8e3b2808d33b8f92e7b472
    Image:         k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0
    Image ID:      docker-pullable://k8s.gcr.io/kubernetes-dashboard-amd64@sha256:1d2e1229a918f4bc38b5a3f9f5f11302b3e71f8397b492afac7f273a0008776a
    Port:          8443/TCP
    Host Port:     0/TCP
    Args:
      --auto-generate-certificates
    State:          Running
      Started:      Sat, 15 Dec 2018 15:18:04 -0600
    Ready:          True
    Restart Count:  0
    Liveness:       http-get https://:8443/ delay=30s timeout=30s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /certs from kubernetes-dashboard-certs (rw)
      /tmp from tmp-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kubernetes-dashboard-token-mrd9k (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kubernetes-dashboard-certs:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  kubernetes-dashboard-certs
    Optional:    false
  tmp-volume:
    Type:    EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
  kubernetes-dashboard-token-mrd9k:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  kubernetes-dashboard-token-mrd9k
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node-role.kubernetes.io/master:NoSchedule
                 node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

I checked the service:

[gms@thalia0 ~]$ kubectl -n kube-system get service kubernetes-dashboard
NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes-dashboard   ClusterIP   10.103.93.93   <none>        443/TCP   4d23h

And also of note, if I curl http://localhost:8001/api from the master node, I do get a valid response.

So, in summary, I’m not sure which if any of these errors are the source of not being able to access the dashboard.

Понравилась статья? Поделить с друзьями:
  • Remote error tls handshake failure
  • Remote error tls bad certificate
  • Remote error from secret service org freedesktop dbus error serviceunknown
  • Remote error at least 1 approving review is required by reviewers with write access
  • Remote error access denied or repository not exported