Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request path that contains a hostname results in wrong routing #753

Closed
chitoku-k opened this issue Mar 15, 2021 · 2 comments
Closed

Request path that contains a hostname results in wrong routing #753

chitoku-k opened this issue Mar 15, 2021 · 2 comments
Labels
Milestone

Comments

@chitoku-k
Copy link
Contributor

Description of the problem

Let's say we have the ingress in the last section of this issue. This ingress only specifies that it should route traffic by its hostname; however, when the request path contains a subdomain, it routes to a wrong one as in the following:

OK: example.com goes to nginx-alice

$ curl example.com
nginx-alice-7f9b8cd46d-8rll5

OK: subdomain.example.com goes to nginx-bob

$ curl subdomain.example.com
nginx-bob-848d7b78d9-sv4cv

WRONG: subdomain.example.com/example.com goes to nginx-alice

$ curl subdomain.example.com/example.com
nginx-alice-7f9b8cd46d-8rll5

Expected behavior

example.com goes to nginx-alice

$ curl example.com
nginx-alice-7f9b8cd46d-8rll5

subdomain.example.com goes to nginx-bob

$ curl subdomain.example.com
nginx-bob-848d7b78d9-sv4cv

subdomain.example.com/example.com goes to nginx-bob

$ curl subdomain.example.com/example.ocm
nginx-bob-848d7b78d9-sv4cv

Steps to reproduce the problem

  1. Deploy the following manifest to a Kubernetes cluster:
    (It contains two nginx Pods that print each Pod name respectively whatever path it is given)
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nginx-conf
      namespace: default
    data:
      default.conf.template: |
        server {
          listen 80 default;
          listen [::]:80 default;
          server_name _;
          keepalive_timeout 0;
    
          location / {
            add_header Content-Type text/plain;
            return 200 "$BODY\n";
          }
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-alice
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx-alice
      template:
        metadata:
          labels:
            app: nginx-alice
        spec:
          containers:
            - name: web
              image: nginx:1.19.7-alpine
              env:
                - name: BODY
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
              volumeMounts:
                - name: nginx-conf
                  mountPath: /etc/nginx/templates
              ports:
                - name: http
                  containerPort: 80
          volumes:
            - name: nginx-conf
              configMap:
                name: nginx-conf
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-alice
      namespace: default
    spec:
      ports:
        - name: http
          protocol: TCP
          port: 80
          targetPort: 80
      selector:
        app: nginx-alice
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-bob
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx-bob
      template:
        metadata:
          labels:
            app: nginx-bob
        spec:
          containers:
            - name: web
              image: nginx:1.19.7-alpine
              env:
                - name: BODY
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
              volumeMounts:
                - name: nginx-conf
                  mountPath: /etc/nginx/templates
              ports:
                - name: http
                  containerPort: 80
          volumes:
            - name: nginx-conf
              configMap:
                name: nginx-conf
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-bob
      namespace: default
    spec:
      ports:
        - name: http
          protocol: TCP
          port: 80
          targetPort: 80
      selector:
        app: nginx-bob
  2. Deploy the ingress in the previous section
  3. curl to HAProxy

Environment information

HAProxy Ingress version: v0.11 and v0.12 (NOT reproducible in v0.10)

Command-line options:

--configmap=ingress-controller/haproxy-ingress

Global options:

apiVersion: v1
kind: ConfigMap
metadata:
  name: haproxy-ingress
  namespace: ingress-controller
data:
  bind-http: ':80,:::80'

Ingress objects:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
  namespace: default
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-alice
                port:
                  number: 80
    - host: subdomain.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-bob
                port:
                  number: 80
@jcmoraisjr
Copy link
Owner

Good catch, thanks for the report. This behavior comes from the way haproxy's dir match type works - it's matching the pattern list with your input without start from the beginning of the string. I'll try a proper fix in the next few days, in the mean time you can work around your configuration changing pathType from Prefix to ImplementationSpecific.

@jcmoraisjr
Copy link
Owner

v0.12.2 and v0.11.5 were just released and fixes this issue. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants