Jak połączyć się z usługami Traefik TCP z włączoną konfiguracją TLS?

13

Próbuję skonfigurować Traefik, aby uzyskać dostęp do usług za pośrednictwem nazw domen i aby nie musiałem ustawiać różnych portów. Na przykład dwie usługi MongoDB, obie na domyślnym porcie, ale w różnych domenach, example.localhostiexample2.localhost . Działa tylko ten przykład. Mam na myśli, że inne przypadki prawdopodobnie działają, ale nie mogę się z nimi połączyć i nie rozumiem na czym polega problem. Prawdopodobnie nie jest to nawet problem z Traefikiem.

Przygotowałem repozytorium z przykładem, który działa. Wystarczy wygenerować własny certyfikat za pomocą mkcert . Strona w example.localhostzwraca 403 Forbiddenbłąd, ale nie powinieneś się tym przejmować, ponieważ celem tej konfiguracji jest pokazanie, że SSL działa (kłódka, zielony status). Więc nie skupiaj się na403 .

mongoDziała tylko połączenie SSL z usługą. Testowałem to z programem Robo 3T . Po wybraniu połączenia SSL działa udostępnienie hosta example.localhosti wybranie certyfikatu dla połączenia z podpisem własnym (lub własnego). I to jedyna rzecz, która działa w ten sposób. Połączenia z redis( Redis Desktop Manager ) i pgsql( PhpStorm , DBeaver , DbVisualizer ) nie działają, niezależnie od tego, czy dostarczę certyfikaty, czy nie. Nie przekazuję SSL do usług, łączę się tylko z Traefik. Spędziłem nad tym długie godziny. Przeszukałem internet. Nie znalazłem jeszcze odpowiedzi. Czy ktoś to rozwiązał?

PS. Pracuję na Linux Mint, więc moja konfiguracja powinna działać w tym środowisku bez żadnych problemów. Poprosiłbym o rozwiązania dla Linuksa.


Jeśli nie chcesz przeglądać repozytorium , dołączam najważniejsze pliki:

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"

Kompiluj i uruchamiaj

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

Przygotuj się krok po kroku

  1. Zainstaluj mkcert (uruchom także mkcert -installdla CA)
  2. Sklonuj mój kod
  3. W certsfolderze uruchommkcert example.localhost
  4. Uruchom kontener przez docker-compose up -d
  5. Otwórz stronę https: //example.localhost/ i sprawdź, czy jest to bezpieczne połączenie
  6. Jeśli adres http: //example.localhost/ jest nieosiągalny , dodaj 127.0.0.1 example.localhostdo/etc/hosts

Certyfikaty:

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

Przetestuj MongoDB

  1. Zainstaluj Robo 3T
  2. Utwórz nowe połączenie:
    • Adres: example.localhost
    • Użyj protokołu SSL
    • Certyfikat CA: rootCA.pem(lub samopodpisany certyfikat)
  3. Narzędzie testowe:

test

Przetestuj Redis

  1. Zainstaluj RedisDesktopManager
  2. Utwórz nowe połączenie:
    • Adres: example.localhost
    • SSL
    • Klucz publiczny: example.localhost.pem
    • Prywatny klucz: example.localhost-key.pem
    • Autorytet: rootCA.pem
  3. Narzędzie testowe:

test


Jak dotąd:

  1. Może połączyć się z Postgres przez IP (informacje z Traefik)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable

wprowadź opis zdjęcia tutaj

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

wprowadź opis zdjęcia tutaj


Spróbuj telet (adres IP zmienia się przy każdym ponownym uruchomieniu dokera):

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

Jeśli połączę się bezpośrednio z postgres, dane są miłe. Jeśli połączę się przez Traefik, mam złe żądanie podczas zamykania połączenia. Nie mam pojęcia, co to znaczy i czy to musi coś znaczyć.

Gąsior
źródło
I can't connect to them-> jak to przetestowałeś i jaki był błąd?
Jan Garaj
@ JanGaraj Dodałem instrukcję krok po kroku
Gander
Connections to redis (Redis Desktop Manager) ... do not work, ale zrzut ekranu pokazuje Successful connection-? Dlaczego nie testujesz na niskim poziomie curl, openssl, telnet, ...? Dlaczego nie netstattestujesz, czy te porty aplikacji są naprawdę powiązane z traefikiem w 127.0.0.1interfejsie?
Jan Garaj
Czy kontener z traefikiem i bazami danych działa na tym samym hoście?
Ryabchenko Alexander
@RyabchenkoAlexander tak, w kontenerach dokerów
Gander

Odpowiedzi:

2

Przynajmniej w przypadku problemu PostgreSQL wydaje się, że połączenie jest uruchamiane w postaci tekstu jawnego, a następnie uaktualniane do TLS:

Zasadniczo więc nie można używać zakończenia TLS z serwerem proxy, jeśli wspomniany serwer proxy nie obsługuje tego jawnego uzgadniania tekstu + aktualizacji do protokołu TLS.

Jose Liber
źródło