180 lines
4.8 KiB
Markdown
180 lines
4.8 KiB
Markdown
# User Firewall Module
|
|
|
|
This NixOS module provides network access restrictions for non-privileged users, ensuring they can only access local services and VPN interfaces while blocking direct internet access.
|
|
|
|
## Overview
|
|
|
|
The `user-firewall` module implements firewall rules that:
|
|
- Block all outbound network traffic for normal (non-system) users by default
|
|
- Allow specific users to bypass restrictions (exemptUsers)
|
|
- Permit traffic on specific interfaces (like VPNs and localhost)
|
|
- Support both iptables and nftables backends
|
|
- Handle both IPv4 and IPv6 traffic
|
|
|
|
## Installation
|
|
|
|
Add the module to your NixOS configuration:
|
|
|
|
```nix
|
|
{
|
|
imports = [
|
|
self.inputs.clan-core.nixosModules.user-firewall
|
|
];
|
|
}
|
|
```
|
|
|
|
The module is automatically enabled once imported. It will immediately start restricting network access for all normal users except those listed in `exemptUsers`.
|
|
|
|
## Configuration
|
|
|
|
### Basic Usage
|
|
|
|
```nix
|
|
{
|
|
networking.user-firewall = {
|
|
exemptUsers = [ "alice" ]; # Users who can access the internet
|
|
};
|
|
}
|
|
```
|
|
|
|
### Full Configuration Example
|
|
|
|
```nix
|
|
{
|
|
networking.user-firewall = {
|
|
# Users who are exempt from network restrictions
|
|
exemptUsers = [
|
|
"alice"
|
|
"admin"
|
|
];
|
|
|
|
# Network interfaces that all users can use
|
|
# Default includes common VPN interfaces
|
|
allowedInterfaces = [
|
|
"lo" # localhost (required for local services)
|
|
"tun*" # OpenVPN, OpenConnect
|
|
"wg*" # WireGuard (wg0, wg-home, etc.)
|
|
"tailscale*" # Tailscale
|
|
# Add custom interfaces as needed
|
|
];
|
|
};
|
|
}
|
|
```
|
|
|
|
## How It Works
|
|
|
|
1. **User Classification**: The module automatically identifies all normal users (non-system users) and applies restrictions to those not in the `exemptUsers` list.
|
|
|
|
2. **Firewall Rules**:
|
|
- For iptables: Creates a custom chain `user-firewall-output` in the OUTPUT table
|
|
- For nftables: Creates a table `inet user-firewall` with an output chain
|
|
- Rules check outgoing packets and reject those from restricted users
|
|
|
|
3. **Interface Patterns**: Supports wildcards in interface names:
|
|
- `*` matches any characters (e.g., `wg*` matches `wg0`, `wg-home`)
|
|
|
|
## Default Allowed Interfaces
|
|
|
|
The module comes with sensible defaults for common VPN and overlay network interfaces:
|
|
|
|
- `lo` - Loopback (localhost access)
|
|
- `tun*` - OpenVPN, OpenConnect
|
|
- `tap*` - OpenVPN (bridged mode)
|
|
- `wg*` - WireGuard
|
|
- `tailscale*` - Tailscale
|
|
- `zt*` - ZeroTier
|
|
- `hyprspace` - Hyprpspace
|
|
- `vpn*` - Generic VPN interfaces
|
|
- `nebula*` - Nebula mesh network
|
|
- `tinc*` - Tinc VPN
|
|
- `edge*` - n2n
|
|
- `ham0` - Hamachi
|
|
- `easytier` - EasyTier
|
|
- `mycelium` - Mycelium
|
|
|
|
## Use Cases
|
|
|
|
### 1. Public Kiosk Systems
|
|
Restrict users to only access local services:
|
|
```nix
|
|
{
|
|
networking.user-firewall = {
|
|
allowedInterfaces = [ "lo" ]; # Only localhost
|
|
exemptUsers = [ ]; # No exempt users
|
|
};
|
|
}
|
|
```
|
|
|
|
### 2. Corporate Workstations
|
|
Force all traffic through corporate VPN:
|
|
```nix
|
|
{
|
|
networking.user-firewall = {
|
|
allowedInterfaces = [ "lo" "wg-corp" ];
|
|
exemptUsers = [ "sysadmin" ];
|
|
};
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
The module includes comprehensive tests for both iptables and nftables backends:
|
|
|
|
```bash
|
|
# Run iptables backend test
|
|
nix build .#checks.x86_64-linux.user-firewall-iptables
|
|
|
|
# Run nftables backend test
|
|
nix build .#checks.x86_64-linux.user-firewall-nftables
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Check Active Rules
|
|
|
|
The output includes package counters for each firewall rule, that can help to debug connectivity issues.
|
|
|
|
For iptables:
|
|
```bash
|
|
sudo iptables -L user-firewall-output -n -v
|
|
sudo ip6tables -L user-firewall-output -n -v
|
|
```
|
|
|
|
For nftables:
|
|
```bash
|
|
sudo nft list table inet user-firewall
|
|
|
|
# Watch counters in real-time
|
|
sudo watch -n1 'nft list table inet user-firewall'
|
|
```
|
|
|
|
Check which rule your VPN traffic is hitting. If packets are being rejected, verify:
|
|
1. Your VPN interface name matches the patterns in `allowedInterfaces`
|
|
2. Your user is listed in `exemptUsers` if needed
|
|
|
|
To see your current network interfaces:
|
|
```bash
|
|
ip link show | grep -E '^[0-9]+:'
|
|
```
|
|
|
|
### Common Issues
|
|
|
|
1. **Service Connection Failures**: If local services fail to connect, ensure `lo` is in `allowedInterfaces`.
|
|
|
|
2. **VPN Not Working**: Check that your VPN interface name matches the patterns in `allowedInterfaces`. You can find your interface name with `ip link show`.
|
|
|
|
3. **User Still Has Access**: Verify the user is a normal user (not a system user) and not in `exemptUsers`.
|
|
|
|
## Security Considerations
|
|
|
|
- This module provides defense in depth but should not be the only security measure
|
|
- System users (like `nginx`, `systemd-*`) are not restricted
|
|
- Root user always has full network access
|
|
- Restrictions apply at the packet filter level, not application level
|
|
|
|
## Limitations
|
|
|
|
- Requires `networking.firewall.enable = true`
|
|
- Cannot restrict system users or root
|
|
- Interface patterns are evaluated at rule creation time, not dynamically
|