HAProxy migration: load balance two http proxies

I am trying to have traefik load balance two http proxies. I've had a similar architecture working with HAProxy for some time and would like to migrate this to traefik. The configuration noted here allows me to successfully make requests when the destination is http, but fails for https. Based on what we've had
working with the HAProxy configuration, I'm hoping to achieve the same with configuring traefik to pass http/https traffic with https termination taking place only at the destination.

Please let me know if there's a configuration option I've overlooked.

This details a successful request when the destination is unsecure/http:

# curl -v -x proxy.example.com:9095  http://ipinfo.io
*   Trying 192.168.1.30...
* TCP_NODELAY set
* Connected to proxy.example.com (192.168.1.30) port 9095 (#0)
> GET http://ipinfo.io/ HTTP/1.1
> Host: ipinfo.io
> User-Agent: curl/7.64.1
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Content-Type: application/json; charset=utf-8
< Date: Tue, 02 May 2023 13:05:29 GMT
< Referrer-Policy: strict-origin-when-cross-origin
< Strict-Transport-Security: max-age=2592000; includeSubDomains
< Vary: Accept-Encoding
< Via: 1.1 google
< X-Content-Type-Options: nosniff
< X-Envoy-Upstream-Service-Time: 2
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< Transfer-Encoding: chunked
<
{
  "ip": "216.144.236.70",
  "hostname": "216.144.236.70.static.quadranet.com",
...

resulting traefik log from request:

{"ClientAddr":"192.168.1.14:61830","ClientHost":"192.168.1.14","ClientPort":"61830","ClientUsername":"-","DownstreamContentSize":307,"DownstreamStatus":200,"Duration":902490179,"OriginContentSize":307,"OriginDuration":902459146,"OriginStatus":200,"Overhead":31033,"RequestAddr":"ipinfo.io","RequestContentSize":0,"RequestCount":125,"RequestHost":"ipinfo.io","RequestMethod":"GET","RequestPath":"/","RequestPort":"-","RequestProtocol":"HTTP/1.1","RequestScheme":"http","RetryAttempts":0,"RouterName":"http_router@file","ServiceAddr":"proxy01.example.com:8008","ServiceName":"allbackend@file","ServiceURL":{"Scheme":"http","Opaque":"","User":null,"Host":"proxy01.sfio.win:8008","Path":"","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":""},"StartLocal":"2023-05-02T13:07:25.864130655Z","StartUTC":"2023-05-02T13:07:25.864130655Z","entryPointName":"web","level":"info","msg":"","time":"2023-05-02T13:07:26Z"}

This details an unsuccessful request when the destination is secure/https:

# curl -v -x proxy.example.com:9095  https://ipinfo.io
*   Trying 192.168.1.30...
* TCP_NODELAY set
* Connected to proxy.example.com (192.168.1.30) port 9095 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to ipinfo.io:443
> CONNECT ipinfo.io:443 HTTP/1.1
> Host: ipinfo.io:443
> User-Agent: curl/7.64.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Tue, 02 May 2023 13:08:42 GMT
< Content-Length: 19
<
* Received HTTP code 404 from proxy after CONNECT
* CONNECT phase completed!
* Closing connection 0
curl: (56) Received HTTP code 404 from proxy after CONNECT

resulting traefik log from request:

{"ClientAddr":"192.168.1.14:62096","ClientHost":"192.168.1.14","ClientPort":"62096","ClientUsername":"-","DownstreamContentSize":19,"DownstreamStatus":404,"Duration":22308,"OriginContentSize":19,"OriginDuration":7873,"OriginStatus":404,"Overhead":14435,"RequestAddr":"ipinfo.io:443","RequestContentSize":0,"RequestCount":142,"RequestHost":"ipinfo.io","RequestMethod":"CONNECT","RequestPath":"","RequestPort":"443","RequestProtocol":"HTTP/1.1","RequestScheme":"http","RetryAttempts":0,"StartLocal":"2023-05-02T13:08:42.833629378Z","StartUTC":"2023-05-02T13:08:42.833629378Z","entryPointName":"web","level":"info","msg":"","time":"2023-05-02T13:08:42Z"}
# traefik version
Version:      2.10.1
Codename:     saintmarcelin
Go version:   go1.20.3
Built:        2023-04-27T14:52:35Z
OS/Arch:      linux/amd64

traefik.toml:

[entryPoints]
  [entryPoints.web]
    address = ":80"
[log]
  level = "DEBUG"
[accessLog]
  format = "json"
[api]
  insecure = true
[ping]
[providers.file]
  filename = "/etc/traefik/http.yml"
  watch = true

http.yml

http:
  routers:
      http_router:
          entryPoints:
            - "web"
          rule: "PathPrefix(`/`)"
          service: allbackend
  services:
      allbackend:
          loadBalancer:
              servers:
                  - url: "http://proxy01.example.com:8008"
                  - url: "http://proxy02.example.com:8008"

docker-compose.yml

version: '3'
services:
  traefik:
    container_name: traefik_t
    image: traefik:latest
    ports:
      - 9090:8080
      - 9095:80
    volumes:
      - /run/docker.sock:/run/docker.sock
      - ./traefik_config:/etc/traefik
    restart: always

Can you explain again in simple language what you want to achieve?

We found a simple tcp configuration (below) allows for both http/https requests to function properly. I'd still like to know if an http configuration is possible for a load balanced forward proxy. In other words, why does the http configuration noted above not function properly for both http and https requests? Is it not possible with traefik, or is there some configuration option I'm overlooking?

entryPoints:
  web:
    address: ":80"
log:
  level: DEBUG
accesslog:
  format: json
api:
  insecure: true
ping: {}

providers:
  file:
    filename: /etc/traefik/traefik.yml

tcp:
  routers:
    myrouter:
      entryPoints:
        - "web"
      service: backend
      rule: "HostSNI(`*`)"
  services:
    backend:
      loadBalancer:
        servers:
          - address: "192.168.20.62:8008"
          - address: "192.168.25.72:8008"

You can only use http routers with https when you have a custom cert to load via provider.file or use LetsEncrypt - Traefik needs to be able to read the headers of the request. Both options need to be enabled in entrypoint or router.

If you don’t have a cert, then you can only use a TCP router with HostSNI(`*`), because Traefik can not look into the requests.