【问题标题】:How to SSL termination in docker traefik for using varnish如何在 docker traefik 中终止 SSL 以使用清漆
【发布时间】:2021-07-31 02:21:11
【问题描述】:

我正在使用 docker traefik 并在该 varnish 后面进行缓存,而我的网站在 varnish 后面。 这是我的网站和清漆服务的 docker-compose:

version: "3.7"


services:
  dev-ui-service:
    image: mywebsite.ui:latest
    networks:
      - localnetwork

  varnish:
    image: myvarnish:latest
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.ui.rule=Host(`mydomain.com`)"
        - "traefik.http.routers.ui.entrypoints=web"
        - "traefik.http.services.ui.loadbalancer.server.port=80"
        - "traefik.http.routers.ui-secured.rule=Host(`mydomain.com`)"
        - "traefik.http.routers.ui-secured.entrypoints=web-secured"
        - "traefik.http.routers.ui-secured.tls.certresolver=mytlschallenge"
        - "traefik.docker.network=traefik-proxy"
      mode: replicated
      replicas: 1
      resources:
        limits:
          cpus: '0.5'
          memory: 200M
        reservations:
          cpus: '0.2'
          memory: 20M
    networks:
      - localnetwork
      - traefik-proxy
    depends_on:
      - dev-ui-service

networks:
  localnetwork:
  traefik-proxy:
    external: true

这是我的 default.vcl 文件:

vcl 4.0;
backend default {
  .host = "dev-ui-service";
  .port = "4200";
}

# If you don't include below, header Age in response to client always be 0

sub vcl_deliver {
  # Display hit/miss info
  if (obj.hits > 0) {
    set resp.http.V-Cache = "HIT";
  }
  else {
    set resp.http.V-Cache = "MISS";
  }
  set resp.http.Access-Control-Allow-Origin = "*";
  set resp.http.Access-Control-Allow-Headers = "Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With";
  set resp.http.Allow = "GET, POST";
  set resp.http.Access-Control-Allow-Credentials = "true";
  set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, OPTIONS, PATCH";
  set resp.http.Access-Control-Expose-Headers = "X-Pagination-Total, X-Pagination-Page, X-Pagination-Limit";
}
sub vcl_backend_response {
  if (beresp.status == 200) {
    unset beresp.http.Cache-Control;
    set beresp.http.Cache-Control = "public; max-age=200";
    set beresp.ttl = 200s;
  }
  set beresp.http.Served-By = beresp.backend.name;
  set beresp.http.V-Cache-TTL = beresp.ttl;
  set beresp.http.V-Cache-Grace = beresp.grace;
}

一切都很好,但清漆不支持 https 所以所有来自 https MISS 的请求。 当请求从 traefik 发送到清漆时,我如何终止 SSL?

【问题讨论】:

    标签: docker varnish traefik


    【解决方案1】:

    内置 VCL 行为

    您的 VCL 扩展了 vcl_delivervcl_backend_response 子例程的标准行为。因为您没有为vcl_recv 提供任何逻辑,所以将使用 Varnish 的内置 VCL 行为。

    事实上,Varnish 总是使用内置的 VCL,除非相关子程序被覆盖。

    https://github.com/varnishcache/varnish-cache/blob/6.0/bin/varnishd/builtin.vcl

    为什么会错过?

    If we look at the built-in VCL for `vcl_recv`, you'll see that there are some caching rules in place:
    
    sub vcl_recv {
        if (req.method == "PRI") {
            /* This will never happen in properly formed traffic (see: RFC7540) */
            return (synth(405));
        }
        if (!req.http.host &&
          req.esi_level == 0 &&
          req.proto ~ "^(?i)HTTP/1.1") {
            /* In HTTP/1.1, Host is required. */
            return (synth(400));
        }
        if (req.method != "GET" &&
          req.method != "HEAD" &&
          req.method != "PUT" &&
          req.method != "POST" &&
          req.method != "TRACE" &&
          req.method != "OPTIONS" &&
          req.method != "DELETE" &&
          req.method != "PATCH") {
            /* Non-RFC2616 or CONNECT which is weird. */
            return (pipe);
        }
    
        if (req.method != "GET" && req.method != "HEAD") {
            /* We only deal with GET and HEAD by default */
            return (pass);
        }
        if (req.http.Authorization || req.http.Cookie) {
            /* Not cacheable by default */
            return (pass);
        }
        return (hash);
    }
    
    

    当满足以下条件时会发生缓存未命中:

    • GETHEAD 以外的请求方法
    • 请求包含Authorization 标头
    • 请求包含Cookie 标头

    最可能的情况是导致MISS的请求包含cookie。

    如何将未命中变为命中

    假设 cookie 是问题所在,你应该在 vcl_recv 中编写一些 VCL 逻辑,并确定哪些 cookie 被保留,哪些 cookie 应该被删除。

    大多数跟踪 cookie 对服务器端没有影响,可以删除。

    其他 cookie 由应用程序使用,无法删除。

    如果特定的 URL 资源需要 cookie 值,您可以使用 return(pass) 确保 Varnish 不会缓存它。

    不需要 cookie 值的其他页面可以剥离这些 cookie 以确保缓存命中。

    对于需要 cookie,但 cookie 值具有较低且可控变化的页面,您可以使用缓存变化并将 cookie 值缓存在 vcl_hash 中。

    再次,我假设 cookie 是导致缓存未命中的原因。

    如何优化 TLS 终止

    Varnish 的开源版本不支持原生 TLS,因此需要终止。

    Varnish 通过支持 PROXY protocol 来促进 TLS 终止。显然是Traefik supports it as well

    您可以通过打开一个额外的监听端口在 Varnish 级别启用 PROXY 协议。

    而一个简化的仅限 HTTP 的 varnishd 命令看起来像这样:

    varnishd -a :80 -f /etc/varnish/default.vcl
    

    由 PROXY 驱动的 varnishd 命令可能如下所示:

    varnishd -a :80 -a :8443,PROXY -f /etc/varnish/default.vcl
    

    如您所见,我在端口8443 上添加了一个额外的监听接口,它只支持PROXY 流量。端口 80 对于常规 HTTP 流量仍处于活动状态。

    然后您可以配置 Traefik 以终止 TLS 并将流量路由到 Varnish。如果您在 Traefik 上启用 PROXY 协议,Varnish 将能够利用该协议。

    在 VCL 中,您可以使用以下 VCL sn-p 检测 HTTP/HTTPS 请求:

    vcl 4.1;
    
    import proxy;
    
    sub vcl_recv {
        if (proxy.is_ssl()) {
            set req.http.X-Forwarded-Proto = "https";
        } else {
            set req.http.X-Forwarded-Proto = "http";
        }
    }
    

    然后您可以在您的应用程序中返回一个Vary: X-Forwarded-Proto 响应标头,以创建基于协议的缓存变体。

    PROXY 协议的另一个优点是X-Forwarded-For 标头始终包含原始客户端的客户端 IP 地址,而不管跃点数如何。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-01
      • 2017-08-05
      • 2017-08-12
      • 2014-03-04
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2019-01-30
      相关资源
      最近更新 更多