Como substituir lsof dentro de um Docker (nativo, não baseado em LXC)

16

Estou um pouco confuso que dentro de um contêiner do Docker lsof -inão produz nenhuma saída.

Exemplo (todos os comandos / saída de dentro do contêiner):

[1] root@ec016481cf5f:/# lsof -i
[1] root@ec016481cf5f:/# netstat -tulpn
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:22              0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -

Observe também como nenhum nome de programa ou PID é exibido por netstat. fusertambém fornece resultados um tanto confusos e também não consegue identificar os PIDs.

Alguém pode lançar alguma luz sobre isso?

  • Como posso substituir lsof -i(para ver também o nome do processo !)
  • Por que a produção de netstataleijados também?

NB: As pistas recipiente com "ExecDriver": "native-0.1", que é a camada de execução próprio Docker, não LXC.


[1] root@ec016481cf5f:/# fuser -a4n tcp 22
Cannot stat file /proc/1/fd/0: Permission denied
Cannot stat file /proc/1/fd/1: Permission denied
Cannot stat file /proc/1/fd/2: Permission denied
Cannot stat file /proc/1/fd/3: Permission denied
Cannot stat file /proc/1/fd/255: Permission denied
Cannot stat file /proc/6377/fd/0: Permission denied
Cannot stat file /proc/6377/fd/1: Permission denied
Cannot stat file /proc/6377/fd/2: Permission denied
Cannot stat file /proc/6377/fd/3: Permission denied
Cannot stat file /proc/6377/fd/4: Permission denied
22/tcp:

(Eu não sou obcecado pelo Permission denied, porque esses números. O que me confunde é a lista vazia de PIDs depois 22/tcp.)


# lsof|awk '$1 ~ /^sshd/ && $3 ~ /root/ {print}'
sshd    6377      root  cwd   unknown                        /proc/6377/cwd (readlink: Permission denied)
sshd    6377      root  rtd   unknown                        /proc/6377/root (readlink: Permission denied)
sshd    6377      root  txt   unknown                        /proc/6377/exe (readlink: Permission denied)
sshd    6377      root    0   unknown                        /proc/6377/fd/0 (readlink: Permission denied)
sshd    6377      root    1   unknown                        /proc/6377/fd/1 (readlink: Permission denied)
sshd    6377      root    2   unknown                        /proc/6377/fd/2 (readlink: Permission denied)
sshd    6377      root    3   unknown                        /proc/6377/fd/3 (readlink: Permission denied)
sshd    6377      root    4   unknown                        /proc/6377/fd/4 (readlink: Permission denied)
sshd    6442      root  cwd   unknown                        /proc/6442/cwd (readlink: Permission denied)
sshd    6442      root  rtd   unknown                        /proc/6442/root (readlink: Permission denied)
sshd    6442      root  txt   unknown                        /proc/6442/exe (readlink: Permission denied)
sshd    6442      root    0   unknown                        /proc/6442/fd/0 (readlink: Permission denied)
sshd    6442      root    1   unknown                        /proc/6442/fd/1 (readlink: Permission denied)
sshd    6442      root    2   unknown                        /proc/6442/fd/2 (readlink: Permission denied)
sshd    6442      root    3   unknown                        /proc/6442/fd/3 (readlink: Permission denied)
sshd    6442      root    4   unknown                        /proc/6442/fd/4 (readlink: Permission denied)
sshd    6442      root    5   unknown                        /proc/6442/fd/5 (readlink: Permission denied)

Há mais saída para o usuário conectado, que também é identificado corretamente, mas é isso. Aparentemente, é impossível discernir de que tipo ( lsof -ilimites para soquetes da Internet) é um determinado "objeto".

0xC0000022L
fonte
O que faz um lsofrelatório? O mesmo?
slm
@ SLM: inquérito brilhante! Não o mantém vazio. Em vez disso, mostra um host inteiro de sshdlinhas (também relacionadas), algumas das quais podem ser soquetes TCP, como TYPE unknown. Peculiar. Anexando a saída à minha pergunta.
0xC0000022L
Se você executar strace -s 2000 -o lsof.log lsof -i, provavelmente fornecerá algumas informações adicionais sobre o que está sendo bloqueado.
slm
11
@ SLM: bom ponto. Obrigado por me lembrar. Eu vou fazer isso amanhã, no entanto. Também é bem possível que straceele próprio esteja limitado no contêiner. Emocionantes coisas novas para aprender. Obrigado por devolver a ideia. Deve bater na cama, no entanto.
0xC0000022L
FYI: Isso também quebra o netstat -lp. É definitivamente causado por apparmor.
Alan Robertson

Respostas:

7

(OBSERVAÇÃO: não está claro na pergunta como o solicitante está entrando no contêiner do docker. Suponho que docker exec -it CONTAINER bash foi usado.)

Eu tive esse problema ao usar uma imagem do docker baseada na centos:7versão do docker 1.9.0e, para superar isso, executei:

docker exec --privileged -it CONTAINER bash

Observe a inclusão de --privileged.

Meu entendimento ingênuo do motivo pelo qual isso é necessário: parece que o estivador faz um esforço para que o contêiner seja mais "seguro", conforme documentado aqui .

erik.weathers
fonte
4

Hah, o enredo engrossa. Se alguém tiver uma resposta melhor, escreva-a e eu aceito, se aceitável. Mas aqui a aparente razão. Que negligência minha ignorar os arquivos de log no host :

Jun 12 01:29:46 hostmachine kernel: [140235.718807] audit_printk_skb: 183 callbacks suppressed
Jun 12 01:29:46 hostmachine kernel: [140235.718810] type=1400 audit(1402536586.521:477): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="trace" denied_mask="trace" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.718860] type=1400 audit(1402536586.521:478): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.718886] type=1400 audit(1402536586.521:479): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.718899] type=1400 audit(1402536586.521:480): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.718921] type=1400 audit(1402536586.521:481): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.718954] type=1400 audit(1402536586.521:482): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.719001] type=1400 audit(1402536586.521:483): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.719043] type=1400 audit(1402536586.521:484): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.719086] type=1400 audit(1402536586.521:485): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"
Jun 12 01:29:46 hostmachine kernel: [140235.719126] type=1400 audit(1402536586.521:486): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=3782 comm="lsof" requested_mask="read" denied_mask="read" peer="docker-default"

Portanto, o apparmor parece ser o culpado, embora eu tenha que descobrir como convencê-lo a permitir isso sem comprometer a segurança do host / contêiner ou para ver se isso é possível sem comprometer a segurança.

0xC0000022L
fonte
2
Descrito na edição Docker # 7276
Anthony O.
3

Outra possibilidade, desta vez com uma configuração de segurança mais refinada: conceda o privilégio SYS_PTRACE ao contêiner do docker:

docker run --cap-add=SYS_PTRACE ...
peterh - Restabelecer Monica
fonte
11
Caso alguém esteja se perguntando por que lsofprecisa CAP_SYS_PTRACE: É necessário ler /proc/*/stat. Veja ptrace (2)
David Röthlisberger
2

Eu também encontrei esse problema. O problema foi depois que eu desativada apparmorem docker:

$ sudo aa-complain <docker apparmor profile name, "docker-default" on ubuntu>

URL de referência: https://help.ubuntu.com/community/AppArmor

menghan
fonte
3
Você pode considerar adicionar mais explicações a esta resposta (por exemplo, o que aa-complainfaz ou alguma documentação que suporte esta solução).
precisa saber é o seguinte
@HalosGhost Desculpe, eu não estou muito familiarizado apparmor, eu apenas pesquisei no Google e encontrei uma maneira de desativá-lo. Em outras palavras, não sei por que funciona ou por que não funcionou. Meu sistema operacional é o Ubuntu 14.04, então procurei "ubuntu apparmor" e encontrei help.ubuntu.com/community/AppArmor . Espero que isso seja útil para você.
Menghan
2
Eu não tenho esse problema; minha preocupação era com a qualidade da sua resposta e com o quão útil (e informativo) seria para o OP.
HalosGhost
@HalosGhost Obrigado por sua ajuda, eu reedito minha resposta.
menghan
No ubuntu 14.04, o comando era sudo aa-complain /etc/apparmor.d/docker. Basicamente, desativa a armadura do aplicativo para o processo do docker, o que significa que o docker pode ler qualquer arquivo no sistema. Anteriormente, ele só podia funcionar com arquivos permitidos no perfil. Uma solução melhor pode ser alterar as regras de blindagem do aplicativo que permitiriam o acesso aos arquivos / proc / pid / fd.
Martins Balodis