Skip to content

Add another isolated VM

How to attach a new VM to the same OPNsense LAN segment with the same outbound restrictions as the existing Fedora host: internet + DNS on the router only; no main private LAN; no router admin from the VM.

See also: router setup, firewall rules.

Overview

Each isolated VM needs:

  1. A static LAN IP on 192.168.1.0/24
  2. Six LAN firewall rules on OPNsense (source = that IP)
  3. DNS pointed at 192.168.1.1 only
  4. Optional WAN NAT for inbound SSH/RDP (unique external ports per VM)
  5. Verification using the same connectivity tests

Outbound policy is identical per host. Inbound access is optional and configured per VM via NAT.

1. Plan addresses and ports

Example for a second VM:

Item VM 1 (existing) VM 2 (new)
LAN IP 192.168.1.10 192.168.1.11
Gateway 192.168.1.1 192.168.1.1
WAN SSH 172.22.0.127:22 172.22.0.127:2223
WAN RDP 172.22.0.127:3389 172.22.0.127:3390

You cannot reuse WAN ports 22 or 3389 for two VMs — pick unused high ports for each additional machine.

2. VM network configuration

Linux (NetworkManager — Fedora, RHEL, etc.)

Replace interface name and IP as needed:

# Static IP
sudo nmcli connection modify ens33 ipv4.method manual \
  ipv4.addresses 192.168.1.11/24 \
  ipv4.gateway 192.168.1.1

# DNS via router only
sudo nmcli connection modify ens33 ipv4.dns 192.168.1.1
sudo nmcli connection modify ens33 ipv4.ignore-auto-dns yes
sudo nmcli connection up ens33

Or use the project script with overrides:

FEDORA_INTERFACE=ens33 OPNSENSE_LAN_IP=192.168.1.1 bash scripts/fedora/configure-dns.sh

Windows

  1. Settings → Network → Ethernet → IP assignment → Edit → Manual
  2. IP: 192.168.1.11
  3. Mask: 255.255.255.0
  4. Gateway: 192.168.1.1
  5. DNS: 192.168.1.1 only (remove any other DNS entries)

  6. Confirm no VPN or alternate DNS client overrides resolver settings.

Other hypervisors

  • Attach the VM NIC to the same virtual switch / VLAN as the existing isolated host (OPNsense LAN port).
  • Do not bridge the VM directly onto 172.22.0.0/24 — traffic must go through OPNsense.

3. OPNsense — duplicate firewall rules

Firewall → Rules → LAN — add a new block of six rules for 192.168.1.11/32, placed above the default “allow LAN to any” rule (same pattern as the first VM).

Use a clear description prefix, e.g. VM2: instead of Fedora::

Action Proto Source Destination Port Description
Pass UDP 192.168.1.11/32 192.168.1.1 53 VM2: allow DNS (UDP/53)
Pass TCP 192.168.1.11/32 192.168.1.1 53 VM2: allow DNS (TCP/53)
Block UDP 192.168.1.11/32 !192.168.1.1 53 VM2: block DNS except router (UDP)
Block TCP 192.168.1.11/32 !192.168.1.1 53 VM2: block DNS except router (TCP)
Pass any 192.168.1.11/32 !Private_IPv4 VM2: allow internet only
Block any 192.168.1.11/32 any VM2: block all other

Apply changes when done.

Scaling tip — alias for many VMs

If you will run several isolated hosts, create a firewall alias Isolated_Hosts:

Firewall → Aliases → Hosts

192.168.1.10
192.168.1.11
192.168.1.12

Then use Isolated_Hosts as the source on a single set of six rules instead of duplicating per IP. You must migrate existing per-VM rules to the alias-based set (remove duplicates to avoid conflicts).

4. OPNsense — inbound NAT (optional)

Only if you need SSH or RDP from your PC via the WAN IP.

Firewall → NAT → Port Forward

External Target IP Local port Description
2223 TCP 192.168.1.11 22 SSH to VM2
3390 TCP 192.168.1.11 3389 RDP to VM2

Ensure matching WAN pass rules exist. Test from your workstation:

ssh -p 2223 user@172.22.0.127

5. VM services (optional)

SSH server (Linux)

sudo systemctl enable --now sshd

RDP (Fedora — gnome-remote-desktop)

RDP_USER=myuser RDP_PASSWORD='secret' bash scripts/fedora/configure-rdp.sh

On Windows Server or Windows desktop, enable Remote Desktop in system settings and allow it through the local firewall if enabled.

Local host firewall

The OPNsense rules enforce isolation; a local firewall on the VM is optional defense-in-depth. Do not open wide port ranges unless you need inbound services on the LAN side.

6. Verification

On the new VM, run checks with its environment variables:

OPNSENSE_LAN_IP=192.168.1.1 \
UPSTREAM_ROUTER=172.22.0.1 \
MAIN_LAN_TEST_HOST=172.22.0.50 \
PUBLIC_DNS=8.8.8.8 \
bash scripts/fedora/verify-connectivity.sh

All tests should match the first VM:

Test Expected
Ping gateway 192.168.1.1 OK
Ping 172.22.0.1 or 172.22.0.50 Blocked
Ping 8.8.8.8 OK
dig @192.168.1.1 example.com OK
dig @8.8.8.8 example.com Blocked
curl -I https://example.com OK
TCP 192.168.1.1:22 / :443 Blocked

Confirm VM-to-VM isolation

From VM1, try reaching VM2’s LAN IP (and vice versa). With the current rule set, LAN hosts can still talk to each other unless you add explicit block rules between them. To block VM ↔ VM traffic while keeping internet access, add LAN rules:

Action Source Destination Description
Block 192.168.1.10/32 192.168.1.11/32 Block VM1 → VM2
Block 192.168.1.11/32 192.168.1.10/32 Block VM2 → VM1

Or block all LAN-to-LAN for isolated hosts using a Isolated_Hosts source/destination alias pair.

7. Checklist

  • [ ] Static LAN IP assigned on VM
  • [ ] Gateway 192.168.1.1, no alternate DNS
  • [ ] Six LAN firewall rules added on OPNsense for this source IP
  • [ ] NAT + WAN rules for inbound access (if required)
  • [ ] verify-connectivity.sh passes on the new VM
  • [ ] Inbound SSH/RDP tested from WAN IP (if configured)
  • [ ] VM-to-VM policy decided (allow or block)

8. Automation note

Scripts under scripts/opnsense/ are numbered for the initial deployment and hardcode 192.168.1.10. For additional VMs, prefer the Web UI steps above or copy the rule XML in those scripts and replace the source address and UUIDs. A future improvement is a single parameterized add-isolated-host.py <ip> <label> script.