X509: certificate relies on legacy Common Name field, use SANs instead

Situation

I am working through a more complex situation with a reverse proxy, which has caused me to go quite deep into x509 certificates.

One approach I was working through was to create a new certificate authority, issue intermediate certificates, a server certificate and a new client certificate for validation purposes. I worked through all of this using the domain names for the X509v3 Subject Alternative Name.

However, the problem was that I cannot enrol a new identity that is created from a new certificate authority using Open Ziti.

So.. now that I understood how all of this worked.. I found the server certificate and private key created by Open Ziti.. and re-used them.. by deploying into my application server.

This all worked.. except for one thing.. when I go to implement the reverse proxy functionality.. I come across the following error.

x509: certificate relies on legacy Common Name field, use SANs instead

When I inspect both the root and intermediate certificates, I realise that no SANs have been assigned.

openssl x509 -noout -text -in ./pki/168.138.10.79-root-ca/certs/168.138.10.79-root-ca.cert

Suggested change

It would be great if the installation scripts in ziti can be updated to implement SANs

Since Go version 1.15, the deprecated, legacy behavior of treating the CommonName field on X.509 certificates as a hostname when no Subject Alternative Names (SAN) are present is now disabled by default.

https://jfrog.com/knowledge-base/general-what-should-i-do-if-i-get-an-x509-certificate-relies-on-legacy-common-name-field-error/

This is starting to become a real roadblock for me.

I am considering manually replacing all of the Open Ziti certificates so that they have SANs.. though I imagine its not so simple.

any tips?

The problem is that I cannot use a new certificate authority if I create one.. and the ziti commands that created the open ziti certificate authority dont set the SAN.

What this means is that I cannot implement full reverse proxy demonstration that I was intending.

Actually.. after a lot of digging.. I think I have an answer.. but don't really know until I test it

When I use the markamind.com as the test origin server.. the reverse proxy works.

When I use markamind.online (a test domain that I created).. the reverse proxy fails with

x509: certificate is not valid for any names, but wanted to match www.markamind.online

when I looked into the SAN for markamind.com.. it has a wildcard *.markamind.com, www.markamind.com

however, in the markamind.online certificate.. it does not.. markamind.online and www.markamind.online

So.. I am going to recreate this server certificate.. and hopefully this will resolve the issue :slight_smile:

A little bit frustrating.. as you can only use wildcard domains when you can perform a DNS-01 challenge.

my domain provider is not listed.

Time for a break.. and will see if I can work this out later tonight.

As an alternative I have not considered.. I may just create a subdomain.. this will eliminate this problem.. hopefully

just realised this is not going to work because the application server that I am using to host the application needs to have the certificate and private key

maybe I will give the creation of the certificate one more hack.. by including a range of domain names.. instead of a wildcard..

its not going to work.. the tool to generate the certificate wont let me do what I need.

The only way forward that I can see is a self signed certificate.. which I can create.. and verify... but I cannot create an identities with it... because it does not generate a jwt for enrolling

all I can do to demo the capability is to make a reference to my website until I can find a way to resolve this

Can I ask to take a step back and give me the use case you’re trying to implement? I am surmising from the messages in this thread and from our history together that you’re trying to make what seems like a zero trust http proxy and you’re trying to use “https” through ziti. Would that be correct?

It’d be super helpful if you could share a super high level overview if you can? I love how deeply you’re going here and tbh, I think you’re doing great. You’re covering a lot of ground (and I mean a lot of ground) in what you’re doing. I’d like to just level-set if we can?

And we don’t want you frustrated! :slight_smile:

It's been a journey for sure.

The main objective is to provide a simple service that turns websites dark.

  • light access is provided over the public DNS
  • dark access is provided over a ziti network fabric

To make user accounts accessible over a ziti network without needing to duplicate the website.. I am using a golang server to act as a reverse proxy that operates over a ziti network.

While this is not "the solution" it is a simple first step to get started.. and implement a deeper AppWAN in a later implementation.

The business opportunity is to sell reverse proxy service on demand .. automating the process of creating a network fabric for user account management
this means that users will no longer access user account function over a public DNS

As you can see in the image below.. I can redirect a private DNS over a ziti network to my website...https://www.markamind.com

1650963775109

Here is a summary of what is happening

  1. user starts the Ziti Desktop edge tunneller
  2. user types in a http address that I have setup an intercept for
    http://golanghttp.zitified:2000

note: even though the traffic is going over http.. its still encrypted.. because I believe this is what the network fabric is doing.. @TheLumberjack discussed this in another post here.. but I still dont understand it 100% yet
Integrating OpenZiti with a Golang TLS server - #15 by TheLumberjack

  1. the intercept picks up http request.. and sends it to a ziti service
  2. The ziti service sends the http request to a "zitified" golang https server that then connects to the origin server over https .. and returns the request back to the user... without the user accessing the origin server

phew.. it took me some time to even explain that

As you can see.. this works... but what I did not know was why it worked because at the time I had no idea of what I was doing :slight_smile:

What I understand now is that the reason why this worked can be seen in how the certificate is created for my website

You will notice that it is created using a wildcard DNS name.
this is why I didn't get this error coming back from the Golang reverse proxy

x509: certificate relies on legacy Common Name field, use SANs instead

So.. with my new found confidence.. I though I would try something a bit harder.. and replicate this same situation using an Oracle Apex application hosted on Oracle Cloud.. which is when all of the problems happened.

  1. I don't remember exactly what happened at the time.. but rather than using the public dns of the hosted Apex application.. I needed to use a proxy server.. so I decided to deploy ORDS on a private compute..
  • this got me a bit further... but I got stuck because I built ORDS using a self signed certificate.. this did not work because my ziti network does not trust the new "certificate authority" that I created
  1. I decided to return back to my website to see if I could reproduce the problem..
  • I broke it.. long story short.. the reverse proxy forwards the user to the origin server if I use http://markamind.com.. but is not for http://www.markamind.com
  • I thought this was a problem with my Goloang code.. but it was not.. I have a redirect on the DNS server
  1. I tried to reuse the the certificate and key created when I did the quick install. I thought this should be trusted because it was created by the "ziti" Certificate Authority
  • the problem is.. the certificates created do not have a SAN (Subject Alternative Name). Apparently.. this is now a requirement for a Goloang reverse proxy server.

This is why I received this error back from the Golang reverse proxy when i used the certificate and private key created by the Ziti Quick Install

x509: certificate relies on legacy Common Name field, use SANs instead

  • I think this would not work anyway because when I built the controller.. I used an IP address.. so if the quick start program created a SAN.. it would not have matched the URL I was using

After all of this.. I realised you can "verify" a Certificate Authority in Ziti..

I have another post about this.. I believe this will be the "preferred" alternative.. but I still need to work through the details

if you are game enough to venture into this space.. here is a great introduction on how to build a Certificate Authority.. if you follow the steps you will get 95% there.. you will reach a problem when you want to create a client certificate to validate the Certificate Authority in ziti..

https://jamielinux.com/docs/openssl-certificate-authority/introduction.html

Here are the commands that I used to create it

  1. create the user private key

openssl genrsa -aes256
-out intermediate/private/X4EA4CxdE.key.pem 2048
chmod 400 intermediate/private/X4EA4CxdE.key.pem

  1. create the certificate signing request

openssl req -config intermediate/openssl.cnf
-key intermediate/private/X4EA4CxdE.key.pem
-new -sha256 -out intermediate/csr/X4EA4CxdE.csr.pem

  1. create the user certificate

openssl x509 -req -in intermediate/csr/X4EA4CxdE.csr.pem -CA intermediate/certs/ca-chain.cert.pem -CAkey intermediate/private/intermediate.key.pem -CAcreateserial -days 365 -sha256 -extfile intermediate/client_cert_ext.cnf -out intermediate/certs/X4EA4CxdE.cert.pem

note I used the "intermediate CA". if you use the "root CA" it will not verify

1 Like

Thanks. I have a busy day tomorrow but I’ll try to digest this when I can. Appreciate the details.

1 Like

Here is a more detailed overview… as a part of my DeveloperWeek Europe 2022 Hackathon submission.

Thanks for all of your teachings over the last few months (along with everyone else :slight_smile: … it helped me understand the fundamentals… which then provided the foundation to put something like this together.

1 Like

I’m only sad, I have but one like to give! NICE!

1 Like

Thanks for that. FWIW, the ziti cli supports building your own CA too... For my money, it's easier than running the openssl commands but doing it with openssl and understanding what it's doing is really valuable (just a longer path to take). The expressInstall makes a bunch on your behalf.

You can also run :

ziti pki create ca

or

cd ~
mkdir mypki
ziti pki create ca --pki-root=$(pwd)/mypki --ca-file "my-super-secret.ca" --ca-name "my-super-secr
et.ca"

now you have a folder:

ll ~/mypki/my-super-secret.ca/
total 36
drwxr-xr-x 5 ubuntu ubuntu 4096 May  2 11:47 ./
drwxrwxr-x 3 ubuntu ubuntu 4096 May  2 11:47 ../
drwxr-xr-x 2 ubuntu ubuntu 4096 May  2 11:47 certs/
-rw-rw-r-- 1 ubuntu ubuntu    3 May  2 11:47 crlnumber
drwx------ 2 ubuntu ubuntu 4096 May  2 11:47 crls/
-rw-rw-r-- 1 ubuntu ubuntu  138 May  2 11:47 index.txt
-rw-rw-r-- 1 ubuntu ubuntu   20 May  2 11:47 index.txt.attr
drwx------ 2 ubuntu ubuntu 4096 May  2 11:47 keys/
-rw-rw-r-- 1 ubuntu ubuntu    3 May  2 11:47 serial

All kinds of stuff in there to dig into... if you want. or you can be happy that someone in the ziti cli did it all for you already :slight_smile:

Then you can make a client cert with:

ziti pki create client --pki-root=$(pwd)/mypki --ca-name=my-super-secret.ca  --client-name client

(make sure you use the FULL path to the pki-root as I show using $(pwd) (or the type the full path)

Here's mine:

find mypki/ -name "*client*"
mypki/my-super-secret.ca/certs/client.cert
mypki/my-super-secret.ca/keys/client.key

I'll carry this conversation to your other thread now, and probably refer to these commands when responding to your other post at: Creating Endpoint with your own Certificate Authority - #9 by markamind

1 Like