Files
clan-core/nixosModules/user-firewall/README.md
Jörg Thalheim 5d88ac440a add restricted network nixos modules
See README.md for explanation
2025-06-27 18:44:17 +02:00

4.8 KiB

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:

{
  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

{
  networking.user-firewall = {
    exemptUsers = [ "alice" ];  # Users who can access the internet
  };
}

Full Configuration Example

{
  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:

{
  networking.user-firewall = {
    allowedInterfaces = [ "lo" ];  # Only localhost
    exemptUsers = [ ];  # No exempt users
  };
}

2. Corporate Workstations

Force all traffic through corporate VPN:

{
  networking.user-firewall = {
    allowedInterfaces = [ "lo" "wg-corp" ];
    exemptUsers = [ "sysadmin" ];
  };
}

Testing

The module includes comprehensive tests for both iptables and nftables backends:

# 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:

sudo iptables -L user-firewall-output -n -v
sudo ip6tables -L user-firewall-output -n -v

For nftables:

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:

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