# Integrating OpenZiti with a Golang TLS server

**URL:** <https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414>\
**Category:** Building/Development\
**Created:** [April 18, 2022, 5:25am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414 "2022-04-18T05:25:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 18, 2022, 5:25am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/1 "2022-04-18T05:25:15Z")

</div>

# Situation

I have the http golang server demo working.

> **[sdk-golang/exercises/http at main · openziti/sdk-golang](https://github.com/openziti/sdk-golang/tree/main/exercises/http)**
>
> Ziti SDK for Golang. Contribute to openziti/sdk-golang development by creating an account on GitHub.

Next.. I wanted to add one more layer by making it TLS enabled.

So.. I found some source code to start with.

**unzitified code**

[https://github.com/denji/golang-tls](https://github.com/denji/golang-tls)

However.. when I started to read through the setup.. I realised that there is something that I don't understand.

> Where does the certificate come from?

This sounds a bit stupid.. as like in all of the examples.. you just create it on the fly..

> Though how does it relate with the certificates required for the controller and router?

I was thinking that maybe its best to create a certificate based upon the certificates from the controller and router.... so that it has the same hierarchy.

> This is hinted at in the boot-strapping article.. but not specifically mentioned.

[https://openziti.github.io/articles/bootstrapping-trust/part-01.encryption-everywhere.html](https://openziti.github.io/articles/bootstrapping-trust/part-01.encryption-everywhere.html)

Hence.. as I am fumbling around... I thought to post this as a question.

> If you do use the "intermediate" certificates.. from the Ziti Quick Install.. what commands do you need to use to create your certificate?

Let me know if you have any tips.

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 18, 2022, 5:55am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/2 "2022-04-18T05:55:18Z")

</div>

To further investigate, I did a search on pem files.

> find /home/opc/.ziti/quickstart/instance-20220416-1603 -depth -name "\*.pem"

When I did this, I noticed that a public key was created for the controller.

However.. there is a difference between ZAC and an application server.

- ZAC is a standalone application to manage the Ziti controller

Whereas.. my situation is to create a handshake from the router to a terminating endpoint (is that how it is described?)..

- My understanding is that the TLS handshake needs to be trusted via CSR.. so it will need to be linked back to the "self-signed" certificate authority that was created during the Quick Start installation process.

> The next step that I have is to make this golang server a reverse proxy server

> PS.. I saw this command in another google search to create a certificate

> $ **openssl** x509 -req -days 365 -in localhost.csr -signkey localhost.key -out **localhost.crt**

> which raises more question.. where is the csr file in the Quick Install folder.. as I could not find it using a search command

sudo find /home/opc/.ziti/quickstart/instance-20220416-1603 -depth -name "\*.csr"

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 18, 2022, 5:59am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/3 "2022-04-18T05:59:32Z")

</div>

Now I feel a bit stupid.

- `.crt` — Alternate synonymous most common among \*nix systems `.pem` (pubkey).

> I have already found them using the find command above 🙂

I also now realise the crt files are in the following directory

/etc/pki/tls/certs/ca-bundle.crt

Still not sure though what to put into the command like to create the SSL certificate though.

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 18, 2022, 11:29pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/4 "2022-04-18T23:29:54Z")

</div>

I had a chat with a friend this morning to piece together a few more bits of the puzzle.

1. you need to create a key pair for the server… this is how it is identified…

2. you then need to sign the key pair using the self signed certificate.

I am going to watch a few more videos to work through all of this and will post my learnings as I go

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 12:05am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/5 "2022-04-19T00:05:44Z")

</div>

I was working through the "ziti-cli-functions.sh" file and stumbled across the following command

> ziti pki

I was going to use something like openssl.. but it probably makes more sense to use the tools integrated with Open Ziti 🙂

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 12:15am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/6 "2022-04-19T00:15:21Z")

</div>

As I was working through this, I initially thought that all I needed was a server certificate.

However.. as I was walking through the function that generates the certificates.. you also need to have a client certificate..

This twigged something back in the boostrapping trust documentation... then I realised that you need both... server and client certificate.. as both are used by OpenZiti

> the steps are covered in the link below

[https://openziti.github.io/articles/bootstrapping-trust/part-05.bootstrapping-trust.html](https://openziti.github.io/articles/bootstrapping-trust/part-05.bootstrapping-trust.html)

> 

unction pki\_client\_server {  
name\_local=${1-}  
ZITI\_CA\_NAME\_local=$2  
ip\_local=$3

if [["${ip\_local}" == ""]]; then  
ip\_local="127.0.0.1"  
fi

if ! test -f "${ZITI\_PKI}/${ZITI\_CA\_NAME\_local}/keys/${name\_local}-server.key"; then  
echo "Creating server cert from ca: ${ZITI\_CA\_NAME\_local} for ${name\_local}"  
"${ZITI\_BIN\_DIR-}/ziti" pki create server --pki-root="${ZITI\_PKI\_OS\_SPECIFIC}" --ca-name "${ZITI\_CA\_NAME\_local}"   
--server-file "${name\_local}-server"   
--dns "${name\_local},localhost" --ip "${ip\_local}"   
--server-name "${name\_local} server certificate"  
else  
echo "Creating server cert from ca: ${ZITI\_CA\_NAME\_local} for ${name\_local}"  
echo "key exists"  
fi

if ! test -f "${ZITI\_PKI}/${ZITI\_CA\_NAME\_local}/keys/${name\_local}-client.key"; then  
echo "Creating client cert from ca: ${ZITI\_CA\_NAME\_local} for ${name\_local}"  
"${ZITI\_BIN\_DIR-}/ziti" pki create client --pki-root="${ZITI\_PKI\_OS\_SPECIFIC}" --ca-name "${ZITI\_CA\_NAME\_local}"   
--client-file "${name\_local}-client"   
--key-file "${name\_local}-server"   
--client-name "${name\_local}"  
else  
echo "Creating client cert from ca: ${ZITI\_CA\_NAME\_local} for ${name\_local}"  
echo "key exists"  
fi  
echo " "  
}

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 12:26am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/7 "2022-04-19T00:26:54Z")

</div>

I found this to be a useful video

[![](https://global.discourse-cdn.com/free1/uploads/netfoundry/original/1X/5325b4abe219e607c19902625f86a87d94eb13bd.jpeg "Client Server Certificate Configuration and Authentication") ](https://www.youtube.com/watch?v=QXSICeRha6c)

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 12:29am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/8 "2022-04-19T00:29:14Z")

</div>

This was also useful to fill in a few more gaps.

> **[Create Secure Clients and Servers in Golang Using HTTPS](https://youngkin.github.io/post/gohttpsclientserver/)**
>
> Create secure web clients and services in Golang using HTTPS

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 1:06am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/9 "2022-04-19T01:06:06Z")

</div>

> I have reached the conclusion that I first need to work through the following example before I try to get the certificate signed by the controller.

The reason is because the zitified http server needs some extra code to enable the TLS service.. of which... I dont have much idea what it is.. other than.. its not a simple one liner.

> **[GitHub - denji/golang-tls: Simple Golang HTTPS/TLS Examples](https://github.com/denji/golang-tls)**
>
> Simple Golang HTTPS/TLS Examples. Contribute to denji/golang-tls development by creating an account on GitHub.

> Does anyone have any samples of how to create a zitified tls enabled golang server?

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 7:20am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/10 "2022-04-19T07:20:51Z")

</div>

Made progress with the tls golang server… I found this to be the most useful

[![](https://global.discourse-cdn.com/free1/uploads/netfoundry/original/1X/7880c07941e4fca85420a7a1a1913cf08efa837d.jpeg "Golang HTTPS") ](https://www.youtube.com/watch?v=Ox-iJshGPyc)

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 9:25am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/11 "2022-04-19T09:25:01Z")

</div>

Quick update.. I think I have worked this out.. but still yet to test it

I thought to put my hypothesis out there in case others see something wrong.. as I am really the blind leading the blind

> what helped is to search through the SDK folders.. I only just realised that you can do this..

As I could not find any TLS implementation.. I realised that it needs to be setup separately to the zitified listener..

> well.. at least I think so.. from what I can work out

# next breakthrough moment

Going through the steps to implement a Golang TLS server helped me understand what all of the config requirements are re certificates.. and the extra code required to implement.

The main line is the following which connects the http service to TLS.. where you need to pass in the certificate and private key

> http.HandleFunc("/", handler)  
> err := http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

# But.. now what..

Well.. here is a sample from the zitified http server.. where the http.Serve activates the ziti listener.

> http.HandleFunc("/hello", hello)  
> http.HandleFunc("/add", add)  
> if err := http.Serve(createZitiListener(), nil); err != nil {  
> panic(err)  
> }

So.. if you combine these together.. this is what I believe is needed from a coding perspective.

> http.HandleFunc("/hello", hello)  
> http.HandleFunc("/add", add)  
> **if err := http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil); err != nil {  
> panic(err)  
> }**  
> if err := http.Serve(createZitiListener(), nil); err != nil {  
> panic(err)  
> }

# Now for the unknown piece

How do you create the certificate and private keys?

In the above example where I implemented a SSL golang server.. they used the following command

> go run $(go env GOROOT)/src/crypto/tls/generate\_cert.go --host=localhost

This creates two files in the directory that it is run in

- cert.pem
- key.pem

However.. this is not linked to the keys from the controller or router.. so if I use this.. I think its going to fail.. with an error like **bad certificate.**

I do know that there is a ziti command for pkis.. but are not 100% sure on the variables

> ziti pki create

This is now at the edge of my knowns.. and now everything else is 100% unknown.

Let me know if you have any tips are how to finish this off 🙂

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 9:30am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/12 "2022-04-19T09:30:13Z")

</div>

I think I need to do something like this

ziti pki create server --??

> Would this be the key.pem above?

ziti pki create csr --??

> Would this be the cert.pem above?

Once created.. pass them into the server as extra variables..

Does this make sense?

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 10:31am UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/13 "2022-04-19T10:31:22Z")

</div>

After more research... I think I have to go back to the drawing board.. because my thinking is wrong.

I picked it up watching this video from 15:30.

[https://www.youtube.com/watch?v=ZKlwKg-f\_\_0&list=PLSak\_q1UXfPp2VwUQ4ZdUVJdMO6pfi5v\_&index=41](https://www.youtube.com/watch?v=ZKlwKg-f__0&list=PLSak_q1UXfPp2VwUQ4ZdUVJdMO6pfi5v_&index=41)

In short.. ListenAndServe is replaced with **ListenAndServeTLS**

You will notice this when you look at the http server example before it is zitified

> if err := http.ListenAndServe(":8090", nil); err != nil {  
> panic(err)  
> }

after it is zitified.. it becomes

> if err := http.Serve(createZitiListener(), nil); err != nil {  
> panic(err)  
> }

This means.. the certificate and key need to be passed into this code somewhere

> func createZitiListener() net.Listener {  
> cfg, err := config.NewFromFile(os.Args[1])  
> if err != nil {  
> panic(err)  
> }  
> options := ziti.ListenOptions{  
> ConnectTimeout: 5 \* time.Minute,  
> }  
> listener, err := ziti.NewContextWithConfig(cfg).ListenWithOptions(os.Args[2], &options)  
> if err != nil {  
> fmt.Printf("Error binding service %+v\n", err)  
> panic(err)  
> }  
> return listener  
> }

So I will keep doing walkabout for a while longer

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 5:18pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/14 "2022-04-19T17:18:26Z")

</div>

Think I get it now..

> When you enrol an identity.. it creates a json file.. which contains all of the bits and pieces.. pem.. cert.. and the cert chain etc

So.. you dont need to create a server / client key manually is the case of the golang ssl example above.

> all you need to do is to create an identity.. and enroll it on the server.. which will take care of everything for you.

Well... that is what I believe for now.. I will give you an update as more unfolds.

> ps.. I am starting to learn golang at the same time..

---

<div class="post-metadata">

**Author:** ![TheLumberjack](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/thelumberjack/32/113_2.png) [@TheLumberjack](https://openziti.discourse.group/u/TheLumberjack)\
**Post date:** [April 19, 2022, 5:50pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/15 "2022-04-19T17:50:34Z")

</div>

Yes. Sort of. OpenZiti will make a mutual TLS connection from any piece of the overlay to another. If you are using a zitified client with a zitified server - then yes that’s 100% perfectly secure and fine.

It’s when you bring the tunneler into the mix that it’ll get more complex. Accessing that service via TLS using a tunneler would require a THIRD layer of encryption, provided by “the http server”. Conceptually you might think of that like three pipes… sorta like this… the inner pipe is the third layer of encryption that is _NOT_ provided by openziti. This would be done from “the browser” to “the https server”. In my pic below that would be the yellow pipe…

 ![image](https://global.discourse-cdn.com/free1/uploads/netfoundry/original/1X/1e1e4c4b9fe6999f254f2401088517d02b346ff0.png)

Wrapping your yellow pipe, the https protocol negotiated by your browser and the https server, is the orange pipe. This represents the end to end encryption (e2ee) that OpenZiti provides by default (you can disable it but why would you??? 🙂 ). That’s negotiated on the “client side” (the tunneler, or inside your golang app itself, wherever) and the far side.

Finally there is the “mutual TLS” (mTLS) encryption that you get also provided by OpenZiti which you cannot disable. This layer protects the links from being inspected by tools like Wireshark/tcpdump.

You should start by making a web server WITHOUT ziti and providing https. There’s a bunch of tutorials on the web how to do that. Once you understand that - then I think you could move over to ‘zitifying’ that app and using OpenZiti on the server too… That’d be my reccomendation.

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 6:03pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/16 "2022-04-19T18:03:15Z")

</div>

Thanks @TheLumberjack that's some nice Selleys work to fill in a few more gaps 🙂

When I worked through the SSL golang example.. this was the main line of code required to get the TLS to work.. i.e. adding TLS to the ListenAndServe method

> err := http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

When I was looking through the zitified http server.. I noticed that this was all embedded in the ziti library

So.. what I have done.. maybe its wrong.. is to replace the line above with the following

> if err := http.Serve(createZitiListener(), nil); err != nil {  
> panic(err)  
> }

Then.. when I pass in the json and service.. it should run and be encrypted ... though I am unsure about the ssl part.

go run main-ssl.go "$HOME/golang.http.server.json" golanghttp

Now.. I did find some references to tls in the ziti code.. but that was on the client end.. so maybe there is more that I need to do.

Am I heading in the right direction?

PS\> my next challenge is to make this a reverse proxy.. if that is possible

---

<div class="post-metadata">

**Author:** ![TheLumberjack](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/thelumberjack/32/113_2.png) [@TheLumberjack](https://openziti.discourse.group/u/TheLumberjack)\
**Post date:** [April 19, 2022, 6:25pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/17 "2022-04-19T18:25:59Z")

</div>

> [@markamind](#):
>
> Then… when I pass in the json and service… it should run and be encrypted … though I am unsure about the ssl part.

It'll be encrypted yes. BUT - **if** you use a tunneling app (a tunneller) and try to access the server you will find that you must use "http" (as in "[http://your.intercept.name.here](http://your.intercept.name.here)"). You **WILL NOT** be able to use https.

Keep playing with it and you'll probably come to discover what I mean 🙂 good luck!

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 6:30pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/18 "2022-04-19T18:30:33Z")

</div>

Now that is a brainteaser.

so… like its encrypted… but its over http… thought its ok… because the encryption is end to end…

---

<div class="post-metadata">

**Author:** ![markamind](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/markamind/32/157_2.png) [@markamind](https://openziti.discourse.group/u/markamind)\
**Post date:** [April 19, 2022, 6:31pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/19 "2022-04-19T18:31:52Z")

</div>

I think this is where some of my gaps start to fade away… because it makes sense why I keep stumbling on this ssl thing… and why the json file has all of that information in it.

---

<div class="post-metadata">

**Author:** ![TheLumberjack](https://yyz2.discourse-cdn.com/free1/user_avatar/openziti.discourse.group/thelumberjack/32/113_2.png) [@TheLumberjack](https://openziti.discourse.group/u/TheLumberjack)\
**Post date:** [April 19, 2022, 6:37pm UTC](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414/20 "2022-04-19T18:37:47Z")

</div>

the “outer” (yellow pipe) transport will be unencrypted http. that INSECURE protocol is only insecure until the tunneling client intercepts the packets and puts the packets onto the ziti overlay network. from there - it’s “tunneled” unencrypted to the other side. since the other side is an http server itself - the payload won’t ever be unencrypted anywhere except for that first local hop from browser → local ziti tunneller.

If you had a tunneling app on the server side (which you don’t in this example) it would leave the far side as ‘http’ and be able to be sniffed by tcpdump/wireshark. By using ziti - that’s not possible on the server side (since the e2ee goes INTO the server and never hits the local os network stack unencrypted). it WOULD be able to be sniffed by wireshark unecrypted on the ‘client side’ if you used a tunneling app with HTTP though because between the browser and the tunneller it hits the OS network stack unencrypted (http)… If you aren’t using the browser, and if you use the golang http client - at that point it’ll be e2ee the full way… and encrypted but not “https”.

It’s complex I know - have a walkabout and I bet you’ll get it. cheers

[Next page](https://openziti.discourse.group/t/integrating-openziti-with-a-golang-tls-server/414.md?page=2)
