RootDirectory=를 사용하여 systemd 서비스를 실행하고 /bin 바이너리에 액세스합니다.

RootDirectory=를 사용하여 systemd 서비스를 실행하고 /bin 바이너리에 액세스합니다.

일부 시스템 도우미를 활용하려고합니다.chroot(2)이 프로세스는 호스팅 웹 서버 아래에 RootDirectory=있는 기본 Python 스크립트입니다 . /srv/http셔뱅이 있어#!/usr/bin/python (다른 조합도 시도해 봤습니다)

서비스 파일도 매우 간단합니다.

[Unit]
Wants=network-online.target
After=network-online.target

AssertPathExists=/srv/http

[Service]
Type=simple
Restart=always
RestartSec=10

RootDirectory=/srv/http
PrivateTmp=true

ExecStart=/server.py
PIDFile=/run/miniweb.pid

[Install]
WantedBy=multi-user.target

로그에는 실행 파일을 찾을 수 없다고 명확하게 표시됩니다.

Mar 11 19:23:49 bigrigv2 systemd[13213]: testweb.service: Failed to execute /server.py: No such file or directory
Mar 11 19:23:49 bigrigv2 systemd[13213]: testweb.service: Failed at step EXEC spawning /server.py: No such file or directory

실행 가능으로 표시됩니다.

-rwxr-xr-x 1 anton anton  650 Mar 11 19:06 server.py

나는 또한 ExecStart=/bin/python /srv/http/server.py다른 변형을 시도했다. RootDirectorychroot 서비스 스크립트에서 Python 또는 기타 바이너리를 올바르게 실행하는 방법과 개념을 이해하고 있는지 잘 모르겠습니다 . 내 가정은 서비스를 실행하기 전에 chroot:s를 입력한 /srv/http후 이 경우 서비스를 종료하고 Python을 실행할 수 없다는 것입니다. 이것은 의미가 있지만 왜 /server.py찾을 수 없는지 잘 모르겠습니다 . 다른 바이너리에 의존하는 작업을 어떻게 수행하시겠습니까? 대부분의 솔루션에서는 언어(예: C)를 활용 chroot하고 이를 애플리케이션에서 제어하는 ​​방법을 언급하지만 매우 제한된 bash 스크립트 또는 독립 실행형 바이너리 이외의 다른 것에 대해 서비스 스크립트에 chroot를 제공하는 요점이 보이지 않습니다.

아마도 매우 간단한 질문일 것입니다. 하지만 저는 매우 당황스럽습니다. 어떤 도움이라도 대단히 감사하겠습니다!

답변1

질문에 직접 답변하려면:

RootDirectory를 사용하여 chroot 외부의 외부 종속성이 있는 서비스를 올바르게 실행하는 방법.

당신은 할 수 없습니다. chroot 감옥에 무언가가 있으면 바이너리와 라이브러리를 포함한 외부의 어떤 것도 액세스할 수 없습니다. 하지만 여전히 시스템을 보호할 수 있는 방법이 있습니다.

~에서man systemd.exec

Service Manager가 실행 중인 시스템의 루트인 호스트 루트를 기준으로 하는 디렉터리 경로를 선택합니다. 실행되는 프로세스의 루트 디렉토리를 설정하려면 chroot(2) 시스템 호출을 사용하십시오. 이것을 사용하면,chroot() 감옥에서 프로세스 바이너리와 모든 보조 파일을 사용할 수 있는지 확인해야 합니다..

이것을 설정하면 호출 RootDirectory=/srv/http/server.py실행을 시도 /usr/bin/python하지만 경로를 찾을 수 없기 때문에 실패합니다. 이와 같은 작업을 수행할 수 있더라도 그렇게 하려고 할 때 또는 이러한 라이브러리가 chroot에 설치되어 있지 않기 때문에 ExecStartPre=/bin/cp /usr/bin/python /src/http/usr/bin/python여전히 문제가 발생할 수 있습니다 . 나는 좋은 설정 없이 당신과 같은 설정으로 테스트를 했는데 당신과 같은 오류가 발생했습니다.import flaskimport pyramid

여기에는 세 가지 옵션이 있습니다.

  1. chroot에 필요한 모든 것을 제공하십시오. Debian 기반 시스템을 사용하는 경우debootstrap설정 deboostrap buster /srv/http하고 작동하는 좋은 도구입니다. 기본 시스템을 설치한 다음 sudo chroot && apt install python python-flask원하는 것을 설치할 수 있습니다.

  2. 서비스를 루트로 전환하는 대신 기본 제공 옵션을 사용하여 서비스를 샌드박싱하세요. 구체적으로:

  • RemoveIPC=true그리고 PrivateTmp=true. 이를 통해 실행 프로세스에서 생성된 IPC 개체 및 임시 파일의 수명 주기가 서비스 런타임에 연결됩니다. /tmp및는 일반적으로 시스템에서 누구나 쓸 수 있는 유일한 디렉토리이기 때문에 /var/tmp장치가 종료된 후에 파일이 남지 않도록 보장합니다.
  • NoNewPrivileges=true그리고 RestrictSUIDSGID=true. 이를 통해 호출 프로세스는 SUID/SGID 파일이나 디렉터리를 활용하거나 생성할 수 없습니다.
  • ProtectSystem=strict서비스가 파일 시스템의 어디에도 쓸 수 없도록 비활성화 합니다 ProtectHome=read-only(예외는 /dev/ /proc/및 입니다 /sys/. 서비스가 특정 디렉터리에 쓸 수 있도록 허용하려면 를 사용해야 합니다 ReadWritePaths=.
  • RuntimeDirectory=서비스에는 서비스 사용자가 소유한 런타임 디렉터리가 할당되며 시스템이 종료되면 자동으로 삭제됩니다.
  1. 2단계에서 제가 말한 모든 내용을 한 줄로 바꿀 수 있습니다.DynamicUser=true. 좋은 시간 보내세요개발자 설명은 여기

어쨌든, 당신이 그것을 사용하지 않는다면 User=, 아니면 DynamicUser=사용해야 합니다. 이렇게 하면 서비스가 root다른 비밀에 대한 읽기 액세스 권한을 갖지 못하게 됩니다 ./etc/shadow

나는 옵션 3을 정말 좋아한다. 이를 활성화하면 서비스로부터 시스템이 보호됩니다.

관련 정보