<p>I have use case where we want to route certain requests via a corporate HTTP proxy. Based on <a href="https://istio.io/latest/docs/tasks/traffic-management/egress/http-proxy/#configure-traffic-to-external-https-proxy" rel="nofollow noreferrer">this</a> guide I was able to configure the external access successfully. For context I've added a example ServiceEntry:</p>
<pre><code>
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: proxy
spec:
  addresses:
    - 10.1.1.1
    - 10.1.1.2
  exportTo:
  - .
  hosts:
  - foo.proxy # this is technically ignored when protocol is TCP
  location: MESH_EXTERNAL
  ports:
  - name: tcp
    number: 3128
    protocol: TCP

</code></pre>
<p>This works when we have the app automatically resolve to one of the proxy addresses above (i.e: host file entry).</p>
<p>In an effort to provide automatic DNS resolution I setup a a k8s <a href="https://kubernetes.io/docs/concepts/services-networking/service/#services-without-selectors" rel="nofollow noreferrer">Service without selectors</a> as per the docs. In a <strong>non istio</strong> namespace, this allows me to resolve <code>foo.proxy.default.cluster.local</code> without the host file entries as expected e.g:</p>
<pre><code>curl -v --proxy foo.default.svc.cluster.local:3128 https://blah.com
</code></pre>
<p>However within a istio namespace with the existing ServiceEntry (above) it fails with a <code>404 Not Found</code>. The logs show:</p>
<pre><code>2021-08-11T08:56:47.088919Z debug   envoy router    [C1114][S1115555414526221653] no cluster match for URL ''
2021-08-11T08:56:47.088928Z debug   envoy http  [C1114][S1115555414526221653] Sending local reply with details route_not_found
</code></pre>
<p>Can I get some pointers on where this might be going wrong?</p>

kaizenCoder
<p>After some trial and error the solution to make this work is as following:</p>
<ol>
<li>K8s Service must have a named port</li>
</ol>
<p>For example, I had:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: foo
spec:
  ports:
    - protocol: TCP
      port: 8080      
</code></pre>
<p>But it must include the <code>spec.ports.[].name</code>:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: foo
spec:
  ports:
    - protocol: TCP
      name: tcp # critial. alternatively prefix any name with protocol-&lt;name&gt;
      port: 8080      
</code></pre>
<p>This is documented at:
<a href="https://istio.io/v1.9/docs/ops/configuration/traffic-management/protocol-selection/" rel="nofollow noreferrer">https://istio.io/v1.9/docs/ops/configuration/traffic-management/protocol-selection/</a></p>
<p>For completeness here's the k8s Endpoints example:</p>
<pre><code>apiVersion: v1
kind: Endpoints
metadata:
  name: foo
subsets:
  - addresses:
      - ip: 10.1.1.1
      - ip: 10.1.1.2
    ports:
      - port: 8080
</code></pre>
<p>The Endpoints <code>metadata.name</code> and Service <code>metadata.name</code> MUST match.</p>
<p>Now to the more interesting part.</p>
<ol>
<li>Create a Service Entry for the VIP.</li>
</ol>
<p>I replaced my original ServiceEntry with the following:</p>
<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: foo-forward-proxy
spec:
  hosts:
  - foo.default.svc.cluster.local
  addresses:
  - 172.20.254.32 # my foo service ClusterIP
  location: MESH_EXTERNAL
  ports:
  - number: 8080
    name: tcp
    protocol: TCP
  resolution: STATIC
  endpoints:
  - address: 10.1.1.1
  - address: 10.1.1.2
</code></pre>
<p>This declares the k8s Service IP <code>172.20.254.32</code> as a VIP with the name <code>foo.default.svc.cluster.local</code> which happens to be the Service name. All traffic destined to the VIP on port 8080 will be forwarded to the endpoints.</p>
