@ebowwa/hetzner 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/actions.js +802 -0
- package/actions.ts +1053 -0
- package/auth.js +35 -0
- package/auth.ts +37 -0
- package/bootstrap/FIREWALL.md +326 -0
- package/bootstrap/KERNEL-HARDENING.md +258 -0
- package/bootstrap/SECURITY-INTEGRATION.md +281 -0
- package/bootstrap/TESTING.md +301 -0
- package/bootstrap/cloud-init.js +279 -0
- package/bootstrap/cloud-init.ts +394 -0
- package/bootstrap/firewall.js +279 -0
- package/bootstrap/firewall.ts +342 -0
- package/bootstrap/genesis.js +406 -0
- package/bootstrap/genesis.ts +518 -0
- package/bootstrap/index.js +35 -0
- package/bootstrap/index.ts +71 -0
- package/bootstrap/kernel-hardening.js +266 -0
- package/bootstrap/kernel-hardening.test.ts +230 -0
- package/bootstrap/kernel-hardening.ts +272 -0
- package/bootstrap/security-audit.js +118 -0
- package/bootstrap/security-audit.ts +124 -0
- package/bootstrap/ssh-hardening.js +182 -0
- package/bootstrap/ssh-hardening.ts +192 -0
- package/client.js +137 -0
- package/client.ts +177 -0
- package/config.js +5 -0
- package/config.ts +5 -0
- package/errors.js +270 -0
- package/errors.ts +371 -0
- package/index.js +28 -0
- package/index.ts +55 -0
- package/package.json +56 -0
- package/pricing.js +284 -0
- package/pricing.ts +422 -0
- package/schemas.js +660 -0
- package/schemas.ts +765 -0
- package/server-status.ts +81 -0
- package/servers.js +424 -0
- package/servers.ts +568 -0
- package/ssh-keys.js +90 -0
- package/ssh-keys.ts +122 -0
- package/ssh-setup.ts +218 -0
- package/types.js +96 -0
- package/types.ts +389 -0
- package/volumes.js +172 -0
- package/volumes.ts +229 -0
package/auth.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hetzner authentication utilities
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
export function getTokenFromCLI() {
|
|
8
|
+
try {
|
|
9
|
+
const configPath = join(homedir(), ".config", "hcloud", "cli.toml");
|
|
10
|
+
if (existsSync(configPath)) {
|
|
11
|
+
const config = readFileSync(configPath, "utf-8");
|
|
12
|
+
const match = config.match(/token\s*=\s*["']([^"']+)["']/);
|
|
13
|
+
if (match && match[1]) {
|
|
14
|
+
return match[1];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
// Ignore errors
|
|
20
|
+
}
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
export function isAuthenticated(apiToken) {
|
|
24
|
+
return apiToken.length > 0;
|
|
25
|
+
}
|
|
26
|
+
export function resolveApiToken(explicitToken) {
|
|
27
|
+
if (explicitToken) {
|
|
28
|
+
return explicitToken;
|
|
29
|
+
}
|
|
30
|
+
if (process.env.HETZNER_API_TOKEN) {
|
|
31
|
+
return process.env.HETZNER_API_TOKEN;
|
|
32
|
+
}
|
|
33
|
+
return getTokenFromCLI();
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=auth.js.map
|
package/auth.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hetzner authentication utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
|
|
9
|
+
export function getTokenFromCLI(): string {
|
|
10
|
+
try {
|
|
11
|
+
const configPath = join(homedir(), ".config", "hcloud", "cli.toml");
|
|
12
|
+
if (existsSync(configPath)) {
|
|
13
|
+
const config = readFileSync(configPath, "utf-8");
|
|
14
|
+
const match = config.match(/token\s*=\s*["']([^"']+)["']/);
|
|
15
|
+
if (match && match[1]) {
|
|
16
|
+
return match[1];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
} catch (e) {
|
|
20
|
+
// Ignore errors
|
|
21
|
+
}
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isAuthenticated(apiToken: string): boolean {
|
|
26
|
+
return apiToken.length > 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resolveApiToken(explicitToken?: string): string {
|
|
30
|
+
if (explicitToken) {
|
|
31
|
+
return explicitToken;
|
|
32
|
+
}
|
|
33
|
+
if (process.env.HETZNER_API_TOKEN) {
|
|
34
|
+
return process.env.HETZNER_API_TOKEN;
|
|
35
|
+
}
|
|
36
|
+
return getTokenFromCLI();
|
|
37
|
+
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# UFW Firewall Module
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The UFW (Uncomplicated Firewall) module provides composable cloud-init blocks for securing servers with a stateful firewall. It follows the same pattern as `ssh-hardening.ts` with three main functions:
|
|
6
|
+
|
|
7
|
+
- `ufwFirewallPackages()` → Returns packages for the `packages:` section
|
|
8
|
+
- `ufwFirewallWriteFiles()` → Returns files for the `write_files:` section
|
|
9
|
+
- `ufwFirewallRunCmd()` → Returns commands for the `runcmd:` section
|
|
10
|
+
|
|
11
|
+
## Security Policy
|
|
12
|
+
|
|
13
|
+
### Default Configuration
|
|
14
|
+
- **Incoming**: DENY (whitelist approach)
|
|
15
|
+
- **Outgoing**: ALLOW (stateful - return traffic allowed)
|
|
16
|
+
- **Forwarded**: DENY
|
|
17
|
+
|
|
18
|
+
### Standard Ports
|
|
19
|
+
|
|
20
|
+
| Port | Service | Access | Notes |
|
|
21
|
+
|------|---------|--------|-------|
|
|
22
|
+
| 22 | SSH | Rate-limited | 6 connections per 30 seconds |
|
|
23
|
+
| 80 | HTTP | Optional | Genesis servers only |
|
|
24
|
+
| 443 | HTTPS | Optional | Genesis servers only |
|
|
25
|
+
| 8911 | Node Agent | Workers only | Internal communication |
|
|
26
|
+
| 41641 | Tailscale | Always | VPN functionality |
|
|
27
|
+
|
|
28
|
+
### Kernel Hardening (via sysctl)
|
|
29
|
+
|
|
30
|
+
The module also configures kernel network security parameters:
|
|
31
|
+
|
|
32
|
+
- **IP spoofing protection**: `rp_filter=1`
|
|
33
|
+
- **ICMP redirect protection**: `accept_redirects=0`
|
|
34
|
+
- **SYN cookies**: `tcp_syncookies=1`
|
|
35
|
+
- **Martian packet logging**: `log_martians=1`
|
|
36
|
+
- **Source address verification**: `secure_redirects=1`
|
|
37
|
+
|
|
38
|
+
## Files Created
|
|
39
|
+
|
|
40
|
+
### 1. /etc/ufw/before.rules
|
|
41
|
+
|
|
42
|
+
Stateful firewall rules applied before UFW rules:
|
|
43
|
+
- Allows loopback interface
|
|
44
|
+
- Drops invalid packets
|
|
45
|
+
- Allows established/related connections
|
|
46
|
+
- Allows ICMP messages (required for PMTU discovery)
|
|
47
|
+
- Drops packets with bogus TCP flags (potential scans)
|
|
48
|
+
|
|
49
|
+
### 2. /etc/ufw/sysctl.conf
|
|
50
|
+
|
|
51
|
+
Kernel network security parameters for:
|
|
52
|
+
- IP spoofing protection
|
|
53
|
+
- ICMP redirect protection
|
|
54
|
+
- SYN flood mitigation
|
|
55
|
+
- Martian packet logging
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### Genesis Servers (Control Plane)
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { generateUFWFirewallForGenesis } from "./firewall";
|
|
63
|
+
|
|
64
|
+
const firewall = generateUFWFirewallForGenesis();
|
|
65
|
+
// Returns: { packages, writeFiles, runCmd }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Default configuration:
|
|
69
|
+
- SSH: Rate-limited from anywhere
|
|
70
|
+
- HTTP: Enabled
|
|
71
|
+
- HTTPS: Enabled
|
|
72
|
+
- Node Agent: Disabled
|
|
73
|
+
- Logging: Rate-limited
|
|
74
|
+
|
|
75
|
+
### Worker/Seed Servers
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { generateUFWFirewallForWorker } from "./firewall";
|
|
79
|
+
|
|
80
|
+
const firewall = generateUFWFirewallForWorker();
|
|
81
|
+
// Returns: { packages, writeFiles, runCmd }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Default configuration:
|
|
85
|
+
- SSH: Rate-limited from anywhere
|
|
86
|
+
- HTTP: Disabled
|
|
87
|
+
- HTTPS: Disabled
|
|
88
|
+
- Node Agent: Enabled (port 8911)
|
|
89
|
+
- Logging: Rate-limited
|
|
90
|
+
|
|
91
|
+
### Custom Configuration
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { ufwFirewallPackages, ufwFirewallWriteFiles, ufwFirewallRunCmd } from "./firewall";
|
|
95
|
+
|
|
96
|
+
const options = {
|
|
97
|
+
allowSSHFrom: ['192.168.1.0/24', '10.0.0.0/8'],
|
|
98
|
+
allowHTTP: true,
|
|
99
|
+
allowHTTPS: true,
|
|
100
|
+
allowNodeAgent: true,
|
|
101
|
+
additionalPorts: [
|
|
102
|
+
{ port: 3000, protocol: 'tcp', comment: 'Custom app' }
|
|
103
|
+
],
|
|
104
|
+
verboseLogging: false,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const packages = ufwFirewallPackages();
|
|
108
|
+
const writeFiles = ufwFirewallWriteFiles(options);
|
|
109
|
+
const runCmd = ufwFirewallRunCmd(options);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Integration
|
|
113
|
+
|
|
114
|
+
The firewall module is automatically integrated into:
|
|
115
|
+
|
|
116
|
+
1. **Genesis servers** (`genesis.ts`)
|
|
117
|
+
- Imported and added to bootstrap
|
|
118
|
+
- Runs after SSH hardening (prevents lockout)
|
|
119
|
+
|
|
120
|
+
2. **Worker/Seed servers** (`cloud-init.ts`)
|
|
121
|
+
- Imported and added to bootstrap
|
|
122
|
+
- Runs after SSH hardening (prevents lockout)
|
|
123
|
+
|
|
124
|
+
## Testing Instructions
|
|
125
|
+
|
|
126
|
+
### Local Testing
|
|
127
|
+
|
|
128
|
+
1. **Build the project**:
|
|
129
|
+
```bash
|
|
130
|
+
cd /Users/ebowwa/Desktop/codespaces/packages/com.hetzner.codespaces
|
|
131
|
+
bun run build
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
2. **Generate a test cloud-init**:
|
|
135
|
+
```bash
|
|
136
|
+
# Test Genesis firewall
|
|
137
|
+
bun -e "
|
|
138
|
+
import { generateGenesisBootstrap } from './workspace/src/lib/bootstrap/genesis.js';
|
|
139
|
+
const yaml = generateGenesisBootstrap({
|
|
140
|
+
adminSSHKey: 'ssh-rsa AAAAB3... test@example.com'
|
|
141
|
+
});
|
|
142
|
+
console.log(yaml);
|
|
143
|
+
" > /tmp/genesis-firewall-test.yaml
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
3. **Verify the output**:
|
|
147
|
+
```bash
|
|
148
|
+
grep -A 20 "UFW Firewall" /tmp/genesis-firewall-test.yaml
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Live Testing (Hetzner VPS)
|
|
152
|
+
|
|
153
|
+
**WARNING**: Test on a disposable VPS first!
|
|
154
|
+
|
|
155
|
+
1. Create a test VPS in Hetzner:
|
|
156
|
+
```bash
|
|
157
|
+
# Using the com.hetzner.codespaces UI or API
|
|
158
|
+
Server Type: cx11 (cheapest)
|
|
159
|
+
Location: any
|
|
160
|
+
SSH Key: Your public key
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
2. Add user data with the generated cloud-init:
|
|
164
|
+
```bash
|
|
165
|
+
# Paste the contents of /tmp/genesis-firewall-test.yaml
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
3. After creation, SSH into the server:
|
|
169
|
+
```bash
|
|
170
|
+
ssh root@<server-ip>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
4. Verify UFW status:
|
|
174
|
+
```bash
|
|
175
|
+
sudo ufw status verbose
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Expected output:
|
|
179
|
+
```
|
|
180
|
+
Status: active
|
|
181
|
+
|
|
182
|
+
Logging: on (low)
|
|
183
|
+
Default: deny (incoming), allow (outgoing), disabled (routed)
|
|
184
|
+
New profiles: skip
|
|
185
|
+
|
|
186
|
+
To Action From
|
|
187
|
+
-- ------ ----
|
|
188
|
+
22/tcp LIMIT Anywhere
|
|
189
|
+
80/tcp ALLOW Anywhere
|
|
190
|
+
443/tcp ALLOW Anywhere
|
|
191
|
+
41641/udp ALLOW Anywhere
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
5. Check firewall logs:
|
|
195
|
+
```bash
|
|
196
|
+
sudo tail -f /var/log/ufw.log
|
|
197
|
+
# or
|
|
198
|
+
sudo journalctl -u ufw -f
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
6. Verify kernel parameters:
|
|
202
|
+
```bash
|
|
203
|
+
sysctl net.ipv4.conf.all.rp_filter
|
|
204
|
+
# Should be: net.ipv4.conf.all.rp_filter = 1
|
|
205
|
+
|
|
206
|
+
sysctl net.ipv4.tcp_syncookies
|
|
207
|
+
# Should be: net.ipv4.tcp_syncookies = 1
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
7. Test connectivity:
|
|
211
|
+
```bash
|
|
212
|
+
# SSH should work (rate-limited)
|
|
213
|
+
ssh -v root@localhost
|
|
214
|
+
|
|
215
|
+
# HTTP/HTTPS should work (on Genesis)
|
|
216
|
+
curl -I http://localhost
|
|
217
|
+
curl -I https://localhost
|
|
218
|
+
|
|
219
|
+
# Tailscale should work
|
|
220
|
+
tailscale status
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Testing Rate Limiting
|
|
224
|
+
|
|
225
|
+
Test that SSH rate limiting works:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# From another machine, try multiple SSH connections
|
|
229
|
+
for i in {1..10}; do
|
|
230
|
+
ssh -o ConnectTimeout=2 root@<server-ip> echo "Connection $i" &
|
|
231
|
+
done
|
|
232
|
+
wait
|
|
233
|
+
|
|
234
|
+
# After 6 fast connections, you should be blocked
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Security Considerations
|
|
238
|
+
|
|
239
|
+
### Order Matters
|
|
240
|
+
|
|
241
|
+
The firewall is activated **after** SSH hardening to prevent lockout:
|
|
242
|
+
|
|
243
|
+
1. Install UFW package
|
|
244
|
+
2. Write configuration files
|
|
245
|
+
3. **SSH hardening** (reload sshd, start fail2ban)
|
|
246
|
+
4. **UFW activation** (configure rules, enable)
|
|
247
|
+
|
|
248
|
+
### Logging
|
|
249
|
+
|
|
250
|
+
Default: Rate-limited logging (`ufw logging low`)
|
|
251
|
+
- Prevents log flooding from constant scanning
|
|
252
|
+
- Still logs blocked packets and policy violations
|
|
253
|
+
|
|
254
|
+
Verbose: High logging (`ufw logging high`)
|
|
255
|
+
- Use only for debugging
|
|
256
|
+
- Can generate large logs on public IPs
|
|
257
|
+
|
|
258
|
+
### Fail2ban Integration
|
|
259
|
+
|
|
260
|
+
UFW works alongside fail2ban:
|
|
261
|
+
- fail2ban monitors logs and bans IP addresses
|
|
262
|
+
- UFW provides the firewall backend (nftables on Ubuntu 24.04)
|
|
263
|
+
- Both provide defense-in-depth
|
|
264
|
+
|
|
265
|
+
## Troubleshooting
|
|
266
|
+
|
|
267
|
+
### Locked Out
|
|
268
|
+
|
|
269
|
+
If you get locked out:
|
|
270
|
+
|
|
271
|
+
1. Use the Hetzner console (VNC/keyboard)
|
|
272
|
+
2. Disable UFW:
|
|
273
|
+
```bash
|
|
274
|
+
sudo ufw disable
|
|
275
|
+
```
|
|
276
|
+
3. Check rules:
|
|
277
|
+
```bash
|
|
278
|
+
sudo ufw status numbered
|
|
279
|
+
```
|
|
280
|
+
4. Re-enable with correct rules:
|
|
281
|
+
```bash
|
|
282
|
+
sudo ufw --force enable
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Rule Conflicts
|
|
286
|
+
|
|
287
|
+
If rules don't apply:
|
|
288
|
+
|
|
289
|
+
1. Check for conflicting rules:
|
|
290
|
+
```bash
|
|
291
|
+
sudo ufw show added
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
2. Reset and reapply:
|
|
295
|
+
```bash
|
|
296
|
+
sudo ufw --force reset
|
|
297
|
+
sudo ufw allow 22/tcp
|
|
298
|
+
sudo ufw enable
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Logs Not Appearing
|
|
302
|
+
|
|
303
|
+
If logs don't appear:
|
|
304
|
+
|
|
305
|
+
1. Check logging is enabled:
|
|
306
|
+
```bash
|
|
307
|
+
sudo ufw status verbose
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
2. Check rsyslog configuration:
|
|
311
|
+
```bash
|
|
312
|
+
sudo tail -f /var/log/syslog | grep UFW
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## References
|
|
316
|
+
|
|
317
|
+
- [UFW Community Documentation](https://help.ubuntu.com/community/UFW)
|
|
318
|
+
- [UFW Man Page](https://manpages.ubuntu.com/manpages/noble/man8/ufw.8.html)
|
|
319
|
+
- [iptables-extensions](https://manpages.debian.org/testing/iptables-extensions/iptables-extensions.html)
|
|
320
|
+
- [Kernel Sysctl Parameters](https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt)
|
|
321
|
+
|
|
322
|
+
## Sources
|
|
323
|
+
|
|
324
|
+
- DigitalOcean - UFW Essentials Guide (Jul 31, 2025)
|
|
325
|
+
- LinuxSecurity - Ubuntu server SSH firewall rules (Jan 9, 2026)
|
|
326
|
+
- Ubuntu Community Wiki - Official UFW documentation
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Kernel Hardening Module
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The kernel hardening module provides comprehensive Linux kernel security hardening for cloud-init bootstrap. It implements 2026 best practices aligned with CIS Benchmarks and NIST guidelines.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
The module follows the same composable pattern as other bootstrap modules:
|
|
10
|
+
|
|
11
|
+
- **`kernelHardeningPackages()`** → Returns packages array (currently empty)
|
|
12
|
+
- **`kernelHardeningWriteFiles()`** → Returns write_files YAML lines
|
|
13
|
+
- **`kernelHardeningRunCmd()`** → Returns runcmd YAML lines
|
|
14
|
+
|
|
15
|
+
## Security Measures
|
|
16
|
+
|
|
17
|
+
### 1. IP Spoofing Protection
|
|
18
|
+
```conf
|
|
19
|
+
net.ipv4.conf.all.rp_filter = 1 # Reverse path filtering
|
|
20
|
+
net.ipv4.conf.all.log_martians = 1 # Log impossible addresses
|
|
21
|
+
net.ipv4.conf.all.accept_redirects = 0 # Block ICMP redirects
|
|
22
|
+
net.ipv4.conf.all.secure_redirects = 0 # Block secure redirects
|
|
23
|
+
net.ipv4.conf.all.send_redirects = 0 # Don't send redirects
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. SYN Flood Protection
|
|
27
|
+
```conf
|
|
28
|
+
net.ipv4.tcp_syncookies = 1 # Enable SYN cookies
|
|
29
|
+
net.ipv4.tcp_tw_reuse = 1 # Reuse TIME_WAIT sockets
|
|
30
|
+
net.ipv4.tcp_max_syn_backlog = 2048 # Increase SYN backlog
|
|
31
|
+
net.ipv4.tcp_synack_retries = 2 # Reduce SYNACK retries
|
|
32
|
+
net.ipv4.tcp_syn_retries = 5 # Reduce SYN retries
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. Network Stack Hardening
|
|
36
|
+
```conf
|
|
37
|
+
net.ipv4.icmp_echo_ignore_broadcasts = 1 # Block broadcast pings
|
|
38
|
+
net.ipv4.icmp_ignore_bogus_error_responses = 1 # Block bogus ICMP
|
|
39
|
+
net.ipv4.tcp_timestamps = 1 # Enable TCP timestamps
|
|
40
|
+
net.ipv4.tcp_sack = 1 # Enable selective ACK
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 4. Core Dump Restrictions
|
|
44
|
+
```conf
|
|
45
|
+
fs.suid_dumpable = 0 # Disable setuid core dumps
|
|
46
|
+
kernel.core_pattern = |/bin/false # Disable core dumps
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 5. Memory Protection (ASLR)
|
|
50
|
+
```conf
|
|
51
|
+
kernel.randomize_va_space = 2 # Full ASLR
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 6. Filesystem Protection
|
|
55
|
+
```conf
|
|
56
|
+
fs.protected_hardlinks = 1 # Prevent hard link attacks
|
|
57
|
+
fs.protected_symlinks = 1 # Prevent symlink attacks
|
|
58
|
+
fs.protected_fifos = 2 # Prevent FIFO attacks
|
|
59
|
+
fs.protected_regular = 2 # Prevent file overwrite
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 7. Security-Related Parameters
|
|
63
|
+
```conf
|
|
64
|
+
kernel.sysrq = 0 # Disable magic sysrq
|
|
65
|
+
kernel.kexec_load = 0 # Disable kexec
|
|
66
|
+
user.max_user_namespaces = 0 # Disable user namespaces
|
|
67
|
+
kernel.unprivileged_bpf_disabled = 1 # Disable unprivileged BPF
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 8. Additional Hardening (2026)
|
|
71
|
+
```conf
|
|
72
|
+
kernel.dmesg_restrict = 1 # Restrict dmesg
|
|
73
|
+
kernel.yama.ptrace_scope = 2 # Restrict ptrace
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Integration
|
|
77
|
+
|
|
78
|
+
### Cloud-Init Integration
|
|
79
|
+
|
|
80
|
+
The module is integrated into both seed and Genesis bootstrap:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import {
|
|
84
|
+
kernelHardeningPackages,
|
|
85
|
+
kernelHardeningWriteFiles,
|
|
86
|
+
kernelHardeningRunCmd,
|
|
87
|
+
} from "./kernel-hardening";
|
|
88
|
+
|
|
89
|
+
// In cloud-init.ts
|
|
90
|
+
lines.push(...kernelHardeningPackages());
|
|
91
|
+
lines.push(...kernelHardeningWriteFiles());
|
|
92
|
+
lines.push(...kernelHardeningRunCmd());
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Bootstrap Order
|
|
96
|
+
|
|
97
|
+
Security modules are applied in this order:
|
|
98
|
+
|
|
99
|
+
1. **UFW Firewall** - Network-level defense
|
|
100
|
+
2. **Kernel Hardening** - System-level hardening
|
|
101
|
+
3. **SSH Hardening** - Service-level hardening
|
|
102
|
+
4. **Security Audit** - Verification and reporting
|
|
103
|
+
|
|
104
|
+
## File Persistence
|
|
105
|
+
|
|
106
|
+
All settings are written to `/etc/sysctl.d/99-security-hardening.conf`:
|
|
107
|
+
|
|
108
|
+
- **Persists across reboots** - Files in `/etc/sysctl.d/` are loaded on boot
|
|
109
|
+
- **Takes precedence** - The `99-` prefix ensures it overrides `/etc/sysctl.conf`
|
|
110
|
+
- **Applied immediately** - `sysctl --system` activates settings without reboot
|
|
111
|
+
|
|
112
|
+
## Testing
|
|
113
|
+
|
|
114
|
+
Run tests with `bun test`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
cd /Users/ebowwa/Desktop/codespaces/packages/com.hetzner.codespaces/workspace
|
|
118
|
+
bun test src/lib/bootstrap/kernel-hardening.test.ts
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Test Coverage
|
|
122
|
+
|
|
123
|
+
- ✅ Package array validation
|
|
124
|
+
- ✅ Sysctl configuration completeness
|
|
125
|
+
- ✅ All security categories present
|
|
126
|
+
- ✅ Activation commands
|
|
127
|
+
- ✅ Verification commands
|
|
128
|
+
- ✅ CIS Benchmark compliance
|
|
129
|
+
- ✅ 2026 best practices
|
|
130
|
+
- ✅ Documentation headers
|
|
131
|
+
|
|
132
|
+
## Verification
|
|
133
|
+
|
|
134
|
+
### Manual Verification
|
|
135
|
+
|
|
136
|
+
After bootstrap, verify settings are applied:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Check IP spoofing protection
|
|
140
|
+
sysctl net.ipv4.conf.all.rp_filter
|
|
141
|
+
|
|
142
|
+
# Check SYN cookies
|
|
143
|
+
sysctl net.ipv4.tcp_syncookies
|
|
144
|
+
|
|
145
|
+
# Check ASLR
|
|
146
|
+
sysctl kernel.randomize_va_space
|
|
147
|
+
|
|
148
|
+
# Check core dumps
|
|
149
|
+
sysctl fs.suid_dumpable
|
|
150
|
+
|
|
151
|
+
# Check filesystem protection
|
|
152
|
+
sysctl fs.protected_hardlinks
|
|
153
|
+
sysctl fs.protected_symlinks
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Automated Verification
|
|
157
|
+
|
|
158
|
+
The module includes automated verification in `runcmd`:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# View applied settings
|
|
162
|
+
cat /var/log/kernel-hardening.log
|
|
163
|
+
|
|
164
|
+
# Check cloud-init output
|
|
165
|
+
grep "Kernel Hardening Applied" /var/log/cloud-init-output.log
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Compliance
|
|
169
|
+
|
|
170
|
+
### CIS Benchmark for Ubuntu Linux 24.04
|
|
171
|
+
|
|
172
|
+
The module implements the following CIS controls:
|
|
173
|
+
|
|
174
|
+
- **1.5.1** - Restrict core dumps
|
|
175
|
+
- **1.5.2** - Enable ASLR
|
|
176
|
+
- **1.5.4** - Restrict core dump backtraces
|
|
177
|
+
- **3.3.1** - Disable IP forwarding (optional)
|
|
178
|
+
- **3.3.2** - Disable send redirects
|
|
179
|
+
- **3.3.3** - Disable ICMP redirects
|
|
180
|
+
- **3.3.4** - Disable secure ICMP redirects
|
|
181
|
+
- **3.3.5** - Log suspicious packets
|
|
182
|
+
- **3.3.6** - Ignore broadcast ICMP
|
|
183
|
+
- **3.3.7** - Ignore bogus ICMP
|
|
184
|
+
- **3.3.8** - Enable reverse path filtering
|
|
185
|
+
- **3.3.9** - Enable TCP SYN cookies
|
|
186
|
+
|
|
187
|
+
### NIST SP 800-53 Revision 5
|
|
188
|
+
|
|
189
|
+
The module addresses the following NIST controls:
|
|
190
|
+
|
|
191
|
+
- **SC-7** - Boundary Protection
|
|
192
|
+
- **SC-8** - Transmission Confidentiality
|
|
193
|
+
- **SC-39** - Process Isolation
|
|
194
|
+
- **SI-3** - Malicious Code Protection
|
|
195
|
+
- **SI-4** - System Monitoring
|
|
196
|
+
|
|
197
|
+
## References
|
|
198
|
+
|
|
199
|
+
- [CIS Benchmark for Ubuntu Linux 24.04](https://www.cisecurity.org/benchmark/ubuntu_linux)
|
|
200
|
+
- [NIST SP 800-53 Revision 5](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final)
|
|
201
|
+
- [Kernel sysctl documentation](https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt)
|
|
202
|
+
- [Ubuntu Security Guide](https://ubuntu.com/server/docs/security)
|
|
203
|
+
|
|
204
|
+
## Troubleshooting
|
|
205
|
+
|
|
206
|
+
### Settings Not Applied
|
|
207
|
+
|
|
208
|
+
If settings don't appear active:
|
|
209
|
+
|
|
210
|
+
1. Check if sysctl service is running:
|
|
211
|
+
```bash
|
|
212
|
+
systemctl status systemd-sysctl.service
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
2. Manually apply settings:
|
|
216
|
+
```bash
|
|
217
|
+
sysctl --system
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
3. Check for conflicting settings:
|
|
221
|
+
```bash
|
|
222
|
+
sysctl -a | grep -E '(rp_filter|syncookies)'
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Performance Impact
|
|
226
|
+
|
|
227
|
+
Some settings may impact performance:
|
|
228
|
+
|
|
229
|
+
- **SYN cookies** - Slight TCP performance impact
|
|
230
|
+
- **ASLR** - Minimal performance impact
|
|
231
|
+
- **Protected hardlinks** - Minimal filesystem overhead
|
|
232
|
+
|
|
233
|
+
Monitor performance after hardening:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Check network performance
|
|
237
|
+
iperf3 -c <server>
|
|
238
|
+
|
|
239
|
+
# Check filesystem performance
|
|
240
|
+
dd if=/dev/zero of=/tmp/test bs=1M count=1024
|
|
241
|
+
|
|
242
|
+
# Check system load
|
|
243
|
+
uptime
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Files Created
|
|
247
|
+
|
|
248
|
+
- `/etc/sysctl.d/99-security-hardening.conf` - Sysctl configuration
|
|
249
|
+
- `/var/log/kernel-hardening.log` - Applied settings log
|
|
250
|
+
|
|
251
|
+
## Next Steps
|
|
252
|
+
|
|
253
|
+
After kernel hardening, consider:
|
|
254
|
+
|
|
255
|
+
1. **Firewall** - Use UFW for network-level filtering
|
|
256
|
+
2. **SSH hardening** - Secure SSH service configuration
|
|
257
|
+
3. **Security audit** - Run Lynis for compliance scanning
|
|
258
|
+
4. **System hardening** - Apply user space security measures
|