HOME INFRASTRUCTURE · BUILD JOURNAL

Building a secure, segmented home lab.

This portfolio documents the lab in the order I built it. Each entry explains the goal, the configuration steps, how I tested the result, and what I learned when the first attempt did not work.

Why I built the lab this way

The goal was not to collect unrelated virtual machines. It was to build a small environment where networking, identity, access, and administration depend on one another in realistic ways.

01

Build in dependency order

The hypervisor came first, then routing, segmentation, remote access, identity services, and finally monitoring and automation.

02

Separate trust zones

Management systems, lab services, the jumpbox, and personal home devices should not share unrestricted access.

03

Do not publish management tools

Remote access begins with WireGuard. RDP and administrative web interfaces remain behind the firewall.

04

Validate every assumption

Handshake counters, port tests, DNS queries, packet captures, logs, and external scans show where a path succeeds or fails.

Current traffic flow

The upstream router provides internet access and forwards only the WireGuard UDP service to pfSense. pfSense routes the internal lab networks and applies policy before traffic crosses a trust boundary.

01InternetExternal client
02Home routerUDP forward only
03pfSenseRoute and filter
ZONE 01RESTRICTED

Management

Administrative interfaces such as Proxmox, pfSense management, and SSH.

  • Reachable only from approved administrative sources
  • Specific service ports instead of broad subnet access
ZONE 02INTERNAL

Lab services

Windows Server, domain services, DNS, Ubuntu systems, and test clients.

  • Provides identity and infrastructure services
  • Separated from normal home devices
ZONE 03CONTROLLED

Jumpbox

The single Windows system used as the remote administrative entry point.

  • Receives approved traffic from WireGuard
  • Can reach only defined management targets

Step-by-step lab walkthroughs

These are practical build notes, not universal production designs. The sequence and validation methods are the important parts; exact menus and addresses may vary.

01

FOUNDATION · COMPLETE

Install and prepare the Proxmox host

Turn one physical computer into the compute and networking foundation for the rest of the lab.

Build steps

  1. Prepare the firmware.

    Enable Intel VT-x/VT-d or the equivalent virtualization and IOMMU options. Confirm the system boots from the installation media.

  2. Install Proxmox VE.

    Select the target disk, set the administrative credentials, and assign a static management address that belongs to the current home subnet.

  3. Open the management interface.

    From another computer, browse to https://<proxmox-address>:8006 and sign in.

  4. Review the default bridge.

    Confirm vmbr0 is attached to the physical NIC and contains the host address and default gateway. The bridge allows VMs to use the physical connection.

  5. Prepare storage and installation media.

    Upload the pfSense, Windows Server, and Ubuntu installation images. Reserve enough free storage for VM disks, snapshots, and future updates.

  6. Create a named administrative account.

    After initial setup, add a named user and grant only the Proxmox path and role required for normal VM administration.

Validation

  • The web interface loads on port 8006.
  • The host can reach its default gateway and resolve DNS.
  • A test VM attached to vmbr0 can reach the network.

Lesson recorded

Storage, not CPU, was the first likely constraint. Backup storage should eventually live away from the disk holding the VMs.

02

ROUTING · COMPLETE

Deploy pfSense and create three lab networks

Move lab routing and firewall policy into a virtual firewall instead of placing every VM on the home LAN.

Build steps

  1. Create internal Proxmox bridges.

    Add one bridge for each isolated segment. Internal-only bridges do not need a physical NIC attached.

  2. Create the pfSense VM.

    Allocate approximately 2 vCPU, 2–4 GB RAM, and a small virtual disk. Mount the pfSense installer.

  3. Add the network adapters.

    Attach one adapter to the upstream bridge for WAN and one adapter to each internal bridge for management, services, and jumpbox traffic.

  4. Install pfSense and assign interfaces.

    Identify WAN and each internal adapter by MAC address, then assign clear interface names before setting addresses.

  5. Set the gateway addresses.

    Give every internal interface a static address that will act as the default gateway for that segment.

  6. Configure client addressing.

    Use DHCP for convenience or static addressing for infrastructure systems. Keep servers, the jumpbox, and management interfaces predictable.

  7. Confirm outbound NAT.

    Automatic outbound NAT is sufficient for the initial lab. Confirm internal clients can reach the internet through the pfSense WAN interface.

Validation

  • A client can ping its local pfSense interface.
  • DNS and internet access work from each intended segment.
  • A traceroute shows pfSense as the first routed hop.

Lesson recorded

Creating a subnet is not the same as securing it. The next stage had to define exactly which cross-network flows were permitted.

03

SEGMENTATION · COMPLETE

Build least-privilege pfSense rules

Allow the jumpbox to administer specific systems without granting access to the entire home or management networks.

Build steps

  1. Create aliases.

    Add host aliases such as PROXMOX_HOST and network aliases such as HOME_NET. Names make policy easier to read and update.

  2. Allow Proxmox administration first.

    On the jumpbox interface, allow the jumpbox host to reach PROXMOX_HOST on TCP 8006.

  3. Allow the upstream router only if needed.

    If the jumpbox must open the router's local management page, allow only that host and TCP 443.

  4. Block the rest of the home network.

    Place a block rule for HOME_NET below the narrow router allow. This prevents access to other personal devices.

  5. Protect the management network.

    After each approved management-host allow, block the remainder of the management subnet.

  6. Add broader internet access last.

    An allow-to-any rule can provide outbound internet access because protected internal destinations have already been matched and blocked above it.

  7. Document every rule.

    Use descriptions that explain the source, destination, service, and reason. Avoid unexplained broad rules.

Validation

  • Proxmox opens from the jumpbox on TCP 8006.
  • Unapproved home and management hosts do not respond.
  • Internet access continues to work where intended.

Lesson recorded

The order of allow and block rules matters as much as the contents of each rule. Testing should include paths expected to fail.

04

REMOTE ACCESS · COMPLETE

Connect through WireGuard and a Windows jumpbox

Create one encrypted entry path into the lab without forwarding RDP from the public internet.

Build steps

  1. Create the pfSense WireGuard tunnel.

    Generate the tunnel keys, choose a private tunnel subnet, and configure a UDP listen port.

  2. Add the remote peer.

    Enter the client's public key and tunnel address. Keep AllowedIPs limited to the lab destinations the client needs.

  3. Assign and enable the WireGuard interface.

    Interface assignment makes firewall rules and routing easier to understand and inspect.

  4. Forward the UDP listener upstream.

    On the home router, forward the selected WireGuard UDP port to the pfSense WAN address.

  5. Create the WireGuard firewall rule.

    Allow the VPN peer to reach the jumpbox on the required traffic. Do not begin with unrestricted access to every internal subnet.

  6. Prepare the Windows jumpbox.

    Assign a predictable address, enable RDP with Network Level Authentication, and scope the Windows Firewall rule to the VPN source network.

  7. Test from a genuinely external connection.

    Use a mobile hotspot or another network so the test traverses the public edge rather than staying inside the home LAN.

Test-NetConnection <jumpbox-address> -Port 3389

Validation order

  • Confirm a current WireGuard handshake and byte counters.
  • Ping the WireGuard gateway, then the jumpbox.
  • Test TCP 3389 before opening the RDP client.

Lesson recorded

A healthy VPN handshake proves encryption and peer reachability, but not the route, firewall rule, Windows firewall, or RDP service behind it.

05

IDENTITY + DNS · COMPLETE

Deploy Active Directory and repair DNS registration

Add centralized identity, domain DNS, administrative account separation, and the foundation for Group Policy.

Build steps

  1. Prepare the Windows Server VM.

    Assign a static address, set the pfSense interface as the gateway, rename the server clearly, and install current updates.

  2. Point the server's DNS client to itself.

    After promotion, the domain controller should use its own address for DNS. Configure external DNS through server forwarders instead of the NIC.

  3. Install AD DS and DNS.

    Add both roles, promote the server to a new forest, and choose the lab domain name.

  4. Verify the DNS zone.

    Confirm it is stored in Active Directory and uses secure dynamic updates. The domain controller should have host and service records.

  5. Force registration if records are missing.

    Flush and register DNS, restart Netlogon, and request domain-controller DNS registration.

ipconfig /flushdns
ipconfig /registerdns
net stop netlogon
net start netlogon
nltest /dsregdns
  1. Test the AD service record.

    Query the LDAP SRV record and confirm it returns the domain controller and port 389.

  2. Join a client.

    Point the client's DNS setting only to the domain controller, verify name resolution, and then join the domain.

  3. Separate identities.

    Use a normal account for daily sign-in, a named administrative account for privileged work, and preserve the built-in administrator for controlled recovery use.

Validation

  • dcdiag /test:dns /v returns healthy results.
  • The LDAP SRV lookup returns the domain controller.
  • nltest /dsgetdc:<domain> locates the DC.

Lesson recorded

Creating missing DNS folders manually would hide the underlying problem. Netlogon registration, zone type, and DNS-client configuration had to be correct first.

06

AUTOMATION · COMPLETE

Build a reusable Windows diagnostic script

Combine common connectivity and system checks into one repeatable PowerShell 5.1 workflow.

Build steps

  1. Define configurable inputs.

    Accept DNS names, TCP targets, internet URLs, service names, certificate-warning days, timeouts, and an output directory.

  2. Create one result format.

    Use PASS, WARN, FAIL, and INFO so every check can be displayed and exported consistently.

  3. Wrap checks safely.

    Run each diagnostic in its own error handler so one failure does not stop the rest of the report.

  4. Add network checks.

    Resolve DNS, connect to TCP host/port pairs with explicit timeouts, test internet URLs, and collect adapters and routes.

  5. Add Windows checks.

    Collect WinHTTP and user proxy settings, firewall profiles, services, system time, and certificate information.

  6. Write both report formats.

    Create a readable text summary and JSON output for later filtering, comparison, or automation.

  7. Return meaningful exit codes.

    Use 0 when clean, 1 when warnings exist, and 2 when a check fails.

.\Invoke-WindowsNetworkDiagnostic.ps1

Validation

  • Known-good targets return PASS.
  • An intentionally invalid target records FAIL without stopping the script.
  • TXT and JSON reports contain matching results.

Lesson recorded

A useful diagnostic tool must handle partial failure, preserve context, and create output that remains useful after the terminal closes.

07

EDGE VALIDATION · COMPLETE

Review the public attack surface with Nmap

Test the network from outside and confirm that the firewall exposes the VPN rather than management services.

Build steps

  1. Identify the public address.

    Record the current public IP without publishing it in project documentation.

  2. Run the default TCP scan.

    Check common TCP services first and note whether results are open, closed, or filtered.

  3. Check management ports explicitly.

    Confirm services such as SSH, HTTPS administration, Proxmox 8006, and RDP 3389 are not public.

  4. Test the VPN UDP port separately.

    A normal Nmap scan does not answer the UDP question. Use a targeted UDP scan for the configured listener.

nmap <public-ip>
nmap -sU -p <wireguard-port> <public-ip>
  1. Interpret UDP carefully.

    open|filtered is normal when the scanner receives no response. WireGuard intentionally ignores unauthenticated probe data.

  2. Compare with the intended design.

    The desired result is no public TCP management service and only the planned UDP VPN path.

Validation result

  • Common TCP ports were filtered.
  • RDP was not directly exposed.
  • Remote access still worked through the authenticated VPN path.

Lesson recorded

“Filtered” does not mean the same thing as “closed,” and a default TCP scan does not validate a UDP VPN service.

08

PACKET TROUBLESHOOTING · COMPLETE

Send and validate a Wake-on-LAN packet

Build the packet in PowerShell and prove its path before treating the BIOS or NIC as the problem.

Build steps

  1. Enable firmware wake support.

    Enable PCIe wake, disable ErP if it removes standby NIC power, and confirm the Ethernet LEDs remain active after a normal shutdown.

  2. Confirm Linux NIC support.

    Use ethtool on the physical interface and confirm it supports and enables magic-packet wake with Wake-on: g.

  3. Build the packet.

    Use the physical Ethernet MAC, not the bridge MAC, and the subnet broadcast address.

$mac = "AA:BB:CC:DD:EE:FF"
$macBytes = $mac -split '[:-]' | ForEach-Object {
    [Convert]::ToByte($_, 16)
}
$packet = [byte[]](,0xFF * 6 + ($macBytes * 16))
$udp = New-Object System.Net.Sockets.UdpClient
$udp.EnableBroadcast = $true
$udp.Connect("192.168.1.255", 9)
[void]$udp.Send($packet, $packet.Length)
$udp.Close()
  1. Capture before shutting down.

    While Proxmox is running, listen for the packet on every interface and send it from Windows.

sudo tcpdump -ni any udp port 9
  1. Confirm the full path.

    A 102-byte packet should appear on the physical NIC and the Linux bridge with the broadcast destination.

  2. Test after a normal shutdown.

    If the packet was proven but the host still does not wake, investigate shutdown-state NIC power, firmware, and driver behavior rather than rewriting the sender.

Validation result

  • The script generated a 102-byte payload.
  • tcpdump captured it on the physical NIC and bridge.
  • The remaining failure domain moved beyond packet construction and delivery.

Lesson recorded

A failed outcome does not mean every component failed. Capturing the packet separated the working network path from the unresolved power-state behavior.

What comes next

The next stages are ordered around recovery first, visibility second, and additional complexity last.

01 · NEXT

Proxmox Backup Server

Move backups away from VM storage, define retention, enable verification, and complete a documented restore.

02 · PLANNED

Centralized monitoring

Collect infrastructure metrics and security events so changes and failures are visible across the environment.

03 · LATER

Kubernetes on Proxmox

Build a small virtual cluster for services, ingress, CNI, persistent storage, and NetworkPolicy practice.

Connect with me on LinkedIn

If you would like to discuss the lab, its architecture, or any of the walkthroughs, LinkedIn is the best place to reach me.