Using tls_insecure_skip_verify
skips all security offered by HTTPS. Anyone who wants to man-in-the-middle the connections could do so without either the client or server complaining (i.e. by decrypting, then re-encrypting the connection).
At that point you might as well use HTTP because you’ll skip the overhead of the TLS handshake when proxying.
The “easiest” way to establish trust between your internal servers would be to use Caddy’s acme_server
on the one that’s publicly accessible, then run Caddy instances on each of your other servers, using the publicly accessible one as their ACME server to issue them certificates that are trusted. But even this isn’t that easy to manage.
You should instead focus on preventing bad actors from gaining access to your network, instead of worrying about what happens once they’re already in.
Tools like fail2ban don’t so much enhance security as much as prevent resource overuse by blocking the connections earlier in the pipeline.
Using fail2ban with Caddy is unfortunately kinda tricky though, because Caddy’s default of JSON logging isn’t supported by it. But you can follow this thread to get an idea of what might be involved: