Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect to Traefik TCP Services with TLS configuration enabled?

I am trying to configure Traefik so that I would have access to services via domain names, and that I would not have to set different ports. For example, two MongoDB services, both on the default port, but in different domains, example.localhost and example2.localhost. Only this example works. I mean, other cases probably work, but I can't connect to them, and I don't understand what the problem is. This is probably not even a problem with Traefik.

I have prepared a repository with an example that works. You just need to generate your own certificate with mkcert. The page at example.localhost returns the 403 Forbidden error but you should not worry about it, because the purpose of this configuration is to show that SSL is working (padlock, green status). So don't focus on 403.

Only the SSL connection to the mongo service works. I tested it with the Robo 3T program. After selecting the SSL connection, providing the host on example.localhost and selecting the certificate for a self-signed (or own) connection works. And that's the only thing that works that way. Connections to redis (Redis Desktop Manager) and to pgsql (PhpStorm, DBeaver, DbVisualizer) do not work, regardless of whether I provide certificates or not. I do not forward SSL to services, I only connect to Traefik. I spent long hours on it. I searched the internet. I haven't found the answer yet. Has anyone solved this?

PS. I work on Linux Mint, so my configuration should work in this environment without any problem. I would ask for solutions for Linux.


If you do not want to browse the repository, I attach the most important files:

docker-compose.yml

version: "3.7"

services:
    traefik:
        image: traefik:v2.0
        ports:
            - 80:80
            - 443:443
            - 8080:8080
            - 6379:6379
            - 5432:5432
            - 27017:27017
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock:ro
            - ./config.toml:/etc/traefik/traefik.config.toml:ro
            - ./certs:/etc/certs:ro
        command:
            - --api.insecure
            - --accesslog
            - --log.level=INFO
            - --entrypoints.http.address=:80
            - --entrypoints.https.address=:443
            - --entrypoints.traefik.address=:8080
            - --entrypoints.mongo.address=:27017
            - --entrypoints.postgres.address=:5432
            - --entrypoints.redis.address=:6379
            - --providers.file.filename=/etc/traefik/traefik.config.toml
            - --providers.docker
            - --providers.docker.exposedByDefault=false
            - --providers.docker.useBindPortIP=false

    apache:
        image: php:7.2-apache
        labels:
            - traefik.enable=true
            - traefik.http.routers.http-dev.entrypoints=http
            - traefik.http.routers.http-dev.rule=Host(`example.localhost`)
            - traefik.http.routers.https-dev.entrypoints=https
            - traefik.http.routers.https-dev.rule=Host(`example.localhost`)
            - traefik.http.routers.https-dev.tls=true
            - traefik.http.services.dev.loadbalancer.server.port=80
    pgsql:
        image: postgres:10
        environment:
            POSTGRES_DB: postgres
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: password
        labels:
            - traefik.enable=true
            - traefik.tcp.routers.pgsql.rule=HostSNI(`example.localhost`)
            - traefik.tcp.routers.pgsql.tls=true
            - traefik.tcp.routers.pgsql.service=pgsql
            - traefik.tcp.routers.pgsql.entrypoints=postgres
            - traefik.tcp.services.pgsql.loadbalancer.server.port=5432
    mongo:
        image: mongo:3
        labels:
            - traefik.enable=true
            - traefik.tcp.routers.mongo.rule=HostSNI(`example.localhost`)
            - traefik.tcp.routers.mongo.tls=true
            - traefik.tcp.routers.mongo.service=mongo
            - traefik.tcp.routers.mongo.entrypoints=mongo
            - traefik.tcp.services.mongo.loadbalancer.server.port=27017
    redis:
        image: redis:3
        labels:
            - traefik.enable=true
            - traefik.tcp.routers.redis.rule=HostSNI(`example.localhost`)
            - traefik.tcp.routers.redis.tls=true
            - traefik.tcp.routers.redis.service=redis
            - traefik.tcp.routers.redis.entrypoints=redis
            - traefik.tcp.services.redis.loadbalancer.server.port=6379

config.toml

[tls]
[[tls.certificates]]
certFile = "/etc/certs/example.localhost.pem"
keyFile = "/etc/certs/example.localhost-key.pem"

Build & Run

mkcert example.localhost # in ./certs/
docker-compose up -d

Prepare step by step

  1. Install mkcert (run also mkcert -install for CA)
  2. Clone my code
  3. In certs folder run mkcert example.localhost
  4. Start container by docker-compose up -d
  5. Open page https://example.localhost/ and check if it is secure connection
  6. If address http://example.localhost/ is not reachable, add 127.0.0.1 example.localhost to /etc/hosts

Certs:

  • Public: ./certs/example.localhost.pem
  • Private: ./certs/example.localhost-key.pem
  • CA: ~/.local/share/mkcert/rootCA.pem

Test MongoDB

  1. Install Robo 3T
  2. Create new connection:
    • Address: example.localhost
    • Use SSL protocol
    • CA Certificate: rootCA.pem (or Self-signed Certificate)
  3. Test tool:

test

Test Redis

  1. Install RedisDesktopManager
  2. Create new connection:
    • Address: example.localhost
    • SSL
    • Public Key: example.localhost.pem
    • Private Key: example.localhost-key.pem
    • Authority: rootCA.pem
  3. Test tool:

test


So far:

  1. Can connect to Postgres via IP (info from Traefik)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable

enter image description here

jdbc:postgresql://172.21.0.4:5432/postgres?sslfactory=org.postgresql.ssl.NonValidatingFactory

enter image description here


Try telet (IP changes every docker restart):

> telnet 172.27.0.5 5432
Trying 172.27.0.5...
Connected to 172.27.0.5.
Escape character is '^]'.
^]
Connection closed by foreign host.
> telnet example.localhost 5432
Trying ::1...
Connected to example.localhost.
Escape character is '^]'.
^]
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8
Connection: close

400 Bad RequestConnection closed by foreign host.

If I connect directly to postgres, the data is nice. If I connect to via Traefik then I have Bad Request when closing the connection. I have no idea what this means and whether it must mean something.

like image 867
Gander Avatar asked Dec 10 '19 09:12

Gander


People also ask

What ports need to be open for Traefik?

We're publishing the default HTTP ports 80 and 443 on the host, and making sure the container is placed within the web network we've created earlier on. Finally, we're giving this container a static name called traefik .

How do I access my Traefik dashboard?

You can now access the dashboard on the port 8080 of the Traefik instance, at the following URL: http://<Traefik IP>:8080/dashboard/ (trailing slash is mandatory).

What is path prefix in Traefik?

Use a *Prefix* matcher if your backend listens on a particular base path but also serves requests on sub-paths. For instance, PathPrefix: /products would match /products but also /products/shoes and /products/shirts . Since the path is forwarded as-is, your backend is expected to listen on /products .

What is Traefik service?

Traefik is a leading modern reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically.


1 Answers

At least for the PostgreSQL issue, it seems that the connection is started in cleartext and then upgraded to TLS:

  • Docs
  • Mailing list discussion
  • Issue on another proxy project

So it is basically impossible to use TLS termination with a proxy if said proxy doesn't support this cleartext handshake + upgrade to TLS function of the protocol.

like image 90
Jose Liber Avatar answered Oct 21 '22 14:10

Jose Liber