TCP Router for TLS Communication Passthrough

Hi,

I'm running an OpenVPN Container behind Traefik. How can I use the HostSNI rule to forward all TCP communication to that Container accessing via openvpn.mydomain.net.

I currently got the OpenVPN Container working and being accessible over traefik using a HostSNI(*) wilcard:

version: '3.7'

services:
  openvpn:
    container_name: openvpn
    build: .
    restart: always
    networks:
      - web
    volumes:
      - openvpn-data:/etc/openvpn
    cap_add:
      - NET_ADMIN
    labels:
      - "traefik.enable=true"
      - "traefik.tcp.routers.openvpn.entrypoints=websecure"
      - "traefik.tcp.routers.openvpn.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.openvpn.service=openvpn"
      - "traefik.tcp.services.openvpn.loadbalancer.server.port=1194"
      - "traefik.docker.network=web"

networks:
  web:
    external: true

volumes:
  openvpn-data:
    name: openvpn-data

But this doesn't allow me to run multiple TCP containers through Traefik, and it's unclear to me why the OpenVPN TLS communication is not being block in this case. (So this setup is now working as a TCP and TLS passtrough)

Ideally I would want to add these two lines to specify only TLS communication on Domain 'openvpn.mydomain.net' should be passed through to that container:

      - "traefik.tcp.routers.openvpn.rule=HostSNI(`openvpn.mydomain.net`)"
      - "traefik.tcp.routers.openvpn.tls.passthrough=true"

But this isn't working. Can this be done?

Kind regards,
Frederic Depuydt

Hi @f.depuydt, thanks for your interest!

It looks like that OpenVPN does not support the Server Name Indication (SNI):

Without this support, Traefik cannot "guess" the hostname that the client tries to connect to.
This is why the TCP router rule HostSNI(*) works: it catches all incoming TCP requests on the associated entrypoint (websecure) and send everything to the associated service.

Don't worry about the encryption: OpenVPN still encrypts at the application layer, with the current working configuration using HostSNI(*) . It's just that Traefik cannot manage the TLS part for you as it forwards the encrypted TCP packets "as it" to the OpenVPN server which takes care of decryption:; it is "TLS passtrough" by default at layer 7, while traefik routes at layer 4.

The only limitation is that you cannot serve 2 different OpenVPN servers on the same entrypoints.

Does it clarify it for you?

1 Like

Sorry for the necropost but there aren't many good hits on google for this so I thought it worth a try.

Basically the OPs usecase nearly 2 years ago matches perfectly with what I'm trying to do today. But given the time since I think I now see evidence that the OpenVPN client has been made SNI aware...

However my testing of this scenario still fails with what I believe is traefik's inability to match the incoming connection against any other rule than HostSNI(*).

Honestly, I don't have a good enough justification for why I want to do this as I only have one TCP service behind my traefik proxy so its not like I can't work with Frederic's solution from 2 years back. I just enjoy the journey so if anyone has an answer here I'd be grateful :smiley: