Skip to content

Allow tunnel to ssh ports - #178

Closed
lalyos wants to merge 1 commit into
STRRL:masterfrom
lalyos:fix-ssh
Closed

Allow tunnel to ssh ports#178
lalyos wants to merge 1 commit into
STRRL:masterfrom
lalyos:fix-ssh

Conversation

@lalyos

@lalyos lalyos commented Feb 9, 2025

Copy link
Copy Markdown

I wondered if its possible to expose both http and ssh ports of a pod.
In my case I deployed gitea which has both.

After making the tunnel work by manually changing the tunnel configuration, I figgured what was missing:

  • in case of http(s) protocol the path make sense
  • for ssh (and probably for tcp) type it shouldn't be set

With a simple check I made the controller successfully expose my gitea ssh service via a cloudflare tunnel.

Example

Here is an ingress with all details:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cloudflare-tunnel-ingress-controller.strrl.dev/backend-protocol: "ssh"
  name: gitea-ssh
  namespace: gitea
spec:
  ingressClassName: cloudflare-tunnel
  rules:
  - host: ssh.mydomain.com
    http:
      paths:
        - path: '/*'
          pathType: ImplementationSpecific
          backend:
            service:
              name: gitea-ssh
              port:
                number: 2222

I was using the official helm chart to deploy gitea, and first the svc had a couple of issue:

  • it was headless (ClusteIp: None) which is not supported
  • there was a port mapping 22->2222 (port:22, targetPort:2222) which is convenient inside the cluster, so one can ssh with a servicename, skipping the port spec, but it did not work

The final relevant chart values to fix the service:

helm upgrade -i  \
  gitea \
  --repo https://dl.gitea.io/charts  \
  gitea \
  --version 10.6.0 \
  --namepace gitea \
  --create-namespace \
  --values values-gitea.yaml

The content of values-gitea.yaml

service:
  http:
    clusterIP:
  ssh:
    clusterIP:
    port: 2222
    targetPort: 2222

@lalyos lalyos changed the title make ssh tunnel work Allow tunnel to ssh ports Feb 9, 2025
@lalyos

lalyos commented Feb 9, 2025

Copy link
Copy Markdown
Author

In case somebody want to test it, I've pushed my image to dockerhub.

helm upgrade -i \
  cf-tunnel \
  --repo https://helm.strrl.dev cloudflare-tunnel-ingress-controller \
  --namespace cloudflare-ingress \
  --create-namespace \
  --values values-cf-tunnel.yaml

Where values-cf-tunnel.yaml:

image:
  repository: lalyos/cloudflare-tunnel-ingress-controller

cloudflare:
  accountId: 888888888888faeb6fd019aaaaaa
  apiToken: qYBe_khasdkjhasdakhsdCPPU
  tunnelName: k8s-ssh-ing
ingressClass:
  name: cloudflare-tunnel
  isDefaultClass: true

@STRRL

STRRL commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Closing in favor of a fresh implementation: the idea is right (non-HTTP protocols like ssh/tcp must not carry a path in the tunnel rule), but this branch predates large changes to transform.go and only handles ssh. We are landing a generalized version that omits Path for all non-http(s) backend protocols, with tests — credit to this PR for identifying the issue. Thanks @lalyos!

@STRRL STRRL closed this Jul 19, 2026
STRRL added a commit that referenced this pull request Jul 19, 2026
Path based routing only exists for http(s) in cloudflare tunnel
ingress rules. For backend protocols like ssh, rdp or tcp the Ingress
spec still requires a dummy http path entry, which previously leaked
into the tunnel rule and broke the tunnel for those protocols.

Supersedes #178, credit to @lalyos for identifying the issue.
STRRL added a commit that referenced this pull request Jul 19, 2026
* fix: omit tunnel rule path for non http backend protocols

Path based routing only exists for http(s) in cloudflare tunnel
ingress rules. For backend protocols like ssh, rdp or tcp the Ingress
spec still requires a dummy http path entry, which previously leaked
into the tunnel rule and broke the tunnel for those protocols.

Supersedes #178, credit to @lalyos for identifying the issue.

* test: add e2e coverage for tcp exposure through the tunnel

Deploys redis, exposes it with the backend-protocol tcp annotation and
performs a real PING round trip from the test runner through cloudflared
access tcp, the Cloudflare edge and the tunnel. Before the path fix the
tcp rule carried a path and this data path did not work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants