Can I route HTTP traffic as HTTPS to an external service?

I would like pods in my mesh to be able to send HTTP requests to a host in the cluster, and then configure Istio to proxy those requests to an external service that is expecting HTTPS. Here’s what I’m experimenting with:

apiVersion: v1
kind: Service
metadata:
  name: httpbin
spec:
  ports:
  - name: http
    port: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      containers:
      - name: httpbin
        image: docker.io/kennethreitz/httpbin
        ports:
        - containerPort: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  gateways:
  - mesh
  hosts:
  - httpbin
  http:
    - route:
      - weight: 0
        destination:
          host: httpbin.default.svc.cluster.local
          port:
            number: 80
      - weight: 0
        destination:
          host: httpbin.org  
          port:
            number: 80
      - weight: 100
        destination:
          host: httpbin.org  
          port:
            number: 443
      rewrite:
        authority: httpbin.org
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin
spec:
  hosts:
  - httpbin.org
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
  location: MESH_EXTERNAL

If I change the weights, the first two destinations (to a local or external HTTP service) work, but the third one (to a remote HTTPS service) doesn’t - it hangs for a while then returns 503. I tried experimenting with DestinationRule to apply a TLS traffic policy to httpbin.org, but it didn’t seem to help.

Is there a way to accomplish this?

1 Like

Can you share your VirtualService and DestinationRule?

  • EDIT sorry, failed to realize the text box scrolled

do you have the istio-egressgateway deployed? This example from the docs seems to cover your usecase: https://preliminary.istio.io/docs/examples/advanced-gateways/egress-gateway-tls-origination/#perform-tls-origination-with-an-egress-gateway

Key takeaways, in your ServiceEntry, port 443 is actually defined as type HTTP, and the DestinationRule initiates the HTTPS

Hi,

Did you manage to solve this? I’ve followed instructions in the docs, but still failing to get this to work.

Opened a stackoverflow issue, but it’s getting virtually no attention as the community is still quite small :slight_smile: - https://stackoverflow.com/questions/56055431/how-to-configure-tls-origination-in-istio

Any help much appreciated!
Viktor

Viktor, have you confirmed that you can call/curl your external service directly from the mesh without the TLS Origination?

kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - https://someurl.somedomain.com/

Does that return the expected output?

1 Like

Hello,

Yes, I can hit the service without TLS origination by specifying a service entry and a destination rule.

As soon as I add TLS origination in the mix, I end up with 504 errors.

In stackoverflow you said you got a 404 error? Is it 404 or 504? That makes a big difference :slight_smile:

Also why do you need the destination rule in the not-TLS-origination case?

Hi,

Apologies, initial error was 404 - I fixed that and I’m now getting 504 as the gateway is timing out.

Interestingly enough, I just took out the timeout and retries section from yaml and TLS origination works - I can curl from the container to the external service whilst addressing it over http.

It looks like the retries are causing a problem.

Regarding your second question on destination rules, you are right - I don’t need it. I’m new to ISTIO :slight_smile: I only need it if I want to encrypt the outgoing traffic.

As soon as you take out the following configuration, the TLS origination starts working:

retries:
  attempts: 10
  perTryTimeout: 1s      
  retryOn: gateway-error,connect-failure,refused-stream,retriable-4xx,5xx

Hi again,

Got to the bottom of this. It turns out that service we were calling got slower recently and a 1 second timeout simply was not enough. Increasing the timeout to 2 seconds has fixed the problem.

Thank you for taking the time to help!

Viktor