Is it possible to use Istio as a reverse proxy? (similar to nginx proxy_pass)

I running on AWS + EKS + Istio, and I using AWS Elasticsearch Service for logging. By default, AWS Kibana is not exposed to the Internet, and in order to do that they propose three approaches. One of the approaches is to deploy a dedicated Nginx to serve as a reverse proxy, which will pass traffic to the Kibana.

I wondering, since I already have Istio, maybe I can save from redundant Nginx deployment and just use Istio traffic management capabilities.

I want to navigate from the Internet to URL https://logs.myproduct.net, traffic will arrive to Istio gateway, it will terminate SSL and then establish connection to the Kibana and pass the traffic.

In order to do that, I created a virtual service:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: kibana-proxy
  namespace: myproduct
spec:
  hosts:
  - "logs.myproduct.net"
  gateways:
  - myproductgateway
  http:
    - route:
      - destination:
          port:
            number: 443
          host: vpc-xxxxxx.amazonaws.com

I getting 503.

Is it possible to do what I intending for or I completely not in the right direction?

Hello,

it should work! Create ServiceEntry for domain where kibana is. Then create DestinationRule with SIMPLE tls mode. Do not forget about sni. Then it should work. :slight_smile:

Hi @Tomas_Kohout,

Added Destination Rule as suggested:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: kibana-proxy-tls-rule
spec:
  host: "*.amazonaws.com"
  trafficPolicy:
    tls:
      mode: SIMPLE
    sni: "vpc-xxxxxx.amazonaws.com"

I do have ServiceEntry:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: aws
spec:
  hosts:
  - "*.amazonaws.com"
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  location: MESH_EXTERNAL

Still 503… any ideas?

sni has bad indentation. Also try to add port 80 to ServiceEntry. I remember that there was some issue when port 80 was not specified. If that won’t work, try to look into envoy config about what is wrong.

Hey!
I have to achieve the exact same thing.
Could you please share if you got it to work?

Hi,

I did not. If you will succeed, please share your solution.

Thanks

I got this part to work.
Try replacing your “internal host” with ‘something.local’. ‘amazon.local’ e.g.

I guess it would be something like:

VirtualService:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: kibana-proxy
  namespace: myproduct
spec:
  hosts:
  - "logs.myproduct.net"
  gateways:
  - myproductgateway
  http:
    - route:
      - destination:
          port:
            number: 443
          host: amazon.local

ServiceEntry:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: aws
spec:
  hosts:
  - amazon.local
  ports:
  - number: 443
    name: https
    protocol: HTTPS
  location: MESH_EXTERNAL
  resolution: DNS
  endpoints:
    - address: actual.host.amazonaws.com
      ports:
        https: 443

In my case it’s HTTP, not HTTPS. Don’t think it would matter for the host name thing, but just in case…

@Illidan we were tasked with the same challenge two days ago. Looking at this thread helped, but did not solve our problems completely. In the end we got it working after following the Istio guide for TLS origination and then adapting it to our use case.

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: kibana
  namespace: logging
spec:
  hosts:
  - aws.local
  ports:
  - number: 80
    name: http-port
    protocol: HTTP
  - number: 443
    name: https-port-for-tls-origination
    protocol: HTTPS
  resolution: DNS
  endpoints:
    - address: vpc-xxxxxxxxx..amazonaws.com
      ports:
        https: 443
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: kibana
  namespace: logging
spec:
  hosts:
  - aws.local
  http:
  - match:
    - port: 80
    route:
    - destination:
        host: aws.local
        # subset: tls-origination
        port:
          number: 443
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: kibana
  namespace: logging
spec:
  host: aws.local
  # subsets:
  # - name: tls-origination
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
    portLevelSettings:
    - port:
        number: 443
      tls:
        mode: SIMPLE # initiates HTTPS 

A few changes were made from the Istio guide:

  1. @willian.campos’s suggestion was followed and the fully qualified domain was replaced with aws.local for the “internal host”
  2. The subset definition was removed from the destination rule. Kiali was warning that the kibana virtual service could not access the subset, and there was only one, so it was safe to remove.

At this point I was able to curl http://vpc-xxxxxxxxx..amazonaws.com from the Sleep Pod and achieve the same result as curl https://vpc-xxxxxxxxx..amazonaws.com meaning that the TLS origination was working.

The last thing to do was create another virtual service that would attach to the ingress gateway. Please note that our ingress gateway is performing TLS termination. The virtual service looked like this:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: kibana-proxy
  namespace: logging
spec:
  hosts:
  - "logging.myproduct.com"
  gateways:
  - istio-system/istio-autogenerated-k8s-ingress
  http:
  - route:
    - destination:
        host: aws.local
        port:
          number: 443

And that completed the POC for us. I’m aware that this solution might have it’s own problems, but I hope it helps.

PS: have you tried to use AWS Cognito to provide a public entry point to Kibana. I’m not sure if it fits your use case, but it might make lives easier.

EDIT:
We had the following setting enabled:


Within the elastic search AWS console: Actions -> Modify encryptions
Toggling this could help with debugging.