Automating Network Security: Dynamic Firewall Rules & VPN Access with Home Assistant and pfSense/OPNsense

Represent Automating Network Security: Dynamic Firewall Rules & VPN Access with Home Assistant and pfSense/OPNsense article
7m read

The Static Firewall Problem in a Dynamic Smart Home

In a world where smart devices constantly connect and disconnect, guest networks fluctuate, and security needs shift based on occupancy, a static firewall is often a bottleneck. Manually enabling or disabling rules, toggling VPNs, or adjusting network policies is tedious, error-prone, and reactive. For tech enthusiasts, DIY makers, and integrators, the goal is a truly proactive and adaptive smart home. Imagine a scenario where your guest network's internet access automatically suspends when no guests are detected, or your security camera's external access tightens when you're home, and expands when you're away. This level of dynamic control, typically found in enterprise environments, is entirely achievable in your Home Assistant-powered smart home using powerful open-source firewalls like pfSense or OPNsense.

This guide will walk you through integrating Home Assistant with your pfSense or OPNsense router/firewall to build dynamic network security policies. We'll focus on practical, actionable steps using REST APIs and Home Assistant's robust automation engine, transforming your network from a static gatekeeper into an intelligent, context-aware guardian.

Step-by-Step Setup: Integrating Home Assistant with OPNsense (via configd API)

While pfSense offers XMLRPC, OPNsense provides a more straightforward RESTful configd API, making it an excellent starting point for direct Home Assistant integration. We'll outline the OPNsense approach and briefly discuss pfSense alternatives.

1. Enable OPNsense API Access and Generate API Keys

First, you need to enable the OPNsense API and generate keys for Home Assistant to authenticate.

  1. Log into your OPNsense Web GUI.
  2. Navigate to System > Access > Users.
  3. Edit an existing user or create a new user specifically for API access (recommended for security).
  4. Under the user's settings, scroll down to API Keys and click the + button to generate new API keys (Key and Secret). Copy these immediately, as the Secret won't be shown again.
  5. Ensure the user has sufficient permissions. For firewall rule management, typically the following access is needed:
    • system:group:read
    • firewall:alias:read, firewall:alias:write
    • firewall:filter:read, firewall:filter:write
    • firewall:filter:apply (crucial for applying changes)
    Start with minimal permissions and add more as needed.
  6. Save the user settings.

Screenshot Placeholder: OPNsense API Key Generation Screen

2. Configure Home Assistant Secrets for API Keys

Store your OPNsense API Key and Secret securely in Home Assistant's secrets.yaml.

# secrets.yaml
opnsense_api_key: "YOUR_OPNSENSE_API_KEY"
opnsense_api_secret: "YOUR_OPNSENSE_API_SECRET"
opnsense_host: "YOUR_OPNSENSE_IP_OR_HOSTNAME" # e.g., 192.168.1.1

3. Define Home Assistant RESTful Commands for OPNsense

Now, create rest_command entries in your Home Assistant configuration.yaml (or a dedicated package file) to interact with the OPNsense API. We'll use the firewall.filter.toggleRule endpoint as an example, which allows enabling or disabling a specific firewall rule by its UUID.

# configuration.yaml or packages/opnsense_commands.yaml
rest_command:
  opnsense_toggle_firewall_rule:
    url: "https://{{ states('sensor.opnsense_host') }}/api/firewall/filter/toggleRule"
    method: POST
    verify_ssl: true # Set to false if you have self-signed certs and don't want to verify
    payload: '{"uuid": "{{ rule_uuid }}", "enabled": {{ "true" if enable else "false" }} }'
    headers:
      accept: "application/json"
      Content-Type: "application/json"
    authentication:
      username: !secret opnsense_api_key
      password: !secret opnsense_api_secret

  # Example for applying firewall changes (essential after toggling rules)
  opnsense_apply_firewall_changes:
    url: "https://{{ states('sensor.opnsense_host') }}/api/firewall/filter/apply"
    method: POST
    verify_ssl: true
    headers:
      accept: "application/json"
      Content-Type: "application/json"
    authentication:
      username: !secret opnsense_api_key
      password: !secret opnsense_api_secret

# Helper sensor for OPNsense host (can be hardcoded or dynamic)
sensor:
  - platform: template
    sensors:
      opnsense_host:
        value_template: "{{ states('sensor.opnsense_host_secret') | default('192.168.1.1') }}" # Or use !secret opnsense_host directly

Note: To find a rule's UUID in OPNsense, inspect the network requests when you toggle a rule manually in the GUI, or use the firewall.filter.searchRule API endpoint.

4. Create Home Assistant Automation

Now, let's create an automation to enable/disable a specific firewall rule based on a Home Assistant input boolean (e.g., for guest network control).

# automations.yaml
- alias: "Toggle Guest Network Internet Access"
  trigger:
    - platform: state
      entity_id: input_boolean.guest_network_internet_access
  action:
    - service: rest_command.opnsense_toggle_firewall_rule
      data_template:
        rule_uuid: "YOUR_GUEST_NETWORK_FIREWALL_RULE_UUID" # Replace with actual UUID
        enable: "{{ is_state('input_boolean.guest_network_internet_access', 'on') }}"
    - service: rest_command.opnsense_apply_firewall_changes # Crucial: apply changes after toggling

Remember to create input_boolean.guest_network_internet_access in your configuration.yaml or via the UI.

Troubleshooting Section

Integrating with network appliances can be finicky. Here are common issues and their solutions:

  • API Key/Authentication Errors: Double-check your API Key and Secret in secrets.yaml. Ensure the OPNsense user has the necessary permissions (firewall:filter:write, firewall:filter:apply, etc.).
  • SSL Verification Errors: If you're using a self-signed certificate on OPNsense, Home Assistant might fail SSL verification. Set verify_ssl: false in your rest_command definition (use with caution, as it bypasses security checks). A better approach is to add your OPNsense CA certificate to Home Assistant's trusted certificates.
  • Firewall on Router Blocking Home Assistant: Ensure there's a firewall rule on OPNsense/pfSense itself that allows Home Assistant (or its specific IP) to access the OPNsense web GUI and API port (usually 443 or 80).
  • Rule Not Toggling/Applying: Verify the rule_uuid is correct. Remember that after toggling a rule, you must call the firewall.filter.apply (or equivalent) endpoint to make the changes active.
  • Command Syntax Errors: Review the payload format carefully. The OPNsense API expects specific JSON structures. Use OPNsense's API documentation for specific endpoints.
  • Network Connectivity: Confirm Home Assistant can reach your OPNsense host. Try a manual curl command from the Home Assistant host to your OPNsense API endpoint to debug.
# Example cURL command from Home Assistant OS terminal for OPNsense API
curl -k -u "YOUR_API_KEY:YOUR_API_SECRET" -X POST -H "Content-Type: application/json" \
     -d '{"uuid": "YOUR_RULE_UUID", "enabled": true}' \
     https://YOUR_OPNSENSE_IP/api/firewall/filter/toggleRule

Advanced Configuration and Optimization

Beyond simple rule toggling, the OPNsense/pfSense integration opens doors to sophisticated network automation.

1. Dynamic Firewall Aliases

Instead of toggling individual rules, consider using firewall aliases. You can use API calls to add or remove IP addresses from an alias, and then have your firewall rules reference these aliases. This is ideal for managing temporary access for devices, or blocking known malicious IPs.

Example OPNsense Alias API call (add IP):

# rest_command to add an IP to an OPNsense firewall alias
  opnsense_add_to_alias:
    url: "https://{{ states('sensor.opnsense_host') }}/api/firewall/alias/add"
    method: POST
    verify_ssl: true
    payload: '{"name": "{{ alias_name }}", "content": "{{ ip_address }}" }'
    headers:
      accept: "application/json"
      Content-Type: "application/json"
    authentication:
      username: !secret opnsense_api_key
      password: !secret opnsense_api_secret

Remember to call firewall.alias.apply after modifying aliases and firewall.filter.apply if alias changes impact rules.

2. Conditional VPN Tunnel Activation

Automate the activation or deactivation of client VPN connections based on Home Assistant state. For instance, if you start streaming geo-restricted content from a specific device (detected via media player state), Home Assistant could activate a VPN client connection on your router for that device's traffic.

3. Guest Network Isolation and Time-Based Access

Combine Home Assistant's presence detection with OPNsense firewall rules to isolate guest devices. When guests are present, enable specific rules allowing internet access; when they leave, revert to a highly restricted state. You can also implement time-based restrictions for kids' devices.

4. Quality of Service (QoS) and Traffic Shaping

While more complex, you can leverage OPNsense's traffic shaping capabilities via the API. Prioritize network traffic for security cameras when a motion sensor triggers, or ensure smooth video conferencing when a work-from-home sensor is active.

pfSense Integration Alternatives

For pfSense users, direct REST API is less common. You'll typically use:

  • XMLRPC Sync: A more complex method often used for HA clusters, but can be adapted for automation.
  • SSH shell_command: Use Home Assistant's shell_command to SSH into pfSense and execute pfctl commands or other CLI scripts. This requires SSH keys for passwordless authentication and careful scripting.
# Example for pfSense via shell_command (requires SSH setup)
shell_command:
  pfsense_disable_guest_rule:
    '/usr/bin/ssh -i /config/ssh_keys/pfsense_id_rsa -o StrictHostKeyChecking=no admin@{{ states('sensor.pfsense_host') }} "pfctl -k YOUR_GUEST_RULE_NUMBER"'
  pfsense_enable_guest_rule:
    '/usr/bin/ssh -i /config/ssh_keys/pfsense_id_rsa -o StrictHostKeyChecking=no admin@{{ states('sensor.pfsense_host') }} "pfctl -E YOUR_GUEST_RULE_NUMBER"'

This approach requires setting up SSH keys on your Home Assistant host and ensuring the admin user (or a dedicated user) has SSH access and the necessary permissions on pfSense.

Real-World Example: Proactive Security Perimeter

Let's build a practical example: a proactive security perimeter that tightens external access to sensitive services (like SSH, NAS, or specific camera streams) when you're away and loosens it (or keeps it internal-only) when you're home.

Scenario:

You have a firewall rule in OPNsense that allows external SSH access to your home server (for maintenance). You also have Home Assistant presence detection (e.g., via mobile app, router scanning, or Unifi integration).

Implementation:

  1. OPNsense Firewall Rule: Create a rule on your WAN interface to allow SSH (port 22) from a specific source (e.g., your work IP, or a 'trusted' alias) to your home server. Give this rule a clear description and note its UUID.
  2. Home Assistant Input Boolean: Create an input_boolean named input_boolean.allow_external_ssh.
  3. Automation for Presence:
# automations.yaml
- alias: "Set External SSH Access Based on Home Presence"
  trigger:
    - platform: state
      entity_id: group.all_occupants # Assuming you have a group for home occupants
      to: "not_home" # When everyone leaves
    - platform: state
      entity_id: group.all_occupants
      to: "home" # When someone arrives
  action:
    - choose:
        - conditions: "{{ is_state('group.all_occupants', 'not_home') }}"
          sequence:
            - service: input_boolean.turn_on
              entity_id: input_boolean.allow_external_ssh # Enable external access when away
        - conditions: "{{ is_state('group.all_occupants', 'home') }}"
          sequence:
            - service: input_boolean.turn_off
              entity_id: input_boolean.allow_external_ssh # Disable external access when home

- alias: "Toggle OPNsense SSH Firewall Rule"
  trigger:
    - platform: state
      entity_id: input_boolean.allow_external_ssh
  action:
    - service: rest_command.opnsense_toggle_firewall_rule
      data_template:
        rule_uuid: "YOUR_SSH_WAN_RULE_UUID" # Replace with the actual UUID of your SSH WAN rule
        enable: "{{ is_state('input_boolean.allow_external_ssh', 'on') }}"
    - service: rest_command.opnsense_apply_firewall_changes

This setup automatically enables the external SSH access rule when everyone leaves home and disables it when someone returns, significantly reducing your attack surface.

Best Practices and Wrap-up

Integrating Home Assistant with your network firewall is a powerful step towards a truly intelligent and secure smart home. To ensure stability and security, adhere to these best practices:

  • Least Privilege: Create a dedicated OPNsense/pfSense API user with the absolute minimum permissions required for Home Assistant's operations. Do not use the root or admin user for API calls.
  • Secure Secrets: Always store API keys and sensitive information in Home Assistant's secrets.yaml.
  • Thorough Testing: Before deploying any automation to production, test firewall rule changes extensively in a controlled environment. Misconfigured firewall rules can easily lock you out of your network.
  • Router Configuration Backups: Regularly back up your pfSense/OPNsense configuration. This is critical for quick recovery in case of accidental misconfiguration or hardware failure.
  • Logging and Monitoring: Monitor your OPNsense/pfSense firewall logs to ensure that rules are being applied correctly and that your automations are having the intended effect. Home Assistant's own logs can also help diagnose issues with rest_command calls.
  • Idempotency: Design your automations so that running them multiple times yields the same result. For instance, if an automation enables a rule, it should not break if the rule is already enabled.
  • HTTPS and SSL Verification: Always use HTTPS for API calls. Verify SSL certificates (verify_ssl: true) to prevent man-in-the-middle attacks. If using self-signed certs, consider adding the CA to Home Assistant's trust store rather than disabling verification.

By leveraging the power of Home Assistant's automation engine with the robust capabilities of pfSense or OPNsense, you're not just creating a smart home; you're building a smart, secure, and resilient network perimeter that adapts to your life.

Avatar picture of NGC 224
Written by:

NGC 224

Author bio: DIY Smart Home Creator

There are no comments yet
loading...