메뉴 닫기

systemd-analyze security로 서비스 보안 점수 개선하기

리눅스 서버에서는 대부분의 백그라운드 프로그램을 systemd 서비스로 실행합니다. 하지만 서비스를 정상적으로 실행하는 것에만 집중하다 보면, 필요 이상의 권한을 부여하거나 시스템 전체에 접근할 수 있도록 설정하는 경우가 많습니다.

systemd에는 별도의 보안 프로그램을 설치하지 않고도 서비스의 격리 수준을 분석할 수 있는 systemd-analyze security 명령이 있습니다.

이번 글에서는 간단한 Python 웹 서비스를 만든 후 보안 노출도를 측정하고, systemd 하드닝 옵션을 적용해 점수를 개선해 보겠습니다.


테스트 환경

이번 테스트는 다음 환경에서 진행했습니다.


참고 — 배포판과 systemd 버전에 따라 지원하는 보안 옵션 및 결과 점수는 달라질 수 있습니다.

systemd 보안 점수란?

systemd-analyze security는 서비스의 다음 항목들을 검사합니다.

  • root 권한으로 실행하는지
  • 추가 권한 획득을 차단했는지
  • 시스템 파일에 쓰기가 가능한지
  • 사용자 홈 디렉터리에 접근할 수 있는지
  • 장치 파일과 커널 설정에 접근할 수 있는지
  • Linux Capability가 제한돼 있는지
  • 사용할 수 있는 시스템 호출과 네트워크 주소 체계가 제한돼 있는지

검사 결과는 0.0부터 10.0까지의 노출도인 Exposure Level로 표시됩니다.

0.0  ← 격리 설정이 강함
10.0 ← 격리 설정이 거의 없음
핵심 포인트 — 일반적인 보안 점수와 반대로 숫자가 낮을수록 격리 수준이 높습니다.

systemd는 각 검사 항목에 위험도와 가중치를 적용하고 전체 결과를 0.0~10.0으로 정규화합니다. 자세한 계산 방식은 systemd-analyze 매뉴얼에서 확인할 수 있습니다.


1. 테스트용 웹 페이지 생성

먼저 웹 서버가 제공할 디렉터리와 HTML 파일을 생성합니다.

sudo mkdir -p /srv/security-demo
echo '<h1>systemd security hardening test</h1>' \
  | sudo tee /srv/security-demo/index.html

생성된 파일을 확인합니다.

cat /srv/security-demo/index.html

결과는 다음과 같습니다.



2. 테스트용 systemd 서비스 생성

다음 명령으로 서비스 파일을 생성합니다.

sudo nano /etc/systemd/system/security-demo.service

아래 내용을 입력합니다.

[Unit]
Description=systemd Security Demo Web Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 -m http.server 8080 --bind 127.0.0.1 --directory /srv/security-demo
Restart=on-failure

[Install]
WantedBy=multi-user.target

systemd 설정을 다시 불러오고 서비스를 실행합니다.

sudo systemctl daemon-reload
sudo systemctl enable --now security-demo.service

서비스 상태를 확인합니다.

systemctl status security-demo.service --no-pager

 

웹 서버가 정상적으로 동작하는지도 확인합니다.

curl http://127.0.0.1:8080

다음과 같이 작성한 HTML이 출력되면 정상입니다.

<h1>systemd security hardening test</h1>

3. 적용 전 보안 노출도 측정

현재 서비스의 보안 설정을 분석합니다.

systemd-analyze security --no-pager security-demo.service

주요 결과는 다음과 같습니다.

✗ User=/DynamicUser=
  Service runs as root user

✗ NoNewPrivileges=
  Service processes may acquire new privileges

✗ PrivateDevices=
  Service potentially has access to hardware devices

✗ ProtectSystem=
  Service has full access to the OS file hierarchy

✗ ProtectHome=
  Service has full access to home directories

✗ ProtectKernelTunables=
  Service may alter kernel tunables

✗ PrivateTmp=
  Service has access to other software's temporary files

→ Overall exposure level for security-demo.service: 9.6 UNSAFE

적용 전 결과: 9.6 UNSAFE

별도로 실행 사용자를 지정하지 않아 서비스가 root 권한으로 실행됩니다. 파일 시스템, 홈 디렉터리, 장치, 커널 설정 및 시스템 호출 등에 대한 제한도 거의 없는 상태입니다.


4. systemd 하드닝 설정 적용

기존 서비스 파일을 직접 수정하는 대신 drop-in 방식으로 보안 설정을 추가하겠습니다.

왜 drop-in을 사용할까?
원본 서비스 파일과 하드닝 설정을 분리할 수 있어 변경 내역을 확인하거나 설정을 되돌리기 쉽습니다.
sudo systemctl edit security-demo.service

편집기가 열리면 다음 내용을 입력합니다.

[Service]
DynamicUser=yes
NoNewPrivileges=yes

PrivateTmp=yes
PrivateDevices=yes

ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes

RestrictSUIDSGID=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_INET AF_INET

LockPersonality=yes
MemoryDenyWriteExecute=yes
RemoveIPC=yes

SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM

CapabilityBoundingSet=
AmbientCapabilities=

UMask=0077

저장하면 다음 경로에 설정이 생성됩니다.

/etc/systemd/system/security-demo.service.d/override.conf

주요 옵션 설명

설정 역할
DynamicUser=yes 서비스 실행 시 임시 비-root 계정을 생성
NoNewPrivileges=yes 서비스 프로세스의 추가 권한 획득 차단
PrivateTmp=yes 서비스 전용 /tmp, /var/tmp 제공
PrivateDevices=yes 물리 장치와 주요 장치 파일 접근 제한
ProtectSystem=strict 운영체제 파일 시스템을 읽기 전용으로 제공
ProtectHome=yes /home, /root, /run/user 접근 차단
ProtectKernelTunables=yes 커널 설정 변경 차단
ProtectKernelModules=yes 커널 모듈 접근 및 로드 차단
ProtectKernelLogs=yes 커널 로그 접근 차단
ProtectControlGroups=yes cgroup 설정 변경 차단
RestrictNamespaces=yes 새로운 네임스페이스 생성 차단
RestrictAddressFamilies= 사용할 수 있는 소켓 주소 체계 제한
SystemCallFilter= 서비스에서 사용할 수 있는 시스템 호출 제한
CapabilityBoundingSet= 모든 Linux Capability 제거
UMask=0077 생성한 파일을 기본적으로 서비스 사용자만 접근 가능하도록 설정

각 옵션의 자세한 설명은 systemd.exec 공식 문서에서 확인할 수 있습니다.


5. 서비스 재시작 및 정상 작동 확인

변경된 설정을 불러오고 서비스를 재시작합니다.

sudo systemctl daemon-reload
sudo systemctl restart security-demo.service

서비스 상태를 확인합니다.

systemctl status security-demo.service --no-pager

웹 서버가 여전히 정상적으로 동작하는지도 확인합니다.

curl http://127.0.0.1:8080

다음 결과가 출력되면 보안 설정을 적용한 후에도 서비스 기능이 정상적으로 유지되는 것입니다.

<h1>systemd security hardening test</h1>

 

서비스가 실행되지 않는다면 다음 명령으로 로그를 확인합니다.

sudo journalctl -u security-demo.service -n 50 --no-pager

설정 파일 자체는 다음 명령으로 검사할 수 있습니다.

sudo systemd-analyze verify \
  /etc/systemd/system/security-demo.service

6. 적용 후 보안 노출도 재측정

동일한 명령을 다시 실행합니다.

systemd-analyze security --no-pager security-demo.service

하드닝 설정이 적용된 항목에는 체크 표시가 나타납니다.

✓ User=/DynamicUser=
  Service runs under a transient non-root user identity

✓ NoNewPrivileges=
  Service processes cannot acquire new privileges

✓ ProtectSystem=
  Service has strict read-only access to the OS file hierarchy

✓ ProtectHome=
  Service has no access to home directories

✓ PrivateTmp=
  Service has no access to other software's temporary files

✓ ProtectKernelModules=
  Service cannot load kernel modules

✓ CapabilityBoundingSet=~CAP_SYS_ADMIN
  Service has no administrator privileges

→ Overall exposure level for security-demo.service: 1.6 OK

적용 후 결과: 1.6 OK

서비스 기능은 그대로 유지하면서 root 실행, 파일 시스템 쓰기, 장치 및 커널 접근 등 불필요한 권한을 제한했습니다.


적용 전후 비교

구분 Exposure Level 평가
하드닝 적용 전 9.6 UNSAFE
하드닝 적용 후 1.6 OK
개선 결과 8.0 감소 격리 수준 향상

기존 서비스의 기능은 유지하면서 노출도를 9.6에서 1.6까지 낮췄습니다.


왜 0.0까지 낮추지 않았을까?

이 서비스는 HTTP 요청을 처리해야 하므로 호스트 네트워크에 접근할 수 있어야 합니다.

PrivateNetwork=yes를 적용하면 서비스가 별도의 네트워크 네임스페이스로 격리됩니다. 이 경우 호스트에서 127.0.0.1:8080으로 웹 서버에 접근할 수 없게 됩니다.

따라서  PrivateNetwork를 적용하지 않고 다음 설정으로 사용할 수 있는 소켓의 종류만 제한했습니다.

RestrictAddressFamilies=AF_INET AF_INET6

주의사항

systemd-analyze security 결과는 취약점 진단 점수나 CVSS 점수가 아닙니다.

이 명령은 다음 항목을 직접 검사하지 않습니다.

  • 프로그램 소스 코드의 보안 취약점
  • 설치된 패키지의 알려진 취약점
  • 계정과 비밀번호 정책
  • 방화벽 설정
  • AppArmor 또는 SELinux 정책
  • TLS 인증서와 암호화 설정
  • 애플리케이션 자체의 인증 및 접근통제

점수 해석 시 주의

1.6 OK가 나오더라도 서비스가 완전히 안전하다는 의미는 아닙니다. 반대로 SSH처럼 root 권한과 네트워크 접근이 필요한 서비스는 점수가 높더라도 실제 취약점이 존재한다는 뜻은 아닙니다. 이 점수는 동일한 서비스에서 설정 적용 전후의 격리 수준을 비교하는 용도로 활용하는 것이 적절합니다.


마무리

systemd는 단순히 서비스를 실행하고 관리하는 도구가 아니라 서비스별 권한과 시스템 접근 범위를 제한할 수 있는 다양한 보안 기능을 제공합니다.

※ 진행과정 정리

  1. 테스트용 웹 서비스 생성
  2. systemd-analyze security를 이용한 노출도 측정
  3. root 실행 및 과도한 시스템 접근 항목 확인
  4. systemd drop-in 설정으로 하드닝 적용
  5. 서비스 정상 작동 확인
  6. 노출도 9.6 UNSAFE에서 1.6 OK로 개선

참고 자료

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다