Como se conectar aos Serviços TCP do Traefik com a configuração TLS ativada?

13

Estou tentando configurar o Traefik para ter acesso aos serviços através de nomes de domínio e para não precisar definir portas diferentes. Por exemplo, dois serviços MongoDB, ambos na porta padrão, mas em domínios diferentes example.localhoste example2.localhost. Somente este exemplo funciona. Quero dizer, outros casos provavelmente funcionam, mas não consigo me conectar a eles e não entendo qual é o problema. Provavelmente isso nem é um problema com o Traefik.

Eu preparei um repositório com um exemplo que funciona. Você só precisa gerar seu próprio certificado com o mkcert . A página em example.localhostretorna o 403 Forbiddenerro, mas você não deve se preocupar com isso, porque o objetivo desta configuração é mostrar que o SSL está funcionando (cadeado, status verde). Portanto, não se concentre 403.

Somente a conexão SSL com o mongoserviço funciona. Eu testei com o programa Robo 3T . Depois de selecionar a conexão SSL, fornecer o host example.localhoste selecionar o certificado para uma conexão autoassinada (ou própria) funciona. E essa é a única coisa que funciona dessa maneira. As conexões com redis( Redis Desktop Manager ) e com pgsql( PhpStorm , DBeaver , DbVisualizer ) não funcionam, independentemente de eu fornecer certificados ou não. Não encaminho SSL para serviços, apenas conecto ao Traefik. Passei longas horas nisso. Eu procurei na internet. Ainda não encontrei a resposta. Alguém resolveu isso?

PS. Como trabalho no Linux Mint, minha configuração deve funcionar neste ambiente sem nenhum problema. Eu pediria soluções para Linux.


Se você não deseja navegar no repositório , anexe os arquivos mais importantes:

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"

Construir e executar

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

Prepare passo a passo

  1. Instale o mkcert (execute também mkcert -installpara a CA)
  2. Clonar meu código
  3. Na certspasta executarmkcert example.localhost
  4. Iniciar contêiner por docker-compose up -d
  5. Abra a página https: //example.localhost/ e verifique se é uma conexão segura
  6. Se o endereço http: //example.localhost/ não estiver acessível, adicione 127.0.0.1 example.localhosta/etc/hosts

Certos:

  • Público: ./certs/example.localhost.pem
  • Privado: ./certs/example.localhost-key.pem
  • CA: ~/.local/share/mkcert/rootCA.pem

Teste do MongoDB

  1. Instale o Robo 3T
  2. Crie uma nova conexão:
    • Endereço: example.localhost
    • Usar protocolo SSL
    • Certificado da CA: rootCA.pem(ou certificado autoassinado)
  3. Ferramenta de teste:

teste

Teste Redis

  1. Instale o RedisDesktopManager
  2. Crie uma nova conexão:
    • Endereço: example.localhost
    • SSL
    • Chave pública: example.localhost.pem
    • Chave privada: example.localhost-key.pem
    • Autoridade: rootCA.pem
  3. Ferramenta de teste:

teste


Tão longe:

  1. Pode se conectar ao Postgres via IP (informações do Traefik)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable

insira a descrição da imagem aqui

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

insira a descrição da imagem aqui


Experimente o telet (o IP muda a cada reinicialização do docker):

> 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.

Se eu me conectar diretamente ao postgres, os dados serão bons. Se eu conectar através do Traefik, tenho uma solicitação incorreta ao fechar a conexão. Não faço ideia do que isso significa e se deve significar alguma coisa.

Ganso
fonte
I can't connect to them-> como você testou e qual foi o erro?
Jan Garaj
@JanGaraj Adicionei uma instrução passo a passo
Gander
Connections to redis (Redis Desktop Manager) ... do not work, mas a captura de tela mostra Successful connection-? Por que você não está testando em nível baixo com curl, openssl, telnet, ...? Por que você não está testando netstatse essas portas de aplicativos estão realmente ligadas ao traefik na 127.0.0.1interface?
Jan Garaj
O contêiner com traefik e bancos de dados é executado no mesmo host?
Ryabchenko Alexander
@RyabchenkoAlexander sim, em recipientes de encaixe
Gander

Respostas:

2

Pelo menos para a questão do PostgreSQL, parece que a conexão é iniciada em texto não criptografado e depois atualizada para o TLS:

Portanto, é basicamente impossível usar a terminação TLS com um proxy se esse proxy não suportar esse handshake de texto não criptografado + atualizar para a função TLS do protocolo.

Jose Liber
fonte