Files
web-log/container/site/content/posts/router-build/index.md
T
nicholas 2e9bd0e409
Build & Push Hugo Site Image / Build & Push Image (push) Successful in 9s
Build & Push Hugo Site Image / deploy (push) Successful in 16s
add tags, descriptions to posts (#38)
2026-08-05 16:24:33 -05:00

6.5 KiB
Raw Blame History

+++ 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:

  1. Write custom firmware to existing router (DD-WRT, OpenWRT, Tomato, etc.)

    • Fun
    • Free
    • Too much jank
  2. Buy new hardware

    • Very easy setup
    • Boring
    • 💲 Could require expensive/high-end router hardware
  3. 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:

  1. Configure the virtual switch on my VM host to perform 802.1Q VLAN tagging for router VM.

    • Free, no additional hardware required
  2. 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.