<p>Nignx ingress <a href="https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/" rel="nofollow noreferrer">provides</a> a way to expose tcp or udp service: all you need is public <a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html" rel="nofollow noreferrer">NLB</a>.</p>
<p>However this way tcp service will be exposed publicly: NLB does not support security groups or acl, also nginx-ingress does not have any way to filter traffic while proxying tcp or udp.</p>
<p>The only solution that comes to my mind is internal load balancer and separate non-k8s instance with haproxy or iptables, where I'll actually have restrictions based on source ip - and then forward/proxy requests to internal NLB.</p>
<p>Maybe there are another ways to solve this?</p>

Ilia Kondrashov
<ul>
<li><p>Do not use nginx-ingress for this. To get real IP inside nginx-ingress you have to set <code>controller.service.externalTrafficPolicy: Local</code>, which in its turn changes the way the nginx-ingress service is exposed - making it local to the nodes. See <a href="https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip" rel="nofollow noreferrer">https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip</a>. This in its turn causes your nginx-ingress LoadBalancer to have unhealthy hosts which will create noise in your monitoring (opposite to NodePort where every node exposes the same port and healthy). Unless you run nginx-ingress as a DaemonSet or use other hacks, e.g. limit which nodes are added as a backends (mind scheduling, scaling), or move nginx-ingress to a separate set of nodes/subnet - IMO each of these is a lot of headache for such a simple problem. More on this problem: <a href="https://elsesiy.com/blog/kubernetes-client-source-ip-dilemma" rel="nofollow noreferrer">https://elsesiy.com/blog/kubernetes-client-source-ip-dilemma</a></p>
</li>
<li><p>Use plain Service <code>type: LoadBalancer</code> (classic ELB) which supports:</p>
<ul>
<li>Source ranges: <a href="https://aws.amazon.com/premiumsupport/knowledge-center/eks-cidr-ip-address-loadbalancer/" rel="nofollow noreferrer">https://aws.amazon.com/premiumsupport/knowledge-center/eks-cidr-ip-address-loadbalancer/</a></li>
<li><code>service.beta.kubernetes.io/aws-load-balancer-extra-security-groups</code> annotation in case you want to manage the source ranges from the outside.</li>
</ul>
<p>In this case your traffic going like <code>World -&gt; ELB -&gt; NodePort -&gt; Service -&gt; Pod</code>, without Ingress.</p>
</li>
</ul>
