Skip to content

tyvsmith/unifi5gmax-opnsense-setup

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

UniFi 5G Max + OPNsense Integration Guide

⚠️ PROOF OF CONCEPT
This is a proof-of-concept implementation extracted from a working homelab setup. It is provided as-is for educational and reference purposes. Test thoroughly before using in any production environment. No warranty is provided.

Note: My actual home environment uses a full logging stack (Vector, Loki, etc.) for this and other automation. I put together this lightweight implementation using just Alpine + socat to help others get started without the overhead.

License

Why This Exists

The UniFi 5G Max is not a typical cellular modem:

  • No bridge mode - Unlike traditional modems, you can't simply bridge the connection to your own router. The U5G-Max insists on being a router itself.
  • GRE tunnel is the escape hatch - UniFi designed the U5G-Max to integrate with other UniFi gateways (like the UDM) via a built-in GRE tunnel. This project leverages that same tunnel to integrate with OPNsense instead.
  • Locked-down firmware - The U5G-Max doesn't persist filesystem changes across reboots. The config.properties trick that works on other UniFi devices doesn't apply here.
  • IPv6 is especially problematic - The device gets a dynamic IPv6 prefix from the carrier, but ip6tables rules don't survive reboots. An external automation system is needed to reconfigure IPv6 NAT66 after every boot.

This project provides that external automation: a lightweight syslog listener that detects when the U5G-Max boots, then SSHes in to configure IPv6 NAT masquerading through the GRE tunnel.

What This Provides

  • GRE tunnel between OPNsense and U5G-Max for WAN failover
  • IPv6 NAT66 automation (the U5G-Max loses IPv6 config on reboot)
  • Log-based trigger using a lightweight Alpine container (~8MB)
  • Step-by-step OPNsense configuration guide

This guide provides the minimum viable setup to integrate a UniFi 5G Max (U5G-Max) cellular gateway with OPNsense as a WAN failover connection with full IPv6 support via NAT66.

Overview

The UniFi 5G Max is a cellular gateway that provides LTE/5G connectivity. While it works seamlessly in a pure UniFi ecosystem, integrating it with OPNsense as a failover WAN requires:

  1. GRE Tunnel - Already configured on the U5G-Max for IPv4
  2. OPNsense GRE Interface - Match the U5G-Max's tunnel configuration
  3. IPv6 NAT66 - Since the carrier provides a dynamic /64, we use NAT66
  4. Automation - The U5G-Max loses its IPv6 config on reboot, so we automate re-configuration

Key Points

  • The U5G-Max already has GRE configured - You don't need to set up the tunnel on it
  • IPv4 works out of the box - The GRE tunnel handles IPv4 routing automatically
  • IPv6 requires automation - The U5G-Max loses ip6tables rules and interface IP on reboot
  • Syslog via UniFi Controller - Configure SIEM forwarding in the UniFi UI (the U5G-Max doesn't allow persistent filesystem changes)

Architecture

                                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                    β”‚           5G/LTE Carrier            β”‚
                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                       β”‚ wwan0
                                                       β”‚ (dynamic IPv4/IPv6)
                                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                    β”‚          UniFi 5G Max               β”‚
                                    β”‚                                     β”‚
                                    β”‚  gre1: 100.127.125.128/31           β”‚
                                    β”‚        fd70::1/127 (via automation) β”‚
                                    β”‚                                     β”‚
                                    β”‚  NAT66: fd70::/127 β†’ wwan0          β”‚
                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                       β”‚ LAN: 192.168.1.30
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                                     LAN          β”‚                                       β”‚
    β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
    β”‚      β”‚                                           β”‚                                 β”‚    β”‚
    β”‚      β–Ό                                           β–Ό                                 β–Ό    β”‚
    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    GRE Tunnel (encapsulated)   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
    β”‚ β”‚OPNsense │◄───────────────────────────────│  Switch   β”‚                    β”‚Automationβ”‚β”‚
    β”‚ β”‚         β”‚  100.127.125.129 ↔ .128        β”‚           β”‚                    β”‚  Server  β”‚β”‚
    β”‚ β”‚         β”‚  fd70::0 ↔ fd70::1             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚ (Alpine) β”‚β”‚
    β”‚ β”‚         β”‚                                      β”‚                          β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜β”‚
    β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                                      β”‚                               β”‚      β”‚
    β”‚      β”‚                                           β”‚                               β”‚      β”‚
    β”‚      β”‚                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚      β”‚
    β”‚      β”‚                              β”‚  UniFi Network App      β”‚ β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
    β”‚      β”‚                              β”‚  (Controller)           β”‚   SIEM Syslog           β”‚
    β”‚      β–Ό                              β”‚                         β”‚   UDP 5514              β”‚
    β”‚  LAN Clients                        β”‚  Forwards logs via SIEM β”‚                         β”‚
    β”‚                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Flow:
1. U5G-Max boots β†’ logs to UniFi Controller (LAN)
2. Controller forwards logs via SIEM β†’ Automation Server (LAN)  
3. Automation SSHes to U5G-Max β†’ configures NAT66 (LAN)
4. OPNsense routes traffic via GRE tunnel β†’ U5G-Max β†’ Carrier (WAN)

Prerequisites

  • OPNsense firewall (tested on 24.x)
  • UniFi 5G Max with SSH access enabled
  • UniFi Network Controller (for SIEM log forwarding)
  • A server to run the automation stack (any Docker host)
  • Basic familiarity with OPNsense and networking concepts

1. UniFi 5G Max Configuration

Enable SSH Access

  1. In the UniFi Controller, go to Settings β†’ System β†’ Advanced
  2. Enable SSH access
  3. Set a strong SSH password or add your public key

Log Forwarding (Automatic)

Since the U5G-Max doesn't allow persistent filesystem changes, we rely on the UniFi Controller's built-in log forwarding capability.

If your UniFi Controller and automation server share the same IP:

  • No manual configuration needed - logs are automatically captured by the automation server listening on port 5514
  • The controller and automation server can coexist on the same host

If using separate IPs:

  1. In UniFi Controller: Settings β†’ CyberSecure β†’ Traffic Logging β†’ Activity Logging (Syslog)
  2. Add a new syslog server:
    • Server: Your u5g-automation server IP (e.g., 192.168.1.50)
    • Port: 5514

This forwards logs from all UniFi devices, including the U5G-Max boot events we need.

Note the IP Addresses

The U5G-Max has:

  • LAN IP: 192.168.1.30 (adjust to your network)
  • GRE Tunnel IP: 100.127.125.128 (inside the tunnel, already configured)
  • wwan0: Dynamic carrier-assigned IPv4/IPv6

2. OPNsense Configuration

See opnsense/README.md for detailed step-by-step GUI instructions.

Summary of what to configure:

  1. GRE Interface - Match the U5G-Max's existing tunnel:

    • Remote: 192.168.1.30
    • Tunnel IPs: 100.127.125.129/31 (OPNsense) ↔ 100.127.125.128/31 (U5G)
  2. Assign as WAN - Create WAN_GRE interface on gre0

  3. Virtual IP for IPv6 - Add fd70::0/127 on the GRE interface

  4. Gateways:

    • IPv4: Auto-detected via tunnel
    • IPv6: fd70::1 (U5G-Max side, configured by automation)
  5. Gateway Groups - Primary WAN as Tier 1, GRE as Tier 2 for failover


3. Automation Stack

The u5g-automation runs in a single Alpine container (~8MB):

  • syslog-trigger.sh - Listens for syslog, detects boot events, triggers SSH
  • nat66.sh - Configures IPv6 NAT on the U5G-Max

Directory Structure

.
β”œβ”€β”€ README.md              # This file
β”œβ”€β”€ LICENSE                # Apache 2.0
β”œβ”€β”€ docker/
β”‚   β”œβ”€β”€ compose.yml        # All services
β”‚   β”œβ”€β”€ .env.example       # Configuration template
β”‚   β”œβ”€β”€ syslog-trigger.sh  # Syslog receiver + trigger
β”‚   β”œβ”€β”€ nat66.sh           # NAT66 script (runs on U5G via SSH)
β”‚   └── init-mongo.sh      # MongoDB init (for demo UniFi)
└── opnsense/
    β”œβ”€β”€ README.md          # OPNsense setup guide
    └── gre-gateway-config.xml

Deploy

cd docker
cp .env.example .env

# Generate SSH key if needed
ssh-keygen -t ed25519 -f ~/.ssh/u5g -N ""
ssh-copy-id -i ~/.ssh/u5g.pub [email protected]

# Base64 encode and add to .env
echo "SSH_PRIVATE_KEY_BASE_64=$(base64 -w0 ~/.ssh/u5g)" >> .env

# Start the stack
docker compose up -d

Monitor

docker logs -f u5g-automation

4. Testing

Test GRE Tunnel

From OPNsense shell:

# Ping U5G-Max via tunnel
ping -c 4 100.127.125.128

# Test IPv6 (after automation has run)
ping6 -c 4 fd70::1

Test Internet via U5G-Max

# Force traffic via U5G gateway
ping -S 100.127.125.129 8.8.8.8

Test Automation

  1. Reboot the U5G-Max
  2. Watch automation logs: docker logs -f u5g-automation
  3. Verify NAT66 rules: ssh [email protected] ip6tables -t nat -L -n

Troubleshooting

No Logs Received

  1. Verify UniFi SIEM is configured to send to your server
  2. Check the container is running: docker logs u5g-automation
  3. Test with: nc -ul 5514 and reboot U5G-Max

Automation Not Triggering

  1. Check logs include "Configuring wwan0":
    docker logs u5g-automation 2>&1 | grep -i wwan
  2. Verify SSH connectivity:
    docker exec u5g-automation ssh -i /root/.ssh/id_ed25519 [email protected] echo OK

IPv6 Not Working

  1. Check NAT66 rules: ssh [email protected] ip6tables -t nat -L POSTROUTING -n
  2. Verify wwan0 has IPv6: ssh [email protected] ip -6 addr show wwan0
  3. Check gre1 has fd70::1: ssh [email protected] ip -6 addr show gre1

Files Reference

File Purpose
docker/compose.yml All services
docker/syslog-trigger.sh Syslog receiver + automation trigger
docker/nat66.sh NAT66 script (runs on U5G via SSH)
opnsense/README.md OPNsense setup guide

How the Automation Works

  1. syslog-trigger.sh listens on UDP 5514 using socat
  2. When it sees "Configuring wwan0:" in a log line, it extracts the source IP
  3. SSHes to the U5G-Max and runs nat66.sh to configure IPv6 NAT
  4. Optionally forwards all logs to your UniFi controller for normal viewing

Optional: Start the demo UniFi controller with docker compose --profile unifi up -d


Security Considerations

  • SSH key should be dedicated to this automation
  • Consider a separate VLAN for U5G-Max management
  • Automation server should be in a trusted network segment
  • Regularly update U5G-Max firmware

License

Apache License 2.0 - See LICENSE

FAQ

Is this hacky?

Yes. This entire solution is a workaround for the U5G-Max's lack of bridge mode and inability to persist configuration changes. We're using syslog parsing to detect boot events and SSH automation to reconfigure the deviceβ€”it's not elegant, but it works.

Do you actually run it this way?

Yes, but with a real logging stack (Vector, Loki, Grafana, etc.) rather than a standalone Alpine container. The lightweight implementation here is designed to help others get started without the overhead of a full observability stack. If you want to scale this or integrate it into broader home automation, consider using a proper log aggregation pipeline.

Why not just use a cron job?

That would workβ€”you could run the NAT66 script every few minutes and call it a day. But then I'd be annoyed by all the unnecessary SSH traffic and redundant configuration attempts when the device is already configured. Ideally, pushing (event-driven) is a better solution than polling. Plus, I already had a logging stack available, so hooking into syslog events was the natural choice. If you don't have that infrastructure and just want something simple, a cron job is a perfectly valid approach.

Are there security concerns?

Yes. Having an SSH key with root access to the U5G-Max sitting in a container isn't ideal. Some mitigations:

  • Use a dedicated SSH key only for this automation
  • Restrict the automation server to a trusted network segment or VLAN
  • Lock down firewall rules so only the automation container can SSH to the U5G-Max
  • Monitor for unauthorized access attempts

Unfortunately, until UniFi provides more granular controls (like per-device SSH keys or persisted authorized_keys) or allows the device to operate in a standard bridge mode like other cellular modems, this is the reality of the situation. It is what it is.

About

Connects the Unifi 5g Max to OPNSense

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages