Writing a TCP/UDP server type for Caddy

(Matt Holt) #22

@miekg Just add those directives to your list of allowed directives :slight_smile: It should just work, assuming your DNS server imports it as one of the “standard” plugins.

(Matt Holt) #23

I do this too, but :exclamation: make sure to use Let’s Encrypt’s staging endpoint :bangbang:

Or you could just set up https://github.com/letsencrypt/pebble as a lightweight ACME CA on your local computer (haven’t tried this yet).

@pieterlouw I’ve been thinking about this… indeed, the server type will need to know what hostnames to support. Maybe you could add a hosts (or server_names or something…) directive or something to your server types, that registers the host names to apply for that block of the Caddyfile? I’d rather not tack it onto the tls directive because it gets confusing when used with HTTP where the host is often specified in the site name, but if we did, it would be called sni I think.

(Pieter Louw) #24

@miekg, thanks will try this.

I’m curious, do you have auto tls built into coredns?

(Pieter Louw) #25

Do you mean the Caddyfile will look something like this:

proxy :12017 :22017 {
    hosts example.com

“…that registers the host names to apply for that block”, by that you mean I register the hostnames in the action function for the hosts directive to be used in the callback function specified in caddy.RegisterParsingCallback("net", "tls", activateTLS) ?

Also, how would I need to handle tls if the user want to specify it’s own certificate instead of using the auto feature?

(Miek Gieben) #26

But I think i need just the middleware in a git repo, not sure if it will work will all of caddy in a repo.
Also I need to pass ServerType to (for instance) to startshutdown.go’s registration function - would be nice to find some middleware groun here that sharing plugins becomes easier (at least the non-middleware ones - bind comes to mind)

(Miek Gieben) #27

No, but we’re planning it: https://github.com/coredns/coredns/issues/582

TLS storage plugin type for sharing certs
(Pieter Louw) #28

Nice. We should be able to share notes as I guess it will be very similar for both server types

(Miek Gieben) #29


Note I want to do some details differently, like spinning for TLS certs while starting up (similar to the https_google protocol in middleware/proxy). I.e. If let’s encrypt is down, CoreDNS should just start up and flag that middleware as unhealthy.

(Matt Holt) #30

Yes! That, precisely.

Take a look at how the https.go file in the httpserver package does it. There’s a function called caddytls.QualifiesForManagedTLS that you can call and it will do the heavy lifting of figuring out if you should set the Managed field of the TLSConfig to true.

(Matt Holt) #31

No, I think it should just work. :thinking: Let me know if it doesn’t though. You should just need to import the package: https://github.com/mholt/caddy/blob/36d2027493a65e76463d7075d37cd0a139dcb7f7/caddyhttp/caddyhttp.go#L32 and then add it to your list of directives: https://github.com/mholt/caddy/blob/36d2027493a65e76463d7075d37cd0a139dcb7f7/caddyhttp/httpserver/plugin.go#L443-L444

(Miek Gieben) #32

Sweet ***** that works:

diff --git a/middleware.cfg b/middleware.cfg
index 75985cf..4a30a87 100644
--- a/middleware.cfg
+++ b/middleware.cfg
@@ -42,3 +42,4 @@

go gen; go build

I repeat the line for shutdown and have that working as well.

(Miek Gieben) #33

except there not dns server plugins, but they don’t need to, because no middleware.

(Matt Holt) #34

Yep. Any server type can be shutdown or started, which is why it doesn’t need to be tied to a specific server type.

(Mark) #35

TLS knows the »SNI extension«. That is, the server name will be sent before the handshake completes, in cleartext. (That’s why you shouldn’t run stuff like SecureDrop or the like on its own domain.) It’s stored here:


(Matt Holt) #36

Hey @pieterlouw - I talked to someone at my university today named Jordan who wants to get on board and help with your TCP/UDP server plugin. Might be a few weeks out still, but he’ll contact you soon I think!

(Pieter Louw) #37

That’s great news!

(Matt Holt) #38

3 posts were split to a new topic: TLS storage plugin type for sharing certs

(Pieter Louw) #39

So I’ve done quite a bit to add tls to the plugin.

I have registered the callback and the config getter caddy.RegisterParsingCallback(serverType, "tls", activateTLS)

caddytls.RegisterConfigGetter(serverType, func(c *caddy.Controller) *caddytls.Config {return GetConfig(c).TLS})

The activateTLS follow all the steps stated in the wiki guide.

I also added a tlshost directive to set the hostname the tls will use i.e

echo :22017 {
    tlshost echo.caddynet.com

Before I call tls.Listen I do the necessary call to caddytls.MakeTLSConfig to get the tlsConfig to use in tls.Listen

When I start caddy I get the Let’s Encrypt questionaire. (I cancelled as I’m not on an owned domain)

I tried to test with the self-signed option like this

echo :22017 {
    tlshost localhost
    tls self_signed

But then I recive an error: tls: neither Certificates nor GetCertificate set in Config when I call tls.Listen from my server.
I have double checked and debugged quit for a while now and can’t exactly figure out what I’m doing wrong here. Have I missed something?

caddy-net (main repo)
caddy-net (tls branch) [EDIT: tls brand merged and deleted]

(Matt Holt) #40

I’d suggest going into config.go and see what configMap looks like by printing it: https://github.com/mholt/caddy/blob/4e1229e7c9bd5643ed079f3dafa25df4e426da56/caddytls/config.go#L350

And make sure this line gets executed: https://github.com/mholt/caddy/blob/4e1229e7c9bd5643ed079f3dafa25df4e426da56/caddytls/config.go#L267

Make sure everything checks out there. Hope that helps!

Edit: How do you feel about just using the directive name host instead of tlshost? In theory the hostname wouldn’t have to be limited to TLS.

(Pieter Louw) #41


After adding some traces I could see configMap loaded and the line mentioned did execute.
It turns out that I used the wrong function when creating a listener for tls.
I used tls.Listen() but when I switched to tls.NewListener() it works. (Still unsure why exactly…)

I don’t have a problem naming the directive host - I named it tlshost as I thought that was the only reason a host would need to be specified. Do you see a reason why it maybe could be plural (hosts)?

I’ll finish off the tls for the proxy and merge then I guess it’s just tests that left.[EDIT: I have implemented tls for the proxy as well and merged to master]

I might need help with testing auto-TLS as at the momenet I don’t own a domain of my own.