Initial commit: Portfolio Website
Vollständige Next.js 15 Portfolio-Website mit: - Blog-System mit 100+ Artikeln - Supabase-Integration - Responsive Design mit Tailwind CSS - TypeScript-Konfiguration - Testing-Setup mit Vitest und Playwright Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,825 @@
|
||||
# IoT Security Best Practices
|
||||
|
||||
**Meta-Description:** IoT Security implementieren. Device Authentication, Verschlüsselung, Secure Boot und Firmware Updates für sichere IoT-Systeme.
|
||||
|
||||
**Keywords:** IoT Security, Device Authentication, TLS, Encryption, Secure Boot, Firmware Update, MQTT Security
|
||||
|
||||
---
|
||||
|
||||
## Einführung
|
||||
|
||||
IoT-Sicherheit ist kritisch – vernetzte Geräte sind potenzielle Angriffsziele. **Device Authentication, Verschlüsselung, Secure Boot** und sichere **Firmware Updates** sind Pflicht für jedes professionelle IoT-System.
|
||||
|
||||
---
|
||||
|
||||
## IoT Security Layers
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ IOT SECURITY ARCHITECTURE │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Layer 7 - Application Security: │
|
||||
│ ├── Input Validation │
|
||||
│ ├── API Security (Rate Limiting, Auth) │
|
||||
│ └── Secure Data Handling │
|
||||
│ │
|
||||
│ Layer 6 - Identity & Access: │
|
||||
│ ├── Device Authentication (Certificates, Tokens) │
|
||||
│ ├── User Authentication (MFA, Passkeys) │
|
||||
│ └── Role-Based Access Control (RBAC) │
|
||||
│ │
|
||||
│ Layer 5 - Communication Security: │
|
||||
│ ├── TLS 1.3 Encryption │
|
||||
│ ├── mTLS (Mutual TLS) │
|
||||
│ └── VPN / Private Networks │
|
||||
│ │
|
||||
│ Layer 4 - Network Security: │
|
||||
│ ├── Firewalls / Segmentation │
|
||||
│ ├── Intrusion Detection (IDS) │
|
||||
│ └── Traffic Monitoring │
|
||||
│ │
|
||||
│ Layer 3 - Device Security: │
|
||||
│ ├── Secure Boot │
|
||||
│ ├── Hardware Security Module (HSM) │
|
||||
│ ├── Firmware Signing │
|
||||
│ └── Secure Storage (Encrypted) │
|
||||
│ │
|
||||
│ Layer 2 - Physical Security: │
|
||||
│ ├── Tamper Detection │
|
||||
│ ├── Secure Enclosure │
|
||||
│ └── Debug Port Disable │
|
||||
│ │
|
||||
│ Compliance: NIST, ISO 27001, IEC 62443, GDPR │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Device Authentication
|
||||
|
||||
```typescript
|
||||
// lib/device-auth.ts
|
||||
import crypto from 'crypto';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
interface DeviceCredentials {
|
||||
deviceId: string;
|
||||
certificate: string;
|
||||
privateKey: string;
|
||||
}
|
||||
|
||||
interface DeviceToken {
|
||||
deviceId: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
capabilities: string[];
|
||||
}
|
||||
|
||||
class DeviceAuthenticator {
|
||||
private caCertificate: string;
|
||||
private jwtSecret: string;
|
||||
|
||||
constructor(caCertPath: string, jwtSecret: string) {
|
||||
this.caCertificate = require('fs').readFileSync(caCertPath, 'utf8');
|
||||
this.jwtSecret = jwtSecret;
|
||||
}
|
||||
|
||||
// X.509 Certificate-based Authentication
|
||||
verifyCertificate(clientCert: string): boolean {
|
||||
try {
|
||||
const cert = new crypto.X509Certificate(clientCert);
|
||||
const caCert = new crypto.X509Certificate(this.caCertificate);
|
||||
|
||||
// Verify certificate chain
|
||||
if (!cert.verify(caCert.publicKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
const now = new Date();
|
||||
if (now < new Date(cert.validFrom) || now > new Date(cert.validTo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check revocation (in production: check CRL/OCSP)
|
||||
// ...
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Certificate verification failed:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract Device ID from Certificate
|
||||
extractDeviceId(clientCert: string): string | null {
|
||||
try {
|
||||
const cert = new crypto.X509Certificate(clientCert);
|
||||
// CN (Common Name) enthält Device ID
|
||||
const cnMatch = cert.subject.match(/CN=([^,]+)/);
|
||||
return cnMatch ? cnMatch[1] : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// JWT Token Generation für Devices
|
||||
generateDeviceToken(deviceId: string, capabilities: string[]): string {
|
||||
const payload: Omit<DeviceToken, 'iat' | 'exp'> = {
|
||||
deviceId,
|
||||
capabilities
|
||||
};
|
||||
|
||||
return jwt.sign(payload, this.jwtSecret, {
|
||||
expiresIn: '24h',
|
||||
issuer: 'iot-platform',
|
||||
audience: 'iot-devices'
|
||||
});
|
||||
}
|
||||
|
||||
// Token Verification
|
||||
verifyDeviceToken(token: string): DeviceToken | null {
|
||||
try {
|
||||
return jwt.verify(token, this.jwtSecret, {
|
||||
issuer: 'iot-platform',
|
||||
audience: 'iot-devices'
|
||||
}) as DeviceToken;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Challenge-Response Authentication
|
||||
generateChallenge(): { challenge: string; expiresAt: Date } {
|
||||
const challenge = crypto.randomBytes(32).toString('hex');
|
||||
const expiresAt = new Date(Date.now() + 5 * 60 * 1000); // 5 Minuten
|
||||
|
||||
return { challenge, expiresAt };
|
||||
}
|
||||
|
||||
verifyChallenge(
|
||||
challenge: string,
|
||||
response: string,
|
||||
devicePublicKey: string
|
||||
): boolean {
|
||||
try {
|
||||
const verify = crypto.createVerify('SHA256');
|
||||
verify.update(challenge);
|
||||
|
||||
return verify.verify(devicePublicKey, response, 'base64');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// API Key Authentication (für einfachere Devices)
|
||||
interface APIKeyConfig {
|
||||
deviceId: string;
|
||||
apiKey: string;
|
||||
createdAt: Date;
|
||||
lastUsed?: Date;
|
||||
rateLimit: number;
|
||||
}
|
||||
|
||||
class APIKeyAuthenticator {
|
||||
private keys: Map<string, APIKeyConfig> = new Map();
|
||||
|
||||
generateKey(deviceId: string, rateLimit: number = 100): string {
|
||||
const apiKey = `iot_${crypto.randomBytes(24).toString('hex')}`;
|
||||
|
||||
this.keys.set(apiKey, {
|
||||
deviceId,
|
||||
apiKey,
|
||||
createdAt: new Date(),
|
||||
rateLimit
|
||||
});
|
||||
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
validateKey(apiKey: string): APIKeyConfig | null {
|
||||
const config = this.keys.get(apiKey);
|
||||
|
||||
if (!config) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Update last used
|
||||
config.lastUsed = new Date();
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
revokeKey(apiKey: string): void {
|
||||
this.keys.delete(apiKey);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TLS/mTLS Communication
|
||||
|
||||
```typescript
|
||||
// lib/secure-mqtt.ts
|
||||
import mqtt from 'mqtt';
|
||||
import fs from 'fs';
|
||||
import tls from 'tls';
|
||||
|
||||
interface SecureMQTTConfig {
|
||||
brokerUrl: string;
|
||||
caCert: string;
|
||||
clientCert: string;
|
||||
clientKey: string;
|
||||
clientId: string;
|
||||
}
|
||||
|
||||
function createSecureMQTTClient(config: SecureMQTTConfig): mqtt.MqttClient {
|
||||
return mqtt.connect(config.brokerUrl, {
|
||||
clientId: config.clientId,
|
||||
protocol: 'mqtts',
|
||||
protocolVersion: 5, // MQTT 5.0
|
||||
|
||||
// TLS Options
|
||||
ca: fs.readFileSync(config.caCert),
|
||||
cert: fs.readFileSync(config.clientCert),
|
||||
key: fs.readFileSync(config.clientKey),
|
||||
|
||||
// Strict verification
|
||||
rejectUnauthorized: true,
|
||||
checkServerIdentity: (hostname, cert) => {
|
||||
// Custom hostname verification if needed
|
||||
return tls.checkServerIdentity(hostname, cert);
|
||||
},
|
||||
|
||||
// Connection Options
|
||||
keepalive: 60,
|
||||
reconnectPeriod: 5000,
|
||||
connectTimeout: 30000,
|
||||
|
||||
// Clean Session (MQTT 5.0)
|
||||
clean: true,
|
||||
properties: {
|
||||
sessionExpiryInterval: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// HTTPS Server mit mTLS
|
||||
import https from 'https';
|
||||
import express from 'express';
|
||||
|
||||
function createSecureServer(
|
||||
app: express.Application,
|
||||
caCert: string,
|
||||
serverCert: string,
|
||||
serverKey: string
|
||||
) {
|
||||
return https.createServer({
|
||||
ca: fs.readFileSync(caCert),
|
||||
cert: fs.readFileSync(serverCert),
|
||||
key: fs.readFileSync(serverKey),
|
||||
|
||||
// Require client certificates (mTLS)
|
||||
requestCert: true,
|
||||
rejectUnauthorized: true,
|
||||
|
||||
// Minimum TLS version
|
||||
minVersion: 'TLSv1.3',
|
||||
|
||||
// Cipher Suites (only strong ciphers)
|
||||
ciphers: [
|
||||
'TLS_AES_256_GCM_SHA384',
|
||||
'TLS_CHACHA20_POLY1305_SHA256',
|
||||
'TLS_AES_128_GCM_SHA256'
|
||||
].join(':')
|
||||
}, app);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secure Data Storage
|
||||
|
||||
```typescript
|
||||
// lib/secure-storage.ts
|
||||
import crypto from 'crypto';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const scrypt = promisify(crypto.scrypt);
|
||||
|
||||
interface EncryptedData {
|
||||
iv: string;
|
||||
data: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
}
|
||||
|
||||
class SecureStorage {
|
||||
private masterKey: Buffer | null = null;
|
||||
|
||||
// Key Derivation von Password/PIN
|
||||
async deriveKey(password: string, salt: Buffer): Promise<Buffer> {
|
||||
return scrypt(password, salt, 32) as Promise<Buffer>;
|
||||
}
|
||||
|
||||
// Initialize mit Master Key
|
||||
async initialize(masterPassword: string): Promise<void> {
|
||||
const salt = crypto.randomBytes(32);
|
||||
this.masterKey = await this.deriveKey(masterPassword, salt);
|
||||
}
|
||||
|
||||
// AES-256-GCM Encryption
|
||||
encrypt(plaintext: string): EncryptedData {
|
||||
if (!this.masterKey) {
|
||||
throw new Error('Storage not initialized');
|
||||
}
|
||||
|
||||
const iv = crypto.randomBytes(16);
|
||||
const salt = crypto.randomBytes(32);
|
||||
|
||||
const cipher = crypto.createCipheriv('aes-256-gcm', this.masterKey, iv);
|
||||
|
||||
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
|
||||
encrypted += cipher.final('hex');
|
||||
|
||||
const tag = cipher.getAuthTag();
|
||||
|
||||
return {
|
||||
iv: iv.toString('hex'),
|
||||
data: encrypted,
|
||||
tag: tag.toString('hex'),
|
||||
salt: salt.toString('hex')
|
||||
};
|
||||
}
|
||||
|
||||
// Decryption
|
||||
decrypt(encryptedData: EncryptedData): string {
|
||||
if (!this.masterKey) {
|
||||
throw new Error('Storage not initialized');
|
||||
}
|
||||
|
||||
const iv = Buffer.from(encryptedData.iv, 'hex');
|
||||
const tag = Buffer.from(encryptedData.tag, 'hex');
|
||||
|
||||
const decipher = crypto.createDecipheriv('aes-256-gcm', this.masterKey, iv);
|
||||
decipher.setAuthTag(tag);
|
||||
|
||||
let decrypted = decipher.update(encryptedData.data, 'hex', 'utf8');
|
||||
decrypted += decipher.final('utf8');
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
// Secure Credential Storage
|
||||
async storeCredentials(
|
||||
deviceId: string,
|
||||
credentials: Record<string, string>
|
||||
): Promise<EncryptedData> {
|
||||
const data = JSON.stringify({ deviceId, credentials, timestamp: Date.now() });
|
||||
return this.encrypt(data);
|
||||
}
|
||||
}
|
||||
|
||||
// Hardware Security Module (HSM) Integration
|
||||
interface HSMConfig {
|
||||
slotId: number;
|
||||
pin: string;
|
||||
modulePath: string;
|
||||
}
|
||||
|
||||
class HSMIntegration {
|
||||
// Für echte HSM-Integration: PKCS#11 Library verwenden
|
||||
// z.B. graphene-pk11, pkcs11js
|
||||
|
||||
async sign(data: Buffer, keyLabel: string): Promise<Buffer> {
|
||||
// HSM signing operation
|
||||
throw new Error('Implement with actual HSM library');
|
||||
}
|
||||
|
||||
async verify(
|
||||
data: Buffer,
|
||||
signature: Buffer,
|
||||
keyLabel: string
|
||||
): Promise<boolean> {
|
||||
// HSM verification
|
||||
throw new Error('Implement with actual HSM library');
|
||||
}
|
||||
|
||||
async generateKeyPair(keyLabel: string): Promise<{ publicKey: string }> {
|
||||
// Generate key pair in HSM (private key never leaves HSM)
|
||||
throw new Error('Implement with actual HSM library');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secure Firmware Updates
|
||||
|
||||
```typescript
|
||||
// lib/firmware-update.ts
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
import { pipeline } from 'stream/promises';
|
||||
|
||||
interface FirmwareMetadata {
|
||||
version: string;
|
||||
releaseDate: string;
|
||||
sha256: string;
|
||||
signature: string;
|
||||
size: number;
|
||||
minVersion: string;
|
||||
deviceModels: string[];
|
||||
}
|
||||
|
||||
class SecureFirmwareUpdater {
|
||||
private signingPublicKey: string;
|
||||
|
||||
constructor(publicKeyPath: string) {
|
||||
this.signingPublicKey = fs.readFileSync(publicKeyPath, 'utf8');
|
||||
}
|
||||
|
||||
// Firmware Signatur verifizieren
|
||||
verifySignature(firmwarePath: string, signature: string): boolean {
|
||||
const firmware = fs.readFileSync(firmwarePath);
|
||||
|
||||
const verify = crypto.createVerify('SHA256');
|
||||
verify.update(firmware);
|
||||
|
||||
return verify.verify(this.signingPublicKey, signature, 'base64');
|
||||
}
|
||||
|
||||
// Firmware Hash verifizieren
|
||||
verifyHash(firmwarePath: string, expectedHash: string): boolean {
|
||||
const firmware = fs.readFileSync(firmwarePath);
|
||||
const hash = crypto.createHash('sha256').update(firmware).digest('hex');
|
||||
|
||||
return hash === expectedHash;
|
||||
}
|
||||
|
||||
// Firmware Download mit Verification
|
||||
async downloadFirmware(
|
||||
url: string,
|
||||
metadata: FirmwareMetadata,
|
||||
targetPath: string
|
||||
): Promise<boolean> {
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Download failed: ${response.status}`);
|
||||
}
|
||||
|
||||
// Streaming Download mit Hash-Berechnung
|
||||
const hash = crypto.createHash('sha256');
|
||||
const fileStream = fs.createWriteStream(targetPath);
|
||||
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) throw new Error('No response body');
|
||||
|
||||
let downloadedSize = 0;
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
|
||||
if (done) break;
|
||||
|
||||
hash.update(value);
|
||||
fileStream.write(value);
|
||||
downloadedSize += value.length;
|
||||
}
|
||||
|
||||
fileStream.end();
|
||||
|
||||
// Size Check
|
||||
if (downloadedSize !== metadata.size) {
|
||||
fs.unlinkSync(targetPath);
|
||||
throw new Error('Size mismatch');
|
||||
}
|
||||
|
||||
// Hash Check
|
||||
const actualHash = hash.digest('hex');
|
||||
if (actualHash !== metadata.sha256) {
|
||||
fs.unlinkSync(targetPath);
|
||||
throw new Error('Hash mismatch');
|
||||
}
|
||||
|
||||
// Signature Check
|
||||
if (!this.verifySignature(targetPath, metadata.signature)) {
|
||||
fs.unlinkSync(targetPath);
|
||||
throw new Error('Signature verification failed');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Version Check
|
||||
shouldUpdate(
|
||||
currentVersion: string,
|
||||
newVersion: string,
|
||||
minVersion: string
|
||||
): boolean {
|
||||
const current = this.parseVersion(currentVersion);
|
||||
const target = this.parseVersion(newVersion);
|
||||
const min = this.parseVersion(minVersion);
|
||||
|
||||
// Current version must be >= minVersion for update
|
||||
if (this.compareVersions(current, min) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only update if target is newer
|
||||
return this.compareVersions(target, current) > 0;
|
||||
}
|
||||
|
||||
private parseVersion(version: string): number[] {
|
||||
return version.split('.').map(Number);
|
||||
}
|
||||
|
||||
private compareVersions(a: number[], b: number[]): number {
|
||||
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
||||
const av = a[i] || 0;
|
||||
const bv = b[i] || 0;
|
||||
if (av > bv) return 1;
|
||||
if (av < bv) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// OTA Update API
|
||||
import express from 'express';
|
||||
|
||||
const firmwareRouter = express.Router();
|
||||
|
||||
// GET /api/firmware/check?model=xxx&version=1.0.0
|
||||
firmwareRouter.get('/check', async (req, res) => {
|
||||
const { model, version } = req.query;
|
||||
|
||||
// Check for available updates
|
||||
const latestFirmware = await getLatestFirmware(model as string);
|
||||
|
||||
if (!latestFirmware) {
|
||||
return res.json({ updateAvailable: false });
|
||||
}
|
||||
|
||||
const updater = new SecureFirmwareUpdater('./keys/firmware-signing.pub');
|
||||
|
||||
const shouldUpdate = updater.shouldUpdate(
|
||||
version as string,
|
||||
latestFirmware.version,
|
||||
latestFirmware.minVersion
|
||||
);
|
||||
|
||||
res.json({
|
||||
updateAvailable: shouldUpdate,
|
||||
...(shouldUpdate && { firmware: latestFirmware })
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Validation & Sanitization
|
||||
|
||||
```typescript
|
||||
// lib/input-validation.ts
|
||||
import { z } from 'zod';
|
||||
|
||||
// Schema für Sensor-Daten
|
||||
const SensorDataSchema = z.object({
|
||||
device_id: z.string()
|
||||
.min(1)
|
||||
.max(64)
|
||||
.regex(/^[a-zA-Z0-9_-]+$/),
|
||||
|
||||
timestamp: z.string()
|
||||
.datetime()
|
||||
.refine(
|
||||
(ts) => new Date(ts) <= new Date(),
|
||||
'Timestamp cannot be in the future'
|
||||
),
|
||||
|
||||
temperature: z.number()
|
||||
.min(-50)
|
||||
.max(100)
|
||||
.optional(),
|
||||
|
||||
humidity: z.number()
|
||||
.min(0)
|
||||
.max(100)
|
||||
.optional(),
|
||||
|
||||
battery: z.number()
|
||||
.min(0)
|
||||
.max(100)
|
||||
.optional()
|
||||
});
|
||||
|
||||
// Schema für Device Commands
|
||||
const DeviceCommandSchema = z.object({
|
||||
action: z.enum(['restart', 'update', 'configure', 'reset']),
|
||||
target: z.string().min(1).max(64),
|
||||
payload: z.record(z.unknown()).optional()
|
||||
}).refine(
|
||||
(data) => {
|
||||
// Dangerous actions require additional validation
|
||||
if (data.action === 'reset') {
|
||||
return data.payload?.confirm === true;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
'Reset action requires confirmation'
|
||||
);
|
||||
|
||||
// Middleware für Input Validation
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
function validateInput(schema: z.ZodType<any>) {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
req.body = schema.parse(req.body);
|
||||
next();
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return res.status(400).json({
|
||||
error: 'Validation failed',
|
||||
details: error.errors
|
||||
});
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Rate Limiting
|
||||
import rateLimit from 'express-rate-limit';
|
||||
|
||||
const deviceRateLimit = rateLimit({
|
||||
windowMs: 60 * 1000, // 1 Minute
|
||||
max: 60, // 60 Requests pro Minute
|
||||
keyGenerator: (req) => req.headers['x-device-id'] as string || req.ip,
|
||||
handler: (req, res) => {
|
||||
res.status(429).json({
|
||||
error: 'Rate limit exceeded',
|
||||
retryAfter: 60
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Monitoring
|
||||
|
||||
```typescript
|
||||
// lib/security-monitoring.ts
|
||||
|
||||
interface SecurityEvent {
|
||||
timestamp: Date;
|
||||
eventType: string;
|
||||
severity: 'low' | 'medium' | 'high' | 'critical';
|
||||
deviceId?: string;
|
||||
sourceIp?: string;
|
||||
details: Record<string, any>;
|
||||
}
|
||||
|
||||
class SecurityMonitor {
|
||||
private events: SecurityEvent[] = [];
|
||||
|
||||
// Authentication Failure
|
||||
logAuthFailure(deviceId: string, reason: string, sourceIp: string): void {
|
||||
this.logEvent({
|
||||
eventType: 'auth_failure',
|
||||
severity: 'medium',
|
||||
deviceId,
|
||||
sourceIp,
|
||||
details: { reason }
|
||||
});
|
||||
|
||||
// Check for brute force
|
||||
this.checkBruteForce(deviceId, sourceIp);
|
||||
}
|
||||
|
||||
// Anomaly Detection
|
||||
logAnomaly(deviceId: string, anomalyType: string, value: any): void {
|
||||
this.logEvent({
|
||||
eventType: 'anomaly',
|
||||
severity: 'medium',
|
||||
deviceId,
|
||||
details: { anomalyType, value }
|
||||
});
|
||||
}
|
||||
|
||||
// Firmware Tampering
|
||||
logTamperAttempt(deviceId: string, details: Record<string, any>): void {
|
||||
this.logEvent({
|
||||
eventType: 'tamper_attempt',
|
||||
severity: 'critical',
|
||||
deviceId,
|
||||
details
|
||||
});
|
||||
|
||||
// Immediate alert
|
||||
this.sendAlert({
|
||||
type: 'tamper_attempt',
|
||||
deviceId,
|
||||
details
|
||||
});
|
||||
}
|
||||
|
||||
private logEvent(event: Omit<SecurityEvent, 'timestamp'>): void {
|
||||
const fullEvent: SecurityEvent = {
|
||||
...event,
|
||||
timestamp: new Date()
|
||||
};
|
||||
|
||||
this.events.push(fullEvent);
|
||||
|
||||
// In production: send to SIEM
|
||||
console.log('Security Event:', JSON.stringify(fullEvent));
|
||||
}
|
||||
|
||||
private checkBruteForce(deviceId: string, sourceIp: string): void {
|
||||
const recentFailures = this.events.filter(e =>
|
||||
e.eventType === 'auth_failure' &&
|
||||
e.timestamp > new Date(Date.now() - 5 * 60 * 1000) &&
|
||||
(e.deviceId === deviceId || e.sourceIp === sourceIp)
|
||||
);
|
||||
|
||||
if (recentFailures.length >= 5) {
|
||||
this.logEvent({
|
||||
eventType: 'brute_force_detected',
|
||||
severity: 'high',
|
||||
deviceId,
|
||||
sourceIp,
|
||||
details: { failureCount: recentFailures.length }
|
||||
});
|
||||
|
||||
// Block IP/Device
|
||||
this.blockSource(sourceIp, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
private blockSource(ip: string, deviceId: string): void {
|
||||
// Implement blocking logic
|
||||
console.log(`Blocking IP: ${ip}, Device: ${deviceId}`);
|
||||
}
|
||||
|
||||
private sendAlert(alert: Record<string, any>): void {
|
||||
// Send to Slack, PagerDuty, etc.
|
||||
console.log('ALERT:', alert);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Checklist
|
||||
|
||||
| Category | Requirement | Priority |
|
||||
|----------|------------|----------|
|
||||
| **Authentication** | Certificate-based device auth | High |
|
||||
| **Authentication** | No default credentials | Critical |
|
||||
| **Encryption** | TLS 1.3 for all communications | High |
|
||||
| **Encryption** | Data at rest encryption | High |
|
||||
| **Firmware** | Signed firmware updates | Critical |
|
||||
| **Firmware** | Secure boot chain | High |
|
||||
| **Network** | Network segmentation | Medium |
|
||||
| **Network** | Firewall rules | High |
|
||||
| **Monitoring** | Security event logging | High |
|
||||
| **Monitoring** | Anomaly detection | Medium |
|
||||
| **Compliance** | Regular security audits | High |
|
||||
|
||||
---
|
||||
|
||||
## Fazit
|
||||
|
||||
IoT Security erfordert:
|
||||
|
||||
1. **Defense in Depth**: Mehrere Sicherheitsebenen
|
||||
2. **Strong Authentication**: Zertifikate statt Passwörter
|
||||
3. **Encryption**: TLS everywhere
|
||||
4. **Secure Updates**: Signierte Firmware
|
||||
|
||||
Sicherheit ist keine Option – sie ist Pflicht.
|
||||
|
||||
---
|
||||
|
||||
## Bildprompts
|
||||
|
||||
1. "IoT security layers diagram, defense in depth concept"
|
||||
2. "Secure device authentication flow, certificate exchange"
|
||||
3. "Security monitoring dashboard with alerts and events"
|
||||
|
||||
---
|
||||
|
||||
## Quellen
|
||||
|
||||
- [IoT Device Security Best Practices 2026](https://www.jaycon.com/iot-device-security-best-practices/)
|
||||
- [ConnectWise IoT Security Guide](https://www.connectwise.com/blog/how-to-secure-iot-devices)
|
||||
- [Fortinet IoT Best Practices](https://www.fortinet.com/resources/cyberglossary/iot-best-practices)
|
||||
- [Azure IoT Security](https://learn.microsoft.com/en-us/azure/iot/iot-overview-security)
|
||||
Reference in New Issue
Block a user