Jak mogę zastąpić lsof wewnątrz Dockera (natywny, nie oparty na LXC)

16

Jestem nieco zaskoczony, że wewnątrz kontenera Docker lsof -inie daje żadnych wyników.

Przykład (wszystkie polecenia / dane wyjściowe z kontenera):

[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      -

Zwróć także uwagę, jak nie wyświetla się żaden PID ani nazwa programu netstat. fuserdaje również nieco mylące dane wyjściowe i nie jest również w stanie wskazać PID.

Czy ktoś może rzucić jakieś światło na ten temat?

  • Jak mogę podstawić lsof -i(aby zobaczyć również nazwę procesu !)
  • Dlaczego produkcja jest również netstatkaleką?

NB: Kontener działa z "ExecDriver": "native-0.1", czyli własną warstwą wykonawczą Dockera, a nie 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:

(Nie mam obsesji na punkcie tego Permission denied, ponieważ te liczby. To, co mnie dezorientuje, to pusta lista PID po 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)

Podłączony użytkownik ma jeszcze więcej danych wyjściowych, które również są poprawnie zidentyfikowane, ale to wszystko. Najwyraźniej nie można rozpoznać, jakiego typu ( lsof -iograniczenia gniazd internetowych) jest pewien „obiekt”.

0xC0000022L
źródło
Co robi lsofraport? To samo?
slm
@slm: genialne zapytanie! Nie utrzymuje go pustego. Zamiast tego pokazuje cały szereg (również sshdpowiązanych) linii, z których niektóre mogą być gniazdami TCP, jak TYPE unknown. Szczególny. Dołączanie wyniku do mojego pytania.
0xC0000022L
Jeśli uruchomisz strace -s 2000 -o lsof.log lsof -i, prawdopodobnie dostarczysz dodatkowych informacji o tym, co jest blokowane.
slm
1
@slm: dobra uwaga. Dzięki za przypomnienie. Zrobię to jednak jutro. Możliwe też, że stracesam jest ograniczony w pojemniku. Ekscytujące nowe rzeczy do nauki. Dzięki za odrzucony pomysł. Ale musi trafić w łóżko.
0xC0000022L
FYI: To także łamie netstat -lp. Jest to z pewnością spowodowane przez apparmor.
Alan Robertson

Odpowiedzi:

7

(UWAGA: nie jest jasne, w jaki sposób pytający wchodzi do kontenera dokowanego. Zakładam, że docker exec -it CONTAINER bash został użyty).

Miałem ten problem, gdy korzystałem z obrazu dokera opartego na centos:7wersji dokera 1.9.0i aby go rozwiązać, po prostu uruchomiłem:

docker exec --privileged -it CONTAINER bash

Zwróć uwagę na włączenie --privileged.

Moje naiwne zrozumienie powodu, dla którego jest to wymagane: wydaje się, że doker stara się, aby kontener był bardziej „bezpieczny”, jak tu udokumentowano .

erik.weathers
źródło
4

Hah, fabuła gęstnieje. Jeśli ktoś ma lepszą odpowiedź, proszę ją napisać, a ja ją zaakceptuję, jeśli będzie to możliwe. Ale tutaj oczywisty powód. Jak zaniedbanie mojego zignorowania plików dziennika na hoście :

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"

Sprawca wydaje się więc winowajcą, chociaż muszę wymyślić, jak go przekonać, aby na to pozwolić, bez narażania bezpieczeństwa hosta / kontenera, lub sprawdzania, czy jest to w ogóle możliwe bez narażania bezpieczeństwa.

0xC0000022L
źródło
2
Opisane w numerze Docker # 7276
Anthony O.
3

Inna możliwość, tym razem z bardziej szczegółowymi ustawieniami zabezpieczeń: nadaj SYS_PTRACE uprawnienie kontenerowi dokowanemu:

docker run --cap-add=SYS_PTRACE ...
peterh - Przywróć Monikę
źródło
1
W przypadku, gdy ktoś zastanawia się, dlaczego lsofpotrzebuje CAP_SYS_PTRACE: należy przeczytać /proc/*/stat. Zobacz ptrace (2)
David Röthlisberger
2

Znalazłem też ten problem. Problem upadł po tym wyłączona apparmorna docker:

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

referencyjny adres URL: https://help.ubuntu.com/community/AppArmor

menghan
źródło
3
Możesz rozważyć dodanie więcej wyjaśnień do tej odpowiedzi (np. Co to aa-complainjest lub trochę dokumentacji, która obsługuje to rozwiązanie).
HalosGhost
@HalosGhost Niestety, nie jestem do końca zaznajomiony apparmor, po prostu google go i znalazłem sposób, aby go wyłączyć. Innymi słowy, nie wiem, dlaczego to działa lub dlaczego nie działa. Moim hostem jest Ubuntu 14.04, więc szukałem „ubuntu apparmor” i znalazłem help.ubuntu.com/community/AppArmor . Mam nadzieję, że to ci pomoże.
menghan
2
Nie mam tego problemu; martwiłem się o jakość twojej odpowiedzi oraz o to, jak pomocny (i informacyjny) byłby dla PO.
HalosGhost
@HalosGhost Dzięki za pomoc, ponownie przeanalizowałem swoją odpowiedź.
menghan
W Ubuntu 14.04 polecenie było sudo aa-complain /etc/apparmor.d/docker. Zasadniczo wyłącza zbroję aplikacji dla procesu dokera, co oznacza, że ​​doktor może odczytać dowolny plik w systemie. Wcześniej mogło działać tylko z plikami dozwolonymi w profilu. Lepszym rozwiązaniem może być zmiana reguł pancerza aplikacji, które zezwalają na dostęp do plików / proc / pid / fd.
Martins Balodis