6.5 KiB
+++ categories = ["software"] tags = ["router","opnsense"] date = 2025-08-27T18:30:00-05:00 description = "Replacing a consumer router with virtualized OPNsense, a managed switch, VLANs, and a router-on-a-stick network design." draft = false slug = "router-build" title = "🔀 Router Build" author = "nicholas" +++
My router (Netgear R6400v2) lacks many of the features I would like to use and become familiar with:
- VLANs
- Advanced routing, firewall
- Monitoring, logging, alerts
- etc.
I need a new router.
I have a few options from here:
-
❌ Write custom firmware to existing router (DD-WRT, OpenWRT, Tomato, etc.)
- ➕ Fun
- ➕ Free
- ➖ Too much jank
-
❌ Buy new hardware
- ➕ Very easy setup
- ➖ Boring
- 💲 Could require expensive/high-end router hardware
-
✅ Repurpose existing hardware
- ➕ Fun
- ➕ Makes use of an unused Dell OptiPlex 5050 Micro
- ➕ Can run proper router OS OPNsense
- ➕ Repurpose router as wireless access point
🪵 Router-on-a-stick (ROAS)
My VM host (where I will build my router) has only a single NIC, with only one physical port. That means I cannot replicate the exact behavior of ordinary consumer routers, which are typically configured with a dedicated WAN port, and several dedicated LAN ports. The router simply routes between the two. Very simple. I need to find a way to replicate the function of such a router without the same hardware.
I have a couple of options:
-
❌ Configure the virtual switch on my VM host to perform 802.1Q VLAN tagging for router VM.
- ➕ Free, no additional hardware required
-
✅ Configure a managed physical switch to handle 802.1Q VLAN tagging and trunking to the router
- ➕ Gain additional physical ports
- 💲 Addtional hardware required
I want the extra ports! I got a Netgear GS108E-400NAS. For no other reason than it was available at my local Best Buy.
🖧 Logical Network Topology
This diagram describes approxmiately what I my network will look like:
graph TD
isp["🌐ISP"]
modem["📡Modem"]
switch["🔀Switch"]
subgraph vm-host["VM Host"]
router["🛡️Router (OPNsense)"]
end
wap["🛜WAP"]
nas["🗄️NAS"]
workstation["🖥️Workstation"]
subgraph wireless["Wireless Devices"]
laptop["💻Laptop"]
phone["📱Phone"]
printer["🖨️Printer"]
end
isp --- modem
modem --- switch
switch --- |"🪵 Trunk (VLANs 10,100)"| router
switch --- wap
switch --- nas
switch --- workstation
wap -.- wireless
🔀 Switch Setup & Port VLAN Assignment Table
-
First, I need to choose a subnet for my network and assign my switch an IP accordingly. I chose 10.0.0.0/8 subnet. It just looks good.
-
Next I cofigure my switch with a trunk port. This port will link to the router and carry multiple VLANs: VLAN 10 (LAN), VLAN 100 (WAN). This allows my router to distinguish between WAN and LAN with just one physical port. Instead of a phyiscal port to ditinguish WAN and LAN, the distinction is made virtually using VLAN tags.
-
This means I will also need to configure a separate port for VLAN 100 (modem/ISP uplink), so that all traffic on that port is tagged and forwarded as WAN traffic.
| Port | Device | VLAN Mode | PVID | Tagged VLANs |
|---|---|---|---|---|
| 1 | Router | Trunk | 10 | 10,100 |
| 2 | Workstation | Access | 10 | - |
| 3 | NAS | Access | 10 | - |
| 4 | WAP | Access | 10 | - |
| 5 | - | Access | 10 | - |
| 6 | - | Access | 10 | - |
| 7 | - | Management | 1 | - |
| 8 | Modem | Access | 100 | - |
Switch VLAN tagging
flowchart TD
lan["🏠LAN"]
modem["🌐Modem/ISP"]
switch[🔀Switch]
subgraph router["🛡️Router"]
wan_interface["🌐WAN Interface"]
lan_interface["🏠LAN Interface"]
end
lan -- "`
*🗅untagged*
🔵access port **VLAN 10**
`" --> switch
modem -- "`
*🗅untagged*
🔵access port **VLAN 100**`" --> switch
switch -- "*🏷️tagged* VLAN 10" --> lan_interface
switch -- "*🏷️tagged* VLAN 100" --> wan_interface
✅ Done. Now I configure a VM for the router.
🖥️ VM Configuration
I need to configure a VM to serve as a router:
- COnfigure VM specs:
- 20 GB vdisk
- 3 GB RAM
- 1 vCPU
- Install OPNsense OS
- Configure VM network adapter with static MAC address (spoof old netgear router MAC, keep current DHCP IP)
- Configure host OS network adapter to carry VLAN ID 10 only
- Configure VM network adapter to carry VLANs ID 10,100
✅ Done. Now I can configure OPNsense.
🛡️ OPNsense
{{< image src="images/OPNsense-dashboard.png" caption="OPNsense Dashboard" >}}
Interfaces
According to the plan, I need to configure OPNsense with an interface for each VLAN I configured:
- VLAN 10 for LAN
- VLAN 100 for WAN
DNSMasq DHCP
Since I want most of my devices to be assigned IPs dynamically, I enable DHCP on the LAN interface.
- Start address: 10.0.10.3
- End address: 10.0.10.100
- 10.0.10.100 - 10.0.10.200 are reserved for static / wired devices.
Unbound DNS
I also want to use my router as a DNS server for local DNS resolution, so I enable Unbound DNS. This is where I can configure A records (host override), and CNAME records (alias).
For example:
| Record Type | Name | Value |
|---|---|---|
| A | proxy.internal.domain.com | 10.0.10.100 |
| CNAME | git.domain.com | proxy.internal.domain.com |
Query Forwarding
Now that I have given my wired devices static IPs, I can do query forwarding to Pi-Hole. This will enable network-wide ad blocking.
flowchart LR
client[💻Client] --> router-dns["`
🛡️Router
(Local DNS)
`"]
router-dns --> pihole[🕳️Pi-hole]
pihole --> upstream["`
☁️ Upstream DNS
(e.g. 8.8.8.8)`"
]
Firewall - GeoIP
I use MaxMind GeoIP database to create a firewall alias. Then I configured a firewall rule on WAN interface which blocks any IP that matches those configured in the alias. I am blocking IPs from most countries.
This nearly eliminates unwanted traffic from annoying and/or malicious bots scanning and scraping my network
MaxMind GeoIP database:https://AccountID:LicenseKey@download.maxmind.com/geoip/databases/GeoLite2-Country-CSV/download?suffix=zip
🎉 It works!
{{< video src="videos/router-traffic-graph-live.mp4" width="100%"
}}
✅ Done.