
eBPF 기반의 Linux 시스템 잠금 및 감사 보안 도구입니다. 커널 기능을 제한하고, 파일리스 실행을 차단하며, 메모리를 보호하고, 선언적 프로필을 통해 컨테이너와 IoT 디바이스를 강화합니다.

bpflock - Linux 머신을 잠그고 감사하기 위한 eBPF 기반 보안.
참고: bpflock은 현재 실험 단계에 있으며, 동작이 중단되거나 옵션과 보안 의미가 변경될 수 있으며, 일부 BPF 프로그램은 Cilium ebpf 라이브러리를 사용하도록 업데이트될 예정입니다.
bpflock은 eBPF를 사용하여 Linux 보안을 강화합니다. 다양한 Linux 기능에 대한 접근을 제한함으로써, bpflock은 공격 표면을 줄이고 잘 알려진 공격 기술을 차단할 수 있습니다.
호스트 pid 및 네트워크 네임스페이스에서 실행되는 컨테이너 관리자, systemd 및 기타 컨테이너/프로그램과 같은 프로그램만 전체 Linux 기능에 접근할 수 있으며, 자체 네임스페이스에서 실행되는 컨테이너 및 애플리케이션은 제한됩니다.
bpflock bpf 프로그램이 restricted 프로필에서 실행되는 경우, 권한 있는 프로그램/컨테이너를 포함한 모든 프로그램/컨테이너의 접근이 거부됩니다.
bpflock은 Linux Security Modules + BPF를 포함한 여러 보안 기능을 활용하여 Linux 머신을 보호합니다.
아키텍처 및 보안 설계 참고 사항:
bpflock은 다음과 같이 분류할 수 있는 여러 보안 보호 기능을 제공합니다:
파일시스템 보호
네트워크 보호
bpflock은 보안 의미론을 간단하게 유지합니다. 보안 스펙트럼을 광범위하게 포괄하고 특정 Linux 기능에 대한 접근을 제한하기 위해 세 가지 전역 프로필을 지원합니다.
profile: bpf 프로그램별로 적용할 수 있는 전역 프로필이며, 다음 중 하나를 취합니다:
allow|none|privileged : 동일하며, 가장 덜 안전한 프로필을 정의합니다. 이 프로필에서는 모든 프로세스에 대해 접근이 기록되고 허용됩니다. 보안 이벤트를 기록하는 데 유용합니다.baseline : 제한적인 프로필로, 호스트 네임스페이스에서 실행되는 권한 있는 애플리케이션 및 컨테이너, 또는 bpflock_cgroupmap bpf 맵의 cgroup별 허용 프로필을 제외한 모든 프로세스에 대해 접근이 거부됩니다.restricted : 모든 프로세스에 대해 접근이 거부되는 강력하게 제한된 프로필입니다.허용 또는 차단 작업/명령:
allow|privileged 또는 baseline 프로필에서 허용 또는 차단할 명령 목록을 지정하고 적용할 수 있습니다.
--protection-allow : 허용되는 작업의 쉼표로 구분된 목록입니다. baseline 프로필에서 유효하며, 매우 특정하고 권한 있는 작업을 수행하는 애플리케이션에 유용합니다. allow | privileged 프로필의 사용을 줄일 수 있습니다. 즉, privileged 프로필을 사용하는 대신 프로필을 지정하고 허용된 명령 집합을 추가하여 해당 애플리케이션에 대한 사례별 정의를 제공할 수 있습니다.bpf 보안 예제는 bpflock 구성 예제를 확인하세요.
bpflock에는 다음이 필요합니다:
Linux 커널 버전 >= 5.13이며, 다음 구성이 필요합니다:
CONFIG_BPF_SYSCALL=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_KPROBES=y
CONFIG_LSM="...,bpf"
CONFIG_BPF_LSM=y
당연히 BTF가 활성화된 커널이 필요합니다.
커널이 CONFIG_BPF_LSM=y로 컴파일된 경우 /boot/config-*를 확인하여 확인하세요. 그러나 bpflock을 실행할 때 다음과 같이 실패하면:
must have a kernel with 'CONFIG_BPF_LSM=y' 'CONFIG_LSM=\"...,bpf\"'"
Ubuntu에서 BPF LSM을 활성화하려면 예를 들어:
GRUB_CMDLINE_LINUX 변수에 다음을 추가하고 저장합니다.
"lsm=lockdown,capability,yama,apparmor,bpf"
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,yama,apparmor,bpf"
sudo update-grub2
기본 allow 또는 privileged 프로필(가장 덜 안전한 프로필)로 실행하려면:
docker run --name bpflock -it --rm --cgroupns=host \
--pid=host --privileged \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
파일리스 바이너리 실행을 로깅하고 제한하려면 다음을 실행하세요:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_FILELESSLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
restricted 프로필로 실행할 때 컨테이너 로그에는 다음이 표시됩니다:
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=./loader retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=lsm_bprm_creds_from_file tgid=1833 pid=1833 ppid=1671 uid=1000 cgroupid=8821 comm=loader pcomm=bash filename=memfd:memfd-test retval=-1 reason=denied (restricted)" bpfprog=filelesslock subsys=bpf
time="2022-02-04T14:54:33Z" level=info msg="event=syscall_execve tgid=1833 pid=1833 ppid=0 uid=1000 cgroupid=8821 comm= pcomm= filename=/proc/self/fd/3 retval=-1" bpfprog=execsnoop subsys=bpf
restricted 프로필로 실행하면 문제가 발생할 수 있으므로 기본 프로필은 allow입니다.
커널 모듈 보호를 적용하려면
환경 변수 BPFLOCK_KMODLOCK_PROFILE=baseline 또는 BPFLOCK_KMODLOCK_PROFILE=restricted로 실행하세요:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KMODLOCK_PROFILE=restricted" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
예제:
$ sudo unshare -p -n -f
# modprobe xfs
modprobe: ERROR: could not insert 'xfs': Operation not permitted
time="2022-02-07T06:50:25+01:00" level=info msg="event=syscall_execve tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=/usr/sbin/modprobe retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:50:25+01:00" level=info msg="event=lsm_kernel_read_file operation=loading module tgid=52323 pid=52323 ppid=52288 uid=0 cgroupid=7014 comm=modprobe pcomm=bash filename=xfs.ko retval=-1 reason=denied (restricted)" bpfprog=kmodlock subsys=bpf
커널 이미지 잠금을 적용하려면 환경 변수 BPFLOCK_KIMGLOCK_PROFILE=baseline으로 실행하세요:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KIMGLOCK_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
$ sudo unshare -f -p -n bash
# head -c 1 /dev/mem
head: cannot open '/dev/mem' for reading: Operation not permitted
time="2022-02-07T06:57:22+01:00" level=info msg="event=syscall_execve tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash filename=/usr/bin/head retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-07T06:57:22+01:00" level=info msg="event=lsm_locked_down operation=/dev/mem,kmem,port tgid=52428 pid=52428 ppid=52288 uid=0 cgroupid=7014 comm=head pcomm=bash retval=-1 reason=denied (baseline)" bpfprog=kimglock subsys=bpf
bpf 제한을 적용하려면 환경 변수 BPFLOCK_BPFRESTRICT_PROFILE=baseline 또는 BPFLOCK_BPFRESTRICT_PROFILE=restricted로 실행하세요:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_BPFRESTRICT_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
다른 pid 및 네트워크 네임스페이스에서 실행하고 bpftool을 사용하는 예제:
$ sudo unshare -f -p -n bash
# bpftool prog
Error: can't get next program: Operation not permitted
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:40:56Z" level=info msg="event=lsm_bpf tgid=2378 pid=2378 ppid=2364 uid=0 cgroupid=9458 comm=bpftool pcomm=bash filename= retval=-1 reason=baseline" bpfprog=bpfrestrict subsys=bpf
-e "BPFLOCK_BPFRESTRICT_PROFILE=restricted" 프로필로 실행하면 모든 것에 대해 bpf가 거부됩니다:
time="2022-02-04T15:44:13Z" level=info msg="event=syscall_execve tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename=./tools/amd64/bpftool retval=0" bpfprog=execsnoop subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
time="2022-02-04T15:44:13Z" level=info msg="event=lsm_bpf tgid=2500 pid=2500 ppid=2499 uid=0 cgroupid=9458 comm=bpftool pcomm=sudo filename= retval=-1 reason=denied (restricted)" bpfprog=bpfrestrict subsys=bpf
바인드 마운트로 구성을 전달하는 것은 다음 명령을 사용하여 수행할 수 있습니다.
bpflock.yaml 및 bpf.d 프로필 구성이 현재 디렉터리의 bpflock 디렉터리 안에 있다고 가정하면 다음과 같이 사용할 수 있습니다:
ls bpflock/
bpf.d bpflock.d bpflock.yaml
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-v $(pwd)/bpflock/:/etc/bpflock \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
환경 변수는 --env-file을 사용하여 파일로 전달할 수도 있습니다. 모든 매개변수는 BPFLOCK_$VARIABLE_NAME=VALUE 형식을 사용하여 환경 변수로 전달할 수 있습니다.
파일의 환경 변수를 사용한 예제 실행:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
--env-file bpflock.env.list \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
문서 파일은 여기에서 찾을 수 있습니다.
bpflock은 빌드에 docker BuildKit을 사용하고, 일부 검사 및 테스트 실행에 Golang을 사용합니다. bpflock은 표준 golang 패키지를 다운로드하는 Ubuntu 컨테이너 내부에서 빌드됩니다.
다음을 실행하여 bpflock docker 컨테이너를 빌드하세요:
git submodule update --init --recursive
make
Bpf 프로그램은 libbpf를 사용하여 빌드됩니다. 사용되는 docker 이미지는 Ubuntu입니다.
docker를 사용하지 않고 bpf 프로그램만 직접 빌드하려면 Ubuntu에서:
sudo apt install -y pkg-config bison binutils-dev build-essential \
flex libc6-dev clang-12 libllvm12 llvm-12-dev libclang-12-dev \
zlib1g-dev libelf-dev libfl-dev gcc-multilib zlib1g-dev \
libcap-dev libiberty-dev libbfd-dev
그런 다음 실행하세요:
make bpf-programs
이 경우 생성된 프로그램은 ./bpf/build/... 디렉터리 안에 위치합니다.
bpflock은 Cilium 및 bcc 프로젝트의 소스 코드를 포함한 많은 리소스를 사용합니다.
bpflock 사용자 공간 구성 요소는 Apache License, Version 2.0에 따라 라이선스가 부여됩니다. BPF 코드는 명시된 경우 General Public License, Version 2.0에 따라 라이선스가 부여됩니다.
baseline--protection-block : 차단되는 작업의 쉼표로 구분된 목록입니다. allow|privileged 및 baseline 프로필에서 유효하며, 특정 애플리케이션을 손상시킬 수 있는 전체 restricted 프로필을 사용하지 않고도 일부 기능에 대한 접근을 제한할 수 있습니다. baseline 또는 privileged 프로필을 사용하면 대부분의 Linux 기능에 대한 접근이 열리지만, --protection-block 옵션을 사용하면 이러한 접근 중 일부를 차단할 수 있습니다.