
Jailer एक eBPF-आधारित प्रोसेस जेलिंग सिस्टम है जो Linux के लिए अनिवार्य एक्सेस नियंत्रण (MAC) प्रदान करता है। यह BPF task_storage मैप्स का उपयोग करके प्रोसेस को ट्रैक करता है और फ़ाइल एक्सेस, नेटवर्क ऑपरेशन तथा प्रोसेस निष्पादन पर भूमिका-आधारित नीतियों को लागू करता है।
चेतावनी: यह परियोजना भारी विकास के अधीन है और उत्पादन उपयोग के लिए तैयार नहीं है. एपीआई, नीति प्रारूप और व्यवहार बिना सूचना के बदल सकते हैं. केवल परीक्षण और प्रयोग के लिए उपयोग करें.
नोट: यह एक स्वतंत्र कार्यान्वयन है और मेटा के समाधान के समान परियोजना नहीं है. जबकि BpfJailer कार्यात्मक रूप से समान है और लियाम वाइज़हार्ट, जस्टिन न्गा, कार्ल एल खौरी, मनसी चड्ढा (मेटा) द्वारा मूल विचार और डिज़ाइन से प्रेरित है, यह एक अलग कोडबेस है जिसे स्वतंत्र रूप से विकसित किया गया है. हम उस दृष्टि और मूलभूत अवधारणाओं के लिए आभार व्यक्त करते हैं जिन्होंने इस कार्य को प्रेरित किया.
जेलर एक eBPF-आधारित प्रक्रिया जेलिंग प्रणाली है जो लिनक्स के लिए अनिवार्य एक्सेस नियंत्रण (MAC) प्रदान करती है. यह BPF task_storage मैप्स का उपयोग करके प्रक्रियाओं को ट्रैक करता है और फ़ाइल एक्सेस, नेटवर्क संचालन और प्रक्रिया निष्पादन पर भूमिका-आधारित नीतियाँ लागू करता है.

BPF_MAP_TYPE_TASK_STORAGE समर्थन के लिए)# Check current kernel config
zcat /proc/config.gz 2>/dev/null || cat /boot/config-$(uname -r)
आवश्यक विकल्प:
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_LSM=y
CONFIG_DEBUG_INFO_BTF=y
BPF LSM को कर्नेल बूट पैरामीटर में सक्षम होना चाहिए:
# Check if BPF LSM is active
cat /sys/kernel/security/lsm
# Should include "bpf" in the list
# If not, add to kernel boot parameters:
# Edit /etc/default/grub and add to GRUB_CMDLINE_LINUX:
# lsm=lockdown,capability,landlock,yama,apparmor,bpf
# Then update grub and reboot:
sudo update-grub
sudo reboot
Ubuntu/Debian सिस्टम के लिए, आप इसका भी उपयोग कर सकते हैं:
# Create a script to enable BPF LSM
cat > /tmp/enable_bpf_lsm.sh << 'EOF'
#!/bin/bash
GRUB_FILE="/etc/default/grub"
if grep -q "lsm=" "$GRUB_FILE"; then
sudo sed -i 's/lsm=[^""]*/lsm=lockdown,capability,landlock,yama,apparmor,bpf/' "$GRUB_FILE"
else
sudo sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 lsm=lockdown,capability,landlock,yama,apparmor,bpf"/' "$GRUB_FILE"
fi
sudo update-grub
echo "BPF LSM enabled. Please reboot."
EOF
chmod +x /tmp/enable_bpf_lsm.sh
sudo /tmp/enable_bpf_lsm.sh
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install build dependencies (Ubuntu/Debian)
sudo apt-get install -y clang llvm libelf-dev linux-headers-$(uname -r)
# Install BPF target for Rust
rustup target add bpfel-unknown-none
cd bpfjail
# Build BPF programs
cd bpfjailer-bpf && cargo build --release && cd ..
# Build daemon and client
cargo build --release
# Run as root (loads config/policy.json if present)
sudo RUST_LOG=info ./target/release/bpfjailer-daemon
अपेक्षित आउटपुट:
[INFO] BpfJailer daemon starting...
[INFO] Loading BpfJailer eBPF programs with libbpf-rs...
[INFO] ✓ pending_enrollments map available for enrollment
[INFO] ✓ network_rules map available for port/protocol filtering
[INFO] ✓ task_storage map created successfully
[INFO] ✓ Program task_alloc attached
[INFO] ✓ Program file_open attached
[INFO] ✓ Program socket_bind attached
[INFO] ✓ Program socket_connect attached
[INFO] ✓ Program bprm_check_security attached
[INFO] Initialized with default roles: restricted (1), permissive (2)
[INFO] Loaded policy from config/policy.json
[INFO] Loaded 5 roles
[INFO] Enrollment server listening on /run/bpfjailer/enrollment.sock
# Run vulnerability tests WITHOUT jailing (shows attacks succeed)
sudo python3 tests/vulnerable_apps/run_tests.py
# Run vulnerability tests WITH restricted role (shows attacks blocked)
sudo python3 tests/vulnerable_apps/run_tests.py --role 1
# Run specific test
sudo python3 tests/vulnerable_apps/run_tests.py --role 1 --test path
# List available tests and roles
sudo python3 tests/vulnerable_apps/run_tests.py --list
प्रतिबंधित भूमिका के साथ नमूना आउटपुट:
============================================================
TEST: Path Traversal / Arbitrary File Read
============================================================
Attempting to read /etc/passwd via path traversal...
BLOCKED - Permission denied (BpfJailer blocked file access)
============================================================
TEST: Command Injection
============================================================
Attempting command injection...
BLOCKED - Permission denied (BpfJailer blocked exec)
============================================================
TEST: Reverse Shell / Data Exfiltration
============================================================
Test 1: Reverse shell connection to 127.0.0.1:4444
BLOCKED - Permission denied (BpfJailer blocked connect)
#!/usr/bin/env python3
import socket
import json
import os
# Connect to daemon
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/run/bpfjailer/enrollment.sock")
# Enroll with restricted role (ID 1)
request = {"Enroll": {"pod_id": 1, "role_id": 1}}
sock.send((json.dumps(request) + "\n").encode())
response = sock.recv(4096).decode()
print(f"Enrollment: {response}")
sock.close()
# Try to read a file (should be blocked)
try:
open("/etc/passwd").read()
print("File access: ALLOWED")
except PermissionError:
print("File access: BLOCKED")
BpfJailer एक JSON नीति फ़ाइल से भूमिकाएँ लोड करता है. डेमॉन इस क्रम में नीति फ़ाइल खोजता है:
$BPFJAILER_POLICY पर्यावरण चर/etc/bpfjailer/policy.jsonconfig/policy.json (कार्यशील निर्देशिका के सापेक्ष){
"roles": {
"restricted": {
"id": 1,
"name": "restricted",
"flags": {
"allow_file_access": false,
"allow_network": false,
"allow_exec": false
},
"network_rules": []
},
"webserver": {
"id": 3,
"name": "webserver",
"flags": {
"allow_file_access": true,
"allow_network": true,
"allow_exec": false
},
"network_rules": [
{"protocol": "tcp", "port": 80, "allow": true},
{"protocol": "tcp", "port": 443, "allow": true}
]
}
},
"pods": []
}
BpfJailer प्रति-पोर्ट TCP/UDP नियमों के साथ सूक्ष्म-स्तरीय नेटवर्क नियंत्रण का समर्थन करता है.
network_rules map:
Key: { role_id, port, protocol, direction }
Value: allowed (1) or denied (0)
// In daemon code:
use bpfjailer_daemon::process_tracker::{PROTO_TCP, DIR_CONNECT};
// Allow TCP connect to ports 80 and 443 only
process_tracker.add_network_rule(RoleId(1), 80, PROTO_TCP, DIR_CONNECT, true)?;
process_tracker.add_network_rule(RoleId(1), 443, PROTO_TCP, DIR_CONNECT, true)?;
पोर्ट रेंज को policy.json में port_start और port_end का उपयोग करके निर्दिष्ट किया जा सकता है:
{
"network_rules": [
{"protocol": "tcp", "port": 443, "allow": true},
{"protocol": "tcp", "port_start": 8000, "port_end": 8100, "allow": true}
]
}
| फ़ील्ड | विवरण |
|---|---|
port | एकल पोर्ट (जैसे, 80) |
port_start + port_end | पोर्ट रेंज (जैसे, 8000-8100) |
नोट: बड़ी रेंज (>1000 पोर्ट) कई BPF मैप प्रविष्टियाँ खपत करती हैं. 1000 पोर्ट से अधिक रेंज के लिए एक चेतावनी लॉग की जाती है.
┌─────────────────────────────────────────────────────────────┐
│ User Space │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ Client │───▶│ bpfjailer-daemon │ │
│ │ (enroll) │ │ │ │
│ └─────────────┘ │ - PolicyManager │ │
│ │ - ProcessTracker│ │
│ │ - EnrollmentSvr │ │
│ └────────┬─────────┘ │
│ │ writes to │
│ ▼ │
├─────────────────────────────────────────────────────────────┤
│ BPF Maps │
│ ┌──────────────────┐ ┌─────────────┐ ┌──────────────┐ │
│ │pending_enrollments│ │ role_flags │ │ task_storage │ │
│ │ (PID → info) │ │ (role→flags)│ │(task→info) │ │
│ └──────────────────┘ └─────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ BPF LSM Hooks │
│ ┌────────────┐ ┌───────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ task_alloc │ │ file_open │ │socket_bind/ │ │bprm_check│ │
│ │(inheritance│ │(migration │ │ connect │ │_security │ │
│ │ + init) │ │ + check) │ │ (check) │ │ (check) │ │
│ └────────────┘ └───────────┘ └─────────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
/run/bpfjailer/enrollment.sock से कनेक्ट होती है{"Enroll": {"pod_id": N, "role_id": M}}pending_enrollments[PID] और role_flags[role_id] में लिखता हैtask_storage में स्थानांतरित करता हैtask_storage + role_flags की जाँच करते हैंtask_alloc हुक के माध्यम से विरासत प्राप्त करती हैंBpfJailer दो इंस्टॉलेशन मोड का समर्थन करता है:
नामांकन और नीति प्रबंधन के लिए एक चल रहे डेमॉन का उपयोग करता है:
# Install systemd service
sudo cp config/bpfjailer-daemon.service /etc/systemd/system/
sudo cp target/release/bpfjailer-daemon /usr/sbin/
sudo mkdir -p /etc/bpfjailer
sudo cp config/policy.json /etc/bpfjailer/
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable bpfjailer-daemon
sudo systemctl start bpfjailer-daemon
विशेषताएँ:
प्रारंभिक बूट पर BPF प्रोग्राम लोड करता है और बाहर निकल जाता है. प्रोग्राम रिबूट तक सक्रिय रहते हैं:
# Install bootstrap service
sudo cp config/bpfjailer-bootstrap.service /etc/systemd/system/
sudo cp target/release/bpfjailer-bootstrap /usr/sbin/
sudo mkdir -p /etc/bpfjailer
sudo cp config/policy.json /etc/bpfjailer/
# Enable (will run at next boot)
sudo systemctl daemon-reload
sudo systemctl enable bpfjailer-bootstrap
# Or run manually now
sudo bpfjailer-bootstrap
विशेषताएँ:
/sys/fs/bpf/bpfjailer/ पर पिन किए गएपिन किए गए प्रोग्राम जाँचें:
ls -la /sys/fs/bpf/bpfjailer/
ls -la /sys/fs/bpf/bpfjailer/maps/
ls -la /sys/fs/bpf/bpfjailer/progs/
ऑडिट ईवेंट देखें:
# Events are emitted to perf buffer, picked up by journald
journalctl -f | grep bpfjailer
# Check kernel version (needs 5.11+)
uname -r
# Check BPF LSM is active
cat /sys/kernel/security/lsm | grep bpf
# Check BTF is available
ls -la /sys/kernel/btf/vmlinux
# Check if BPF programs can be loaded
sudo bpftool prog list
# Check capabilities
sudo capsh --print | grep cap_bpf
# Ensure daemon is running as root
ps aux | grep bpfjailer
# Check socket permissions
ls -la /run/bpfjailer/enrollment.sock
यूनिक्स सॉकेट नामांकन के अलावा, BpfJailer निम्न के आधार पर स्वचालित नामांकन का समर्थन करता है:
किसी विशिष्ट बाइनरी को निष्पादित करने वाली सभी प्रक्रियाओं का स्वतः-नामांकन:
{
"exec_enrollments": [
{
"executable_path": "/usr/bin/nginx",
"pod_id": 1000,
"role": "webserver"
}
]
}
जब कोई प्रक्रिया /usr/bin/nginx निष्पादित करती है, तो यह स्वतः webserver भूमिका के साथ नामांकित हो जाती है. यह निष्पादन योग्य के inode द्वारा मिलान किया जाता है, इसलिए सिमलिंक और हार्डलिंक सही ढंग से संभाले जाते हैं.
किसी विशिष्ट cgroup में सभी प्रक्रियाओं का स्वतः-नामांकन:
{
"cgroup_enrollments": [
{
"cgroup_path": "/sys/fs/cgroup/bpfjailer/sandbox",
"pod_id": 2000,
"role": "sandbox"
}
]
}
cgroup बनाएँ और प्रक्रियाओं को इसमें ले जाएँ:
# Create cgroup
sudo mkdir -p /sys/fs/cgroup/bpfjailer/sandbox
# Move process to cgroup
echo $$ | sudo tee /sys/fs/cgroup/bpfjailer/sandbox/cgroup.procs
# Process is now auto-enrolled with sandbox role
नामांकन जानकारी के लिए निष्पादन योग्य पर विस्तारित विशेषताएँ सेट करें:
# Set enrollment xattrs
sudo setfattr -n user.bpfjailer.pod_id -v $(printf '\x01\x00\x00\x00\x00\x00\x00\x00') /path/to/binary
sudo setfattr -n user.bpfjailer.role_id -v $(printf '\x03\x00\x00\x00') /path/to/binary
# Check xattrs
getfattr -d /path/to/binary
निष्पादन के समय (bprm_check_security LSM हुक):
exec_enrollment मैप में हैcgroup_enrollment मैप में हैtask_storage को pod_id और role_id के साथ सेट करेंनामांकन task_alloc हुक के माध्यम से fork/exec में बना रहता है
नीति नियम (नेटवर्क, पथ, निष्पादन) role_id के आधार पर लागू किए जाते हैं
GPL-2.0 (BPF प्रोग्राम के लिए आवश्यक)
| विशेषता | स्थिति | विवरण |
|---|
| प्रक्रिया ट्रैकिंग | ✅ कार्यरत | task_storage BPF मैप का उपयोग करके प्रक्रियाओं को ट्रैक करता है |
| सॉकेट नामांकन | ✅ कार्यरत | प्रक्रियाएँ यूनिक्स सॉकेट API के माध्यम से नामांकन करती हैं |
| भूमिका-आधारित नीतियाँ | ✅ कार्यरत | प्रतिबंधित और अनुमोदक भूमिकाएँ |
| फ़ाइल एक्सेस नियंत्रण | ✅ कार्यरत | फ़ाइल खोलने के संचालन को ब्लॉक/अनुमति दें |
| जेल विरासत | ✅ कार्यरत | चाइल्ड प्रक्रियाएँ पैरेंट की जेल प्राप्त करती हैं |
| नेटवर्क नियंत्रण | ✅ कार्यरत | सॉकेट बाइंड/कनेक्ट को ब्लॉक/अनुमति दें |
| पोर्ट/प्रोटोकॉल फ़िल्टरिंग | ✅ कार्यरत | प्रति-पोर्ट TCP/UDP अनुमति/अस्वीकार नियम |
| निष्पादन नियंत्रण | ✅ कार्यरत | प्रक्रिया निष्पादन को ब्लॉक/अनुमति दें |
| पथ मिलान | ✅ कार्यरत | कैश अमान्यकरण के साथ डेंट्री वॉकिंग |
| हस्ताक्षरित बाइनरी | 🚧 स्टब | बाइनरी हस्ताक्षर सत्यापन (लागू नहीं) |
| वैकल्पिक नामांकन | ✅ कार्यरत | निष्पादन योग्य, cgroup या xattr द्वारा स्वतः-नामांकन |
| डेमॉनलेस मोड | ✅ कार्यरत | बूटस्ट्रैप बाइनरी प्रारंभिक बूट पर प्रोग्राम पिन करता है |
| ऑडिट ईवेंट | ✅ कार्यरत | systemd-journald एकीकरण के लिए परफ बफर |
| परीक्षण | कमजोरी | शमनकर्ता |
|---|
path_traversal | ../ के माध्यम से मनमानी फ़ाइल पढ़ना | प्रतिबंधित, पृथक |
command_injection | शेल कमांड निष्पादन | प्रतिबंधित, वेबसर्वर, पृथक |
reverse_shell | हमलावर के लिए बाहरी कनेक्शन | प्रतिबंधित, पृथक |
ssrf | आंतरिक सेवाएँ/क्लाउड मेटाडेटा तक पहुँच | प्रतिबंधित, पृथक |
arbitrary_write | संवेदनशील पथों पर लिखना | प्रतिबंधित |
crypto_miner | डाउनलोड + निष्पादित + पूल से कनेक्ट | प्रतिबंधित, वेबसर्वर |
privilege_escalation | शैडो पढ़ना, sudoers लिखना | प्रतिबंधित |
| ध्वज | विवरण |
|---|
allow_file_access | फ़ाइल खोलने के संचालन की अनुमति दें |
allow_network | सॉकेट बाइंड/कनेक्ट की अनुमति दें |
allow_exec | प्रक्रिया निष्पादन की अनुमति दें |
allow_setuid | setuid संचालन की अनुमति दें |
allow_ptrace | ptrace संचालन की अनुमति दें |
| भूमिका आईडी | नाम | फ़ाइल एक्सेस | नेटवर्क | निष्पादन |
|---|
| 1 | प्रतिबंधित | अवरुद्ध | अवरुद्ध | अवरुद्ध |
| 2 | अनुमोदक | अनुमत | अनुमत | अनुमत |
| 3 | वेबसर्वर | अनुमत | पोर्ट 80, 443, 8080 | अवरुद्ध |
| 4 | डेटाबेस | अनुमत | पोर्ट 5432, 6379 | अवरुद्ध |
| 5 | पृथक | अनुमत | अवरुद्ध | अवरुद्ध |
| 6 | डेटाबेस सहित वेब | अनुमत | पोर्ट 80, 443, 5432, 3306, 6379 | अवरुद्ध |
| 7 | कार्यकर्ता | अनुमत | पोर्ट 443, 5432, 6379, 5672 | अनुमत |
| स्थिरांक | मान | विवरण |
|---|
PROTO_TCP | 6 | TCP प्रोटोकॉल |
PROTO_UDP | 17 | UDP प्रोटोकॉल |
DIR_BIND | 0 | socket bind() |
DIR_CONNECT | 1 | socket connect() |
| पहलू | डेमॉन मोड | डेमॉनलेस मोड |
|---|
| हमले की सतह | चल रहा डेमॉन | कोई चल रही प्रक्रिया नहीं |
| नामांकन | यूनिक्स सॉकेट + विकल्प | केवल विकल्प |
| नीति अद्यतन | हॉट रीलोड | रिबूट आवश्यक |
| ऑडिट लॉगिंग | डेमॉन ringbuf पढ़ता है | परफ बफर के माध्यम से journald |
| प्रोग्राम हटाना | डेमॉन रोकें | केवल रिबूट |
| बूट क्रम | network.target के बाद | basic.target से पहले |