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.localhost
iexample2.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.localhost
zwraca 403 Forbidden
błą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
.
mongo
Dział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.localhost
i 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
- Zainstaluj mkcert (uruchom także
mkcert -install
dla CA) - Sklonuj mój kod
- W
certs
folderze uruchommkcert example.localhost
- Uruchom kontener przez
docker-compose up -d
- Otwórz stronę https: //example.localhost/ i sprawdź, czy jest to bezpieczne połączenie
- Jeśli adres http: //example.localhost/ jest nieosiągalny , dodaj
127.0.0.1 example.localhost
do/etc/hosts
Certyfikaty:
- Publiczny:
./certs/example.localhost.pem
- Prywatny:
./certs/example.localhost-key.pem
- CA:
~/.local/share/mkcert/rootCA.pem
Przetestuj MongoDB
- Zainstaluj Robo 3T
- Utwórz nowe połączenie:
- Adres:
example.localhost
- Użyj protokołu SSL
- Certyfikat CA:
rootCA.pem
(lub samopodpisany certyfikat)
- Adres:
- Narzędzie testowe:
Przetestuj Redis
- Zainstaluj RedisDesktopManager
- Utwórz nowe połączenie:
- Adres:
example.localhost
- SSL
- Klucz publiczny:
example.localhost.pem
- Prywatny klucz:
example.localhost-key.pem
- Autorytet:
rootCA.pem
- Adres:
- Narzędzie testowe:
Jak dotąd:
- Może połączyć się z Postgres przez IP (informacje z Traefik)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable
jdbc:postgresql://172.21.0.4:5432/postgres?sslfactory=org.postgresql.ssl.NonValidatingFactory
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ć.
I can't connect to them
-> jak to przetestowałeś i jaki był błąd?Connections to redis (Redis Desktop Manager) ... do not work
, ale zrzut ekranu pokazujeSuccessful connection
-? Dlaczego nie testujesz na niskim poziomiecurl, openssl, telnet, ...
? Dlaczego nienetstat
testujesz, czy te porty aplikacji są naprawdę powiązane z traefikiem w127.0.0.1
interfejsie?Odpowiedzi:
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.
źródło