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:
- A static LAN IP on
192.168.1.0/24 - Six LAN firewall rules on OPNsense (source = that IP)
- DNS pointed at
192.168.1.1only - Optional WAN NAT for inbound SSH/RDP (unique external ports per VM)
- 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
- Settings → Network → Ethernet → IP assignment → Edit → Manual
- IP:
192.168.1.11 - Mask:
255.255.255.0 - Gateway:
192.168.1.1 -
DNS:
192.168.1.1only (remove any other DNS entries) -
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.shpasses 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.