<p>I have an <em>unsecured</em> <code>Postfix</code> instance in a container that listens to port <code>25</code>. This port is not exposed using a <code>Service</code>. The idea is that only a <code>PHP</code> container that runs inside the same pod should be able to connect to Postfix and there is no need for additional <code>Postfix</code> configuration .</p>

<p>Is there any way for other processes that run in the same network or <code>Kubernetes</code> cluster to connect to this <em>hidden</em> port? </p>

<p>From what I know, only other containers in the same Pod can connect to an unexposed port, via <code>localhost</code>.</p>

<p>I'm interested from a security point of view.</p>

<p><em>P.S. I now that one should make sure it has multiple levels of security in place but I'm interested only theoretically if there is some way to connect to this port from outside the pod.</em></p>

<blockquote>
  <p>From what I know, only other containers in the same Pod can connect to an unexposed port, via <code>localhost</code>.</p>
</blockquote>

<p>Not exactly.
How this is implemented is a detail of the particular container runtime in use.</p>

<blockquote>
  <p><em>...I'm interested only theoretically if there is some way to connect to this port from outside the pod.</em></p>
</blockquote>

<p>So here we go :)</p>

<p>For example on GKE you can easily access Pod from other Pod <strong>if you know Target Pod's IP</strong>.</p>

<p>I have used the following setup on GKE: </p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
  annotations:
    run: fake-web
  name: fake-default-knp
spec:
  containers:
  - image: mendhak/http-https-echo
    imagePullPolicy: IfNotPresent
    name: fake-web
</code></pre>

<p>The Docker file for that image can be found <a href="https://github.com/mendhak/docker-http-https-echo/blob/master/Dockerfile" rel="nofollow noreferrer">here</a>.
It specifies <code>EXPOSE  80  443</code>
So, container listens on these 2 Ports.</p>

<pre><code>$kubectl exec fake-default-knp -- netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 :::443                  :::*                    LISTEN      1/node
tcp        0      0 :::80                   :::*                    LISTEN      1/node
</code></pre>

<p>I have no services:</p>

<pre><code>$kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1     &lt;none&gt;        443/TCP   40d
</code></pre>

<p>and only 2 Pods.</p>

<pre><code>$kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP
busybox-sleep-less               1/1     Running   3476       40d   10.52.1.6
fake-default-knp                 1/1     Running   0          13s   10.52.0.50  
</code></pre>

<p>And I can connect to </p>

<pre><code>$kubectl exec busybox-sleep-less -- telnet 10.52.0.50 80
Connected to 10.52.0.50
$kubectl exec busybox-sleep-less -- telnet 10.52.0.50 443
Connected to 10.52.0.50
</code></pre>

<p>As you can see, container is accessible on <code>POD_IP:container_port</code> from other pod (located on <em>another</em> node)</p>

<p>P.S> It worth checking "Inter-process communications (IPC)" if you <em>really</em> would like to continue using unsecured Postfix and prefer avoiding "unauthorized access from outside of Pod". It is described <a href="https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/" rel="nofollow noreferrer">here</a>.</p>

<p>Hope that helps!</p>

<hr>

<p>Edit 30-Jan-2020</p>

<p>I decided to play with it a little bit. Technically, you can achieve what you want with the help of <code>iptables</code>. You need to specifically ACCEPT all traffic from <code>localhost</code> on port25 and DROP from everywhere else.</p>

<p>something like:</p>

<pre><code>cat iptab.txt 
# Generated by xtables-save v1.8.2 on Thu Jan 30 16:37:27 2020
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -s 127.0.0.1/32 -p 6 -m tcp --dport 80 -j ACCEPT
-A INPUT -p 6 -m tcp --dport 80 -j DROP
COMMIT
</code></pre>

<p>I've tested it and can't telnet on port 80 from anywhere except that very Pod. Please note that I had to run my container in privileged mode in order to be able editing <code>iptables</code> rules directly from Pod. But that is going beyond initial question. :)</p>
