Raspberry Pi Security Projects That Actually Solve Problems
From network monitoring to physical security – practical Raspberry Pi projects that enhance your home security without breaking the bank
After collecting a drawer full of Raspberry Pis over the years (we all have that drawer, right?), I decided it was time to put them to work. Here are five security projects that actually solve real problems, complete with implementation guides and lessons learned.
Why Raspberry Pi for Security?
Before diving into projects, let's address the elephant in the room: Why use a $35 computer for security when enterprise solutions exist?
- Low Power Consumption: Running 24/7 costs pennies
- Silent Operation: No fans = no noise in your home
- Versatility: From network monitoring to physical security
- Learning Platform: Mistakes are cheap and educational
- Real Solutions: These aren't toys – they solve actual problems
Project 1: The Network Sentinel – DNS Sinkhole & Monitor
Problem Solved: Ads, tracking, and malicious domains accessing your network
Hardware: Raspberry Pi 4 (2GB), microSD card, Ethernet cable
Implementation
# Install Pi-hole
curl -sSL https://install.pi-hole.net | bash
# Add custom blocklists for security
cd /etc/pihole
sudo wget https://raw.githubusercontent.com/RPiList/specials/master/Blocklists/malware.txt
sudo wget https://raw.githubusercontent.com/RPiList/specials/master/Blocklists/ransomware.txt
sudo wget https://raw.githubusercontent.com/RPiList/specials/master/Blocklists/phishing.txt
# Update gravity database
pihole -g
Enhancements I Added
#!/usr/bin/env python3
# dns_alert.py - Alert on suspicious DNS queries
import tailer
import re
from datetime import datetime
import smtplib
# Suspicious TLDs often used in malware
SUSPICIOUS_TLDS = ['.tk', '.ml', '.ga', '.cf', '.click', '.download']
def check_dns_query(query):
for tld in SUSPICIOUS_TLDS:
if query.endswith(tld):
return True
# Check for DGA-like domains (random looking)
if len(re.findall(r'[0-9]', query)) > 5:
return True
return False
def monitor_pihole_log():
for line in tailer.follow(open('/var/log/pihole.log')):
if 'query[A]' in line:
domain = line.split('query[A]')[1].split('from')[0].strip()
if check_dns_query(domain):
alert(f"Suspicious DNS query: {domain}")
def alert(message):
print(f"[{datetime.now()}] ALERT: {message}")
# Add email/Discord notification here
if __name__ == "__main__":
monitor_pihole_log()
Results: Blocking 30-40% of DNS queries (mostly ads/tracking), caught 3 malware callbacks in 6 months, kids' devices are significantly faster.
Project 2: The Silent Guardian – Motion Detection Security Camera
Problem Solved: Package theft, wanting to monitor specific areas without cloud dependencies
Hardware: Raspberry Pi Zero W, Pi Camera v2, PIR motion sensor, 3D printed case
Implementation
#!/usr/bin/env python3
# motion_security.py - Smart motion detection with AI
import cv2
import numpy as np
from picamera2 import Picamera2
import time
from datetime import datetime
import os
class SecurityCamera:
def __init__(self):
self.camera = Picamera2()
self.camera.configure(self.camera.create_preview_configuration())
self.camera.start()
# YOLO for person detection
self.net = cv2.dnn.readNet("yolov4-tiny.weights", "yolov4-tiny.cfg")
self.classes = open("coco.names").read().strip().split("\n")
def detect_person(self, frame):
height, width = frame.shape[:2]
# Create blob from image
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (416, 416),
swapRB=True, crop=False)
self.net.setInput(blob)
outputs = self.net.forward(self.net.getUnconnectedOutLayersNames())
# Parse detections
for output in outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5 and self.classes[class_id] == "person":
return True
return False
def capture_alert(self):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"alert_{timestamp}.jpg"
frame = self.camera.capture_array()
if self.detect_person(frame):
cv2.imwrite(f"/home/pi/alerts/{filename}", frame)
self.send_notification(filename)
return True
return False
def send_notification(self, filename):
# Send to Discord webhook
import requests
webhook_url = "YOUR_DISCORD_WEBHOOK"
with open(f"/home/pi/alerts/{filename}", "rb") as f:
files = {"file": (filename, f)}
data = {"content": f"🚨 Person detected at {datetime.now()}"}
requests.post(webhook_url, data=data, files=files)
if __name__ == "__main__":
camera = SecurityCamera()
while True:
if GPIO.input(PIR_PIN):
camera.capture_alert()
time.sleep(10) # Cooldown period
time.sleep(0.1)
Results: Caught multiple package delivery attempts, identified a raccoon problem (AI thought it was a person at first), zero false alerts after tuning.
Project 3: The Honeypot – Early Warning System
Problem Solved: Detecting network intrusion attempts before they reach real systems
Hardware: Raspberry Pi 3B+, Ethernet connection
Implementation
#!/usr/bin/env python3
# honeypot.py - Lightweight SSH/HTTP honeypot
import socket
import threading
import json
from datetime import datetime
import sqlite3
class Honeypot:
def __init__(self):
self.setup_database()
def setup_database(self):
self.conn = sqlite3.connect('honeypot.db', check_same_thread=False)
self.conn.execute('''
CREATE TABLE IF NOT EXISTS attempts (
timestamp TEXT,
service TEXT,
source_ip TEXT,
username TEXT,
password TEXT,
user_agent TEXT
)
''')
self.conn.commit()
def log_attempt(self, service, source_ip, **kwargs):
self.conn.execute('''
INSERT INTO attempts VALUES (?, ?, ?, ?, ?, ?)
''', (
datetime.now().isoformat(),
service,
source_ip,
kwargs.get('username', ''),
kwargs.get('password', ''),
kwargs.get('user_agent', '')
))
self.conn.commit()
# Alert on suspicious patterns
if self.check_threat_level(source_ip):
self.send_alert(source_ip)
def fake_ssh_server(self, port=2222):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', port))
server.listen(5)
while True:
client, addr = server.accept()
# Send fake SSH banner
client.send(b"SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.1\r\n")
try:
data = client.recv(1024).decode('utf-8')
# Parse SSH handshake for username
self.log_attempt('ssh', addr[0])
except:
pass
finally:
client.close()
def fake_http_server(self, port=8080):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', port))
server.listen(5)
while True:
client, addr = server.accept()
try:
request = client.recv(1024).decode('utf-8')
lines = request.split('\n')
# Extract user agent
user_agent = ""
for line in lines:
if line.startswith("User-Agent:"):
user_agent = line.split(":", 1)[1].strip()
# Send fake response
response = """HTTP/1.1 200 OK
Content-Type: text/html
<html><body><h1>Router Configuration</h1></body></html>
"""
client.send(response.encode())
self.log_attempt('http', addr[0], user_agent=user_agent)
except:
pass
finally:
client.close()
def check_threat_level(self, ip):
# Check if IP has made multiple attempts
cursor = self.conn.execute('''
SELECT COUNT(*) FROM attempts
WHERE source_ip = ?
AND timestamp > datetime('now', '-1 hour')
''', (ip,))
count = cursor.fetchone()[0]
return count > 5
honeypot = Honeypot()
# Run services in threads
threading.Thread(target=honeypot.fake_ssh_server, daemon=True).start()
threading.Thread(target=honeypot.fake_http_server, daemon=True).start()
print("Honeypot running... Check honeypot.db for attempts")
# Keep main thread alive
while True:
time.sleep(60)
Results: Detected 3 targeted scans of my network, identified compromised IoT device attempting lateral movement, fascinating data on bot behavior.
Project 4: The Vault Guardian – Hardware Security Key Backup
Problem Solved: Secure backup for 2FA recovery codes and emergency access
Hardware: Raspberry Pi Zero, OLED display, button, encrypted SD card
Implementation
#!/usr/bin/env python3
# vault_guardian.py - Offline 2FA backup vault
import os
import json
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
import getpass
from pathlib import Path
class SecureVault:
def __init__(self):
self.vault_file = Path("/home/pi/vault/backup.enc")
self.vault_file.parent.mkdir(exist_ok=True)
def derive_key(self, password: str, salt: bytes) -> bytes:
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
return key
def create_backup(self):
print("=== 2FA Recovery Code Vault ===")
# Generate new salt
salt = os.urandom(16)
# Get master password
password = getpass.getpass("Create master password: ")
confirm = getpass.getpass("Confirm password: ")
if password != confirm:
print("Passwords don't match!")
return
# Derive encryption key
key = self.derive_key(password, salt)
f = Fernet(key)
# Collect recovery codes
codes = {}
print("\nEnter recovery codes (empty service name to finish):")
while True:
service = input("Service name: ").strip()
if not service:
break
recovery_codes = []
print(f"Enter recovery codes for {service} (empty to finish):")
while True:
code = input("Code: ").strip()
if not code:
break
recovery_codes.append(code)
if recovery_codes:
codes[service] = recovery_codes
# Add metadata
vault_data = {
"created": datetime.now().isoformat(),
"services": codes,
"notes": input("\nAny additional notes: ")
}
# Encrypt and save
encrypted = f.encrypt(json.dumps(vault_data).encode())
with open(self.vault_file, 'wb') as file:
file.write(salt + encrypted)
print(f"\n✓ Vault created with {len(codes)} services")
print("⚠️ This Pi is now your 2FA recovery device. Keep it secure!")
def unlock_vault(self):
if not self.vault_file.exists():
print("No vault found!")
return
with open(self.vault_file, 'rb') as file:
data = file.read()
salt = data[:16]
encrypted = data[16:]
# Get password
password = getpass.getpass("Enter vault password: ")
try:
key = self.derive_key(password, salt)
f = Fernet(key)
decrypted = f.decrypt(encrypted)
vault_data = json.loads(decrypted)
print(f"\n=== Vault Contents ===")
print(f"Created: {vault_data['created']}")
print(f"Services: {len(vault_data['services'])}")
for service, codes in vault_data['services'].items():
print(f"\n{service}:")
for code in codes:
print(f" - {code}")
if vault_data.get('notes'):
print(f"\nNotes: {vault_data['notes']}")
except Exception as e:
print("Failed to decrypt vault. Wrong password?")
# Physical button interface
import RPi.GPIO as GPIO
BUTTON_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
vault = SecureVault()
print("Press button to unlock vault...")
while True:
if GPIO.input(BUTTON_PIN) == GPIO.LOW:
vault.unlock_vault()
time.sleep(5) # Debounce
Results: Peace of mind knowing recovery codes are offline but accessible, survived a YubiKey failure gracefully, spouse approved the "break glass" simplicity.
Project 5: The Compliance Scanner – Automated Security Auditing
Problem Solved: Keeping track of security posture across multiple devices
Hardware: Raspberry Pi 4 (4GB), good network connection
Implementation
#!/usr/bin/env python3
# compliance_scanner.py - Automated security baseline checker
import nmap
import paramiko
import json
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
class ComplianceScanner:
def __init__(self):
self.nm = nmap.PortScanner()
self.results = []
def scan_network(self, network="192.168.1.0/24"):
print(f"Scanning network: {network}")
# Find all hosts
self.nm.scan(hosts=network, arguments='-sn')
hosts = []
for host in self.nm.all_hosts():
if self.nm[host].state() == 'up':
hosts.append(host)
print(f"Found {len(hosts)} hosts")
# Detailed scan of each host
for host in hosts:
self.scan_host(host)
return self.results
def scan_host(self, host):
print(f"\nScanning {host}...")
result = {
'host': host,
'timestamp': datetime.now().isoformat(),
'issues': [],
'score': 100
}
# Port scan
self.nm.scan(host, '1-65535', '-sV')
if host in self.nm.all_hosts():
# Check for risky services
risky_ports = {
23: 'Telnet',
21: 'FTP',
445: 'SMB',
3389: 'RDP',
22: 'SSH' # Not risky, but worth checking config
}
for port, service in risky_ports.items():
if port in self.nm[host]['tcp']:
state = self.nm[host]['tcp'][port]['state']
if state == 'open':
issue = f"{service} port {port} is open"
result['issues'].append(issue)
result['score'] -= 10
# Check SSH configuration if available
if 22 in self.nm[host]['tcp'] and self.nm[host]['tcp'][22]['state'] == 'open':
ssh_issues = self.check_ssh_config(host)
result['issues'].extend(ssh_issues)
result['score'] -= len(ssh_issues) * 5
self.results.append(result)
def check_ssh_config(self, host):
issues = []
try:
# Try to connect with weak credentials
weak_creds = [
('pi', 'raspberry'),
('admin', 'admin'),
('root', 'root')
]
for username, password in weak_creds:
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password, timeout=3)
issues.append(f"Weak credentials work: {username}:{password}")
ssh.close()
except:
pass # Good, credentials didn't work
except Exception as e:
pass
return issues
def generate_report(self):
report = "# Network Security Compliance Report\n\n"
report += f"Scan Date: {datetime.now()}\n\n"
critical_hosts = [r for r in self.results if r['score'] < 70]
warning_hosts = [r for r in self.results if 70 <= r['score'] < 90]
if critical_hosts:
report += "## 🔴 Critical Issues\n\n"
for host in critical_hosts:
report += f"### {host['host']} (Score: {host['score']})\n"
for issue in host['issues']:
report += f"- {issue}\n"
report += "\n"
if warning_hosts:
report += "## 🟡 Warnings\n\n"
for host in warning_hosts:
report += f"### {host['host']} (Score: {host['score']})\n"
for issue in host['issues']:
report += f"- {issue}\n"
report += "\n"
# Summary statistics
avg_score = sum(r['score'] for r in self.results) / len(self.results)
report += f"## Summary\n\n"
report += f"- Hosts scanned: {len(self.results)}\n"
report += f"- Average security score: {avg_score:.1f}/100\n"
report += f"- Critical issues: {len(critical_hosts)}\n"
report += f"- Warnings: {len(warning_hosts)}\n"
return report
# Run weekly scan
scanner = ComplianceScanner()
scanner.scan_network()
report = scanner.generate_report()
print("\n" + report)
# Save report
with open(f"/home/pi/reports/scan_{datetime.now().strftime('%Y%m%d')}.md", "w") as f:
f.write(report)
Results: Found 2 IoT devices with default passwords, discovered forgotten test VM with open services, maintains security baseline visibility.
Lessons Learned
After implementing these projects, here are my key takeaways:
1. Start Simple, Iterate Often
My first Pi-hole setup was basic. Now it has custom blocklists, monitoring scripts, and integration with my SIEM. Evolution is normal.
2. Physical Security Matters
That expensive Arlo camera? My Pi Zero setup catches more relevant events because I positioned it better and tuned it myself.
3. False Positives Will Happen
My honeypot initially alerted on my own port scans. My motion detector thought shadows were intruders. Tuning is crucial.
4. Power and Network Reliability
Invest in good power supplies and consider PoE HATs. Nothing worse than your security system going down during a storm.
5. Documentation Is Security
Every project has a README with recovery procedures. When something breaks at 2 AM, you'll thank yourself.
Cost Analysis
Total investment for all five projects:
- Raspberry Pis: ~$200
- Accessories (cases, cards, sensors): ~$100
- Time invested: ~40 hours
- Knowledge gained: Priceless
Compare that to:
- Enterprise DNS filter: $500+/year
- Cloud security camera: $10+/month
- SIEM subscription: $100+/month
- Vulnerability scanner: $2000+/year
What's Next?
I'm currently working on:
- AI-Powered Threat Detection: Using Coral TPU for real-time network traffic analysis
- Mesh Security Network: Multiple Pis creating a distributed security sensor network
- Incident Response Bot: Automated playbook execution via Discord commands
Your Turn
These projects solve my specific problems, but the beauty of Raspberry Pi is customization. Maybe you need:
- A secure password manager display
- Network usage monitor for kids' devices
- Automated backup verification system
- Physical security for a specific door/window
The key is identifying a real problem and building a focused solution.
Resources
- Hardware: CanaKit for reliable Pi bundles
- Cases: Check Thingiverse for security-specific Pi cases
- Community: r/raspberry_pi and r/homelab are goldmines
- My Scripts: [GitHub - Coming Soon] (sanitizing for public release)
Remember: The best security system is one that actually gets used. These Raspberry Pi projects work because they're maintainable, understandable, and solve real problems.
What security problem will you solve with your next Pi?
Have questions about any of these projects? Found a cool use for your Pi? Let me know! I'm always looking for the next practical security project.
Related Posts
Building IR Playbooks with Ansible
Transform incident response from chaos to choreography using Ansible. Learn to build automated playb...
Vulnerability Management at Scale with Open Source Tools
Build an enterprise-grade vulnerability management program using only open source tools. From scanni...
eBPF for Security Monitoring: A Practical Guide
Learn how to leverage eBPF for real-time security monitoring in Linux environments with practical ex...