如何在启用 TLS 配置的情况下连接到 Traefik TCP 服务?

Gan*_*der 14 postgresql ssl tcp docker traefik

我正在尝试配置Traefik,以便我可以通过域名访问服务,并且不必设置不同的端口。例如,两个 MongoDB 服务,都在默认端口上,但在不同的域中,example.localhost并且example2.localhost. 只有这个例子有效。我的意思是,其他情况可能有效,但我无法连接到它们,我不明白问题是什么。这可能甚至不是 Traefik 的问题。

我准备了一个包含一个有效示例的存储库。您只需要使用mkcert生成您自己的证书。页面example.localhost返回403 Forbidden错误,但您不必担心,因为此配置的目的是显示 SSL 正在工作(挂锁,绿色状态)。所以不要专注于403.

只有到mongo服务的 SSL 连接有效。我用Robo 3T程序对其进行了测试。选择 SSL 连接后,提供主机example.localhost并为自签名(或自己的)连接选择证书即可。这是唯一有效的方法。无论我是否提供证书,与redisRedis 桌面管理器)和pgsqlPhpStormDBeaverDbVisualizer)的连接都不起作用。我不将 SSL 转发到服务,我只连接到 Traefik。我花了很长时间在上面。我在互联网上搜索。我还没有找到答案。有没有人解决过这个问题?

附注。我在 Linux Mint 上工作,所以我的配置应该可以在这个环境中正常工作,没有任何问题。我会要求 Linux 的解决方案。


如果您不想浏览存储库,我附上最重要的文件:

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

Run Code Online (Sandbox Code Playgroud)

配置文件

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

Run Code Online (Sandbox Code Playgroud)

构建和运行

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

Run Code Online (Sandbox Code Playgroud)

一步一步准备

  1. 安装mkcert(也mkcert -install为 CA运行)
  2. 克隆我的代码
  3. certs文件夹中运行mkcert example.localhost
  4. 启动容器 docker-compose up -d
  5. 打开页面https://example.localhost/并检查它是否是安全连接
  6. 如果地址http://example.localhost/无法访问,请添加127.0.0.1 example.localhost/etc/hosts

证书:

  • 民众: ./certs/example.localhost.pem
  • 私人的: ./certs/example.localhost-key.pem
  • CA: ~/.local/share/mkcert/rootCA.pem

测试 MongoDB

  1. 安装机器人 3T
  2. 创建新连接:
    • 地址: example.localhost
    • 使用 SSL 协议
    • CA 证书:(rootCA.pem或自签名证书)
  3. 测试工具:

测试

测试Redis

  1. 安装RedisDesktopManager
  2. 创建新连接:
    • 地址: example.localhost
    • 安全证书
    • 公钥: example.localhost.pem
    • 私钥: example.localhost-key.pem
    • 权威: rootCA.pem
  3. 测试工具:

测试


迄今为止:

  1. 可以通过 IP 连接到 Postgres(来自 Traefik 的信息)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

jdbc:postgresql://172.21.0.4:5432/postgres?sslfactory=org.postgresql.ssl.NonValidatingFactory
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


尝试 Telet(每次 docker 重启时 IP 都会更改):

mkcert example.localhost # in ./certs/
docker-compose up -d
Run Code Online (Sandbox Code Playgroud)
jdbc:postgresql://172.21.0.4:5432/postgres?sslmode=disable
Run Code Online (Sandbox Code Playgroud)

如果我直接连接到 postgres,数据很好。如果我通过 Traefik 连接,那么在关闭连接时我有错误的请求。我不知道这意味着什么以及它是否一定意味着什么。

小智 4

至少对于 PostgreSQL 问题,似乎连接是以明文启动,然后升级到 TLS:

因此,如果代理不支持这种明文握手+升级到协议的 TLS 功能,则基本上不可能通过代理使用TLS 终止。