在没有net工具的情况下,哪个PID在k8s pod里面使用PORT?

问题描述 投票:1回答:1

对不起,问题帖很长,但我想对别人学习这个知识是有用的。

我所知道的。

在任何linux系统上 主机 (没有使用docker容器),我可以看 /proc/net/tcp 来提取tcp socket相关信息。

因此,我可以在 LISTEN 州与。

cat /proc/net/tcp | 
 grep " 0A " | 
  sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))/g' | 
   bash

结果:

0.0.0.0:111
10.174.109.1:53
127.0.0.53:53
0.0.0.0:22
127.0.0.1:631
0.0.0.0:8000

/proc/net/tcp 给予 UID, GID不幸的是,没有提供 PID. 但返回的是 inode. 我可以用它来发现 PID 用它作为文件描述符。

所以一种方法是搜索 /proc 寻觅 inode 套接字。虽然很慢,但在主机上能用。

cat /proc/net/tcp |
 grep " 0A " |
  sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).\{72\}\([^ ]*\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))\\\t$(find \/proc\/ -type d -name fd 2>\/dev\/null \| while read f\; do ls -l $f 2>\/dev\/null \| grep -q \6 \&\& echo $f; done)/g' |
   bash

output:

0.0.0.0:111     /proc/1/task/1/fd /proc/1/fd /proc/924/task/924/fd /proc/924/fd
10.174.109.1:53 /proc/23189/task/23189/fd /proc/23189/fd
127.0.0.53:53   /proc/923/task/923/fd /proc/923/fd
0.0.0.0:22      /proc/1194/task/1194/fd /proc/1194/fd
127.0.0.1:631   /proc/13921/task/13921/fd /proc/13921/fd
0.0.0.0:8000    /proc/23122/task/23122/fd /proc/23122/fd

权限提示1: 你只能看到你有权限看的东西。

权限提示2:伪造 root 容器中使用的文件描述符并不能访问到 /proc/*/fd. 你需要对每个用户进行查询。

如果你以普通用户的身份运行,结果是。

0.0.0.0:111
10.174.109.1:53
127.0.0.53:53
0.0.0.0:22
127.0.0.1:631
0.0.0.0:8000    /proc/23122/task/23122/fd /proc/23122/fd

如果以普通用户身份运行,结果是: unshare 隔离环境,它的工作原理和预期一样。

$ unshare -r --fork --pid unshare -r --fork --pid --mount-proc -n bash
# ps -fe
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  2 07:19 pts/6    00:00:00 bash
root       100     1  0 07:19 pts/6    00:00:00 ps -fe
# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
# python -m SimpleHTTPServer &
[1] 152
# Serving HTTP on 0.0.0.0 port 8000 ...
netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      152/python          
# cat /proc/net/tcp |
>  grep " 0A " |
>   sed 's/^[^:]*: \(..\)\(..\)\(..\)\(..\):\(....\).\{72\}\([^ ]*\).*/echo $((0x\4)).$((0x\3)).$((0x\2)).$((0x\1)):$((0x\5))\\\t$(find \/proc\/ -type d -name fd 2>\/dev\/null \| while read f\; do ls -l $f 2>\/dev\/null \| grep -q \6 \&\& echo $f; done)/g' |
>    bash
0.0.0.0:8000    /proc/152/task/152/fd /proc/152/fd
# ls -l /proc/152/fd
total 0
lrwx------ 1 root root 64 mai 25 07:20 0 -> /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 1 -> /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 2 -> /dev/pts/6
lrwx------ 1 root root 64 mai 25 07:20 3 -> 'socket:[52409024]'
lr-x------ 1 root root 64 mai 25 07:20 7 -> /dev/urandom
# cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:1F40 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 52409024 1 0000000000000000 100 0 0 10 0 

在我的主机上的docker容器里,它似乎也以同样的方式工作。

问题是这样的。

我在一个运行jitsi的kubernetes pod里有一个容器。在这个容器内,我无法获得监听端口的服务的PID。

安装了netstat之后,也无法获得服务的PID。

root@jitsi-586cb55594-kfz6m:/# netstat -ntpl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:5222            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5269            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5280            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5347            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::5222                 :::*                    LISTEN      -                   
tcp6       0      0 :::5269                 :::*                    LISTEN      -                   
tcp6       0      0 :::5280                 :::*                    LISTEN      -                   
# ps -fe
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 May22 ?        00:00:00 s6-svscan -t0 /var/run/s6/services
root        32     1  0 May22 ?        00:00:00 s6-supervise s6-fdholderd
root       199     1  0 May22 ?        00:00:00 s6-supervise jicofo
jicofo     203   199  0 May22 ?        00:04:17 java -Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/ -Dnet.java.sip.communicator.SC_HOME_DIR_NAME=config -Djava
root      5990     0  0 09:48 pts/2    00:00:00 bash
root     10926  5990  0 09:57 pts/2    00:00:00 ps -fe

最后的问题是:

a) 为什么我无法读取监听端口5222的proccess的文件描述符?

root@jitsi-586cb55594-kfz6m:/# cat /proc/net/tcp | grep " 0A "
    0: 00000000:1466 00000000:0000 0A 00000000:00000000 00:00000000 00000000   101        0 244887827 1 ffff9bd749145800 100 0 0 10 0                 
...
root@jitsi-586cb55594-kfz6m:/# echo $(( 0x1466 ))
5222
root@jitsi-586cb55594-kfz6m:/# ls -l  /proc/*/fd/* 2>/dev/null | grep 244887827                                                     
root@jitsi-586cb55594-kfz6m:/# echo $?
1
root@jitsi-586cb55594-kfz6m:/# su - svc
svc@jitsi-586cb55594-kfz6m:~$ id -u
101
svc@jitsi-586cb55594-kfz6m:~$ ls -l /proc/*/fd/* 2>/dev/null | grep 244887827
svc@jitsi-586cb55594-kfz6m:~$ echo $?
1

b) 还有一种方法可以列出 inode 并将其连接到 pid 不经意间 /proc/*/fd ?

更新1。

根据 Anton Kostenko 提示,我找了AppArmor。不是这样的,因为服务器不用AppArmor,但是搜索,让我找到了SELinux。

在运行AppArmor的ubuntu机器中,我得到了。

$ sudo apparmor_status  | grep dock                                                                              
   docker-default

在OKE(Oracle Kubernetes Engine,我的案例)节点中,没有AppArmor。我得到的是SELinux。

$ man selinuxenabled | grep EXIT -A1
EXIT STATUS
       It exits with status 0 if SELinux is enabled and 1 if it is not enabled.
$ selinuxenabled && echo $?
0

现在,我相信 SELinux 挡住了 /proc/*/fd 容器内的根目录。但我还不知道如何解锁。

参考文献。

https:/jvns.cablog20161010what-even-is-a-container。

linux docker kubernetes pid inode
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.