Is there any way to connect to an unpublished socket in a Kubernetes pod from outside?

1/28/2020

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

Is there any way for other processes that run in the same network or Kubernetes cluster to connect to this hidden port?

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

I'm interested from a security point of view.

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.

-- Popi
kubernetes
kubernetes-pod
security

2 Answers

1/28/2020

Yes, you can use kubectl port-forward to set up a tunnel directly to it for testing purposes.

-- coderanger
Source: StackOverflow

1/29/2020

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

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

...I'm interested only theoretically if there is some way to connect to this port from outside the pod.

So here we go :)

For example on GKE you can easily access Pod from other Pod if you know Target Pod's IP.

I have used the following setup on GKE:

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

The Docker file for that image can be found here. It specifies EXPOSE 80 443 So, container listens on these 2 Ports.

$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

I have no services:

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

and only 2 Pods.

$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  

And I can connect to

$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

As you can see, container is accessible on POD_IP:container_port from other pod (located on another node)

P.S> It worth checking "Inter-process communications (IPC)" if you really would like to continue using unsecured Postfix and prefer avoiding "unauthorized access from outside of Pod". It is described here.

Hope that helps!


Edit 30-Jan-2020

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

something like:

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

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 iptables rules directly from Pod. But that is going beyond initial question. :)

-- Nick
Source: StackOverflow