Skip to content

**A complete, production-ready home laboratory infrastructure based on pfSense, Hyper-V, Samba AD, VLANs, and DMZ isolation with Traefik reverse proxy.**

License

Notifications You must be signed in to change notification settings

broccoliandpepper/Infra-pfSense

Repository files navigation

🏠 Homelab Secure Network Architecture

A complete, production-ready home laboratory infrastructure based on pfSense, Hyper-V, Samba AD, VLANs, and DMZ isolation with Traefik reverse proxy.


This laboratory is the result of my self-taught learning with the help of AI and my own experience. You use it at your own risk. Everything I publish is tested and works.

📋 Table of Contents

  1. Project Overview
  2. Architecture & Components
  3. Network Topology & VLAN Segmentation
  4. Security & Firewall Rules
  5. Installation & Configuration Guide
  6. Services & Deployment
  7. Traefik Reverse Proxy Deployment
  8. Advanced Features & Troubleshooting
  9. Future Enhancements
  10. References & Support

🎯 Project Overview

This project documents a complete, isolated home laboratory running on Hyper-V with enterprise-grade network segmentation using pfSense as the central firewall and router.

Key Features

Complete Network Isolation – Home network remains untouched via double NAT
VLAN Segmentation – 4 logical security zones (Infra, Servers, Clients, DMZ)
Active Directory – Samba 4 AD DC for centralized management
Firewalling – Granular rules with default-deny policy
DMZ Security – Isolated zone for externally-exposed services
Reverse ProxyTraefik v3.6 with centralized routing for all DMZ services
DNS Resolution – Centralized DNS with internal domain (homelab.local)
Auto SSL – Self-signed certificates for internal lab (Let's Encrypt ready)
Production-Ready – Suitable for learning and professional experimentation


🏗️ Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                        Internet                               │
└────────────────────────────┬────────────────────────────────┘
                             │
                             ↓
┌─────────────────────────────────────────────────────────────┐
│              Home Network Router (192.168.2.0/24)            │
└────────────────────────────┬────────────────────────────────┘
                             │
                    WAN (192.168.2.141)
                             │
         ┌───────────────────┴───────────────────┐
         │                                       │
    ┌────▼────┐                            ┌────▼────┐
    │ Hyper-V │◄──────────────────────────►│ pfSense │
    │  Host   │         vSwitches          │   VM    │
    └────┬────┘                            └────┬────┘
         │                                       │
    ┌─────┴────────┬──────────────┬──────────────┴─────┐
    │              │              │                    │
 VLAN 10      VLAN 20         VLAN 30              VLAN 40
 (Infra)      (Servers)       (Clients)            (DMZ)
192.168.10.0  192.168.20.0    192.168.30.0     192.168.40.0
    │              │              │                    │
    │              │              │                    │
 DC/DNS        n8n, Apps      Test Clients        nginx
 Samba AD      Containers     Windows/Linux    Web Server

DMZ Traffic Flow (New Architecture):

Internet → pfSense NAT (80/443) → Traefik (.40) → Nginx (.50)

Each VLAN represents a security domain with independent firewall rules, DHCP scope, and DNS configuration.


🔧 Core Components

Infrastructure

Component Role Location IP Address Status
pfSense VM Firewall & Router Hyper-V WAN: 192.168.2.141 ✅ Running
Samba AD DC Directory Services VLAN 10 192.168.10.10 ✅ Running
Traefik Reverse Proxy VLAN 40 (DMZ) 192.168.40.40 ✅ Running
Nginx Server Web Server VLAN 40 (DMZ) 192.168.40.50 ✅ Running

Hypervisor

  • Hyper-V: Windows Server or Pro
  • 2 Virtual Switches:
    • vSwitch-LAB-WAN (external, connected to physical NIC)
    • vSwitch-LAB-LAN (internal, trunk mode for all VLANs)
  • Multiple VMs: Ubuntu Server, Windows Desktop, Docker containers

🌐 Network Topology & VLAN Segmentation

VLAN 10 – Infrastructure / Active Directory

Network:

  • Gateway: 192.168.10.1
  • Subnet: 192.168.10.0/24
  • DHCP: 192.168.10.50–199
  • DNS Resolver: Internal Samba DNS (192.168.10.10)

Services:

  • Samba 4 AD DC (192.168.10.10)
  • Centralized DNS server for homelab.local
  • NTP services
  • Core directory services

Security Rules:

  • Allow DNS, Kerberos (88), LDAP (389), SMB (445), RPC (135, 1024-65535) to/from DC
  • Allow outbound Internet
  • Deny inter-VLAN access

Domain-Joined Machines:

  • Servers in VLAN 20
  • Workstations in VLAN 30
  • NOT DMZ (intentionally isolated)

VLAN 20 – Application Servers

Network:

  • Gateway: 192.168.20.1
  • Subnet: 192.168.20.0/24
  • DHCP: 192.168.20.50–199

Services:

  • Docker containers
  • n8n (workflow automation)
  • Backend APIs
  • Development & testing environments

Security Rules:

  • Allow outbound Internet
  • Allow access to VLAN 10 DC (for domain services)
  • Deny access to DMZ

VLAN 30 – Client Workstations

Network:

  • Gateway: 192.168.30.1
  • Subnet: 192.168.30.0/24
  • DHCP: 192.168.30.50–199

Services:

  • Windows desktop machines (AD testing)
  • Linux client machines (SSSD joined)
  • Test workstations

Security Rules:

  • Allow access to VLAN 10 (DC, DNS, Kerberos)
  • Allow outbound Internet
  • Deny access to VLAN 20, VLAN 40

VLAN 40 – Demilitarized Zone (DMZ)

Network:

  • Gateway: 192.168.40.1
  • Subnet: 192.168.40.0/24
  • DHCP: 192.168.40.50–199
  • DNS Resolver: External only (1.1.1.1, 8.8.8.8)

Purpose:

  • Externally-exposed web services
  • Reverse proxies (Traefik at .40)
  • Backend services (Nginx at .50)
  • Public-facing applications

Critical Security Property:
🔒 NOT Domain-Joined – completely isolated from Active Directory

Security Rules:

  • ✅ Allow outbound: HTTP (80), HTTPS (443), DNS (53) only
  • ✅ Allow inbound: WAN via NAT port forwarding (ports 80/443 → Traefik)
  • Block ALL access to internal VLANs (10, 20, 30) using RFC1918 alias
  • ❌ No access to AD DC
  • ✅ Allow intra-DMZ communication (Traefik ↔ Nginx)

🔐 Security & Firewall Rules

Firewall Philosophy

Default Deny + Explicit Allow

Every VLAN follows this principle:

  1. ❌ All inter-VLAN traffic blocked by default
  2. ✅ Only explicitly configured traffic allowed
  3. ✅ Each rule specifies source, destination, and ports
  4. 📊 All rules logged for audit and troubleshooting

RFC1918 Networks Alias

A firewall alias combining all private networks for easy DMZ isolation:

Name: RFC1918
Description: Private IPv4 networks
Networks:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

Used by DMZ firewall rules to block all internal networks in a single rule.

Firewall Rules Matrix

Source VLAN Destination Ports Protocol Action Purpose
All pfSense 53 TCP/UDP Allow DNS resolution
10, 20, 30 Any Any Any Allow Internet access
40 Any 80, 443, 53 TCP/UDP Allow HTTP/HTTPS/DNS outbound
40 RFC1918 All Any Block DMZ isolation
40 40 subnet All Any Allow Intra-DMZ (Traefik ↔ Nginx)
30 10.10 53, 88, 389, 445, 135, 1024-65535 TCP/UDP Allow Domain services
20 10.10 53, 88, 389, 445, 135, 1024-65535 TCP/UDP Allow Domain services

Port Forwarding (WAN → DMZ)

For externally-exposed services (via Traefik):

WAN Port Protocol DMZ IP DMZ Port Service Status
80 TCP 192.168.40.40 80 HTTP → Traefik ✅ Active
443 TCP 192.168.40.40 443 HTTPS → Traefik ✅ Active

Note: All traffic now goes to Traefik first, which then routes to backend services (Nginx, APIs, etc.)


📦 Installation & Configuration Guide

Prerequisites

Hardware Requirements:

  • Windows Server 2016+ or Hyper-V Pro (Windows 10/11 Pro/Enterprise)
  • 4+ CPU cores
  • 16+ GB RAM (8GB minimum)
  • 500GB+ free disk space

Network Requirements:

  • Existing home/lab network with Internet connectivity
  • One network interface card (dual NICs recommended)

Phase 1: pfSense Setup

Create Hyper-V VM:

  • 2 vCPU, 2–4 GB RAM, 20–40 GB disk
  • 2 vNICs: WAN (external) + LAN (internal, trunk)

Virtual Switches (PowerShell):

# External switch for WAN
New-VMSwitch -Name "vSwitch-LAB-WAN" -NetAdapterName "Ethernet"

# Internal switch for LAN (VLANs)
New-VMSwitch -Name "vSwitch-LAB-LAN" -SwitchType Internal

# Attach to pfSense VM
Add-VMNetworkAdapter -VMName "VM-pfsense" -SwitchName "vSwitch-LAB-WAN"
Add-VMNetworkAdapter -VMName "VM-pfsense" -SwitchName "vSwitch-LAB-LAN"

# Enable trunk on LAN interface
Get-VMNetworkAdapter -VMName "VM-pfsense" |
  Where-Object {$_.SwitchName -eq "vSwitch-LAB-LAN"} |
  Set-VMNetworkAdapterVlan -Trunk -AllowedVlanIdList "10,20,30,40" -NativeVlanId 0

pfSense Web UI Configuration:

  1. Interfaces → VLANs: Create VLAN 10, 20, 30, 40
  2. Interfaces → Assignments: Assign OPT1–4 to each VLAN
  3. Services → DHCP Server: Configure DHCP for each VLAN
  4. Services → DNS Resolver: Conditional forward (homelab.local → 192.168.10.10)

Phase 2: Samba AD DC Deployment

Ubuntu Server VM:

  • VLAN: 10 (Infra)
  • IP: 192.168.10.10/24 (static)
  • Hostname: dc1
  • FQDN: dc1.homelab.local

Network Configuration (/etc/netplan/00-installer-config.yaml):

network:
  version: 2
  ethernets:
    ens18:
      dhcp4: no
      addresses:
        - 192.168.10.10/24
      routes:
        - to: default
          via: 192.168.10.1
      nameservers:
        addresses:
          - 127.0.0.1

Apply:

sudo netplan apply

Install Samba 4 AD DC:

sudo apt update
sudo apt install samba krb5-user winbind dnsutils -y

sudo systemctl stop smbd nmbd winbind
sudo systemctl disable smbd nmbd winbind

sudo samba-tool domain provision \
  --realm HOMELAB.LOCAL \
  --domain HOMELAB \
  --server-role dc \
  --dns-backend SAMBA_INTERNAL \
  --dns-forwarder 1.1.1.1

sudo cp -f /var/lib/samba/private/krb5.conf /etc/krb5.conf

sudo systemctl unmask samba-ad-dc
sudo systemctl enable samba-ad-dc
sudo systemctl start samba-ad-dc

# Verify
samba-tool domain level show

Phase 3: Firewall Rules Configuration

Create RFC1918 Alias:

Web UI → Firewall → Aliases → IP → Add

Name: RFC1918
Description: Private IPv4 networks
Type: Network(s)

Networks:
  10.0.0.0/8
  172.16.0.0/12
  192.168.0.0/16

VLAN 40 (DMZ) Rules:

Web UI → Firewall → Rules → OPT4(LAN_DMZ)

  1. Allow DNS outbound
  2. Allow HTTP/HTTPS outbound
  3. Block RFC1918 (all internal networks)
  4. Allow intra-DMZ communication

🚀 Services & Deployment

Nginx in DMZ (Backend Service)

VM: 192.168.40.50 (VLAN 40)
Role: Standard Web Server (proxied by Traefik)

# On DMZ VM (.50)
sudo apt update
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

# Verify locally
curl http://localhost
# Expected: "Welcome to Nginx!"

🚦 Traefik Reverse Proxy Deployment

VM: 192.168.40.40 (VLAN 40 - DMZ)
Role: Central Entry Point & Reverse Proxy for all DMZ services

Why Traefik?

  • Automatic SSL with self-signed certs (Let's Encrypt ready)
  • Dynamic routing to multiple backend services
  • Dashboard for monitoring routes & services
  • Single entry point from WAN (simplifies NAT)

1. Update pfSense Port Forwarding (NAT)

Important: Redirect WAN traffic to Traefik (not Nginx directly anymore).

Firewall → NAT → Port Forward:

HTTP (Port 80):

Interface: WAN
Protocol: TCP
Destination: WAN address
Dest. Port: 80

Redirect Target IP: 192.168.40.40 (Traefik)
Redirect Target Port: 80

Add Filter Rule: ✓
Description: NAT HTTP → Traefik Proxy

HTTPS (Port 443):

Interface: WAN
Protocol: TCP
Destination: WAN address
Dest. Port: 443

Redirect Target IP: 192.168.40.40 (Traefik)
Redirect Target Port: 443

Add Filter Rule: ✓
Description: NAT HTTPS → Traefik Proxy

2. Directory Structure

On VM 192.168.40.40:

mkdir -p ~/traefik/dynamic
cd ~/traefik
touch docker-compose.yml traefik.yml dynamic/external_services.yml acme.json
chmod 600 acme.json

3. Docker Compose Configuration

File: ~/traefik/docker-compose.yml

services:
  traefik:
    image: traefik:v3.6  # v3.6+ required for Docker API v1.44 compatibility
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
      # - "8080:8080" # Uncomment for dashboard (insecure, local only)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./dynamic:/dynamic:ro
      - ./acme.json:/acme.json
    networks:
      - proxy

networks:
  proxy:
    name: proxy_network

4. Static Configuration

File: ~/traefik/traefik.yml

api:
  dashboard: true
  insecure: false  # Set to true ONLY for local debugging

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https  # Auto-redirect HTTP → HTTPS

  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false  # Security: explicit opt-in per container
  file:
    directory: "/dynamic"
    watch: true  # Auto-reload dynamic config files

# Optional: Let's Encrypt (for public domains only)
# certificatesResolvers:
#   myresolver:
#     acme:
#       email: your-email@example.com
#       storage: acme.json
#       httpChallenge:
#         entryPoint: web

5. Dynamic Configuration (External Services)

File: ~/traefik/dynamic/external_services.yml

This file connects Traefik (192.168.40.40) to Nginx (192.168.40.50):

http:
  routers:
    nginx-router:
      # Option 1: Accept all traffic (simple, for lab)
      rule: "PathPrefix(`/`)"
      
      # Option 2: Strict by IP/Domain (recommended)
      # rule: "Host(`192.168.40.40`) || Host(`192.168.40.50`) || Host(`mysite.homelab.local`)"
      
      service: nginx-service
      entryPoints:
        - websecure
      tls: {}  # Self-signed cert by default (Traefik Default Cert)

  services:
    nginx-service:
      loadBalancer:
        servers:
          - url: "http://192.168.40.50:80"

6. Start Traefik

cd ~/traefik
docker compose up -d

# Verify logs
docker compose logs -f

7. Verify Architecture

Test from DMZ VM (192.168.40.50):

curl -k https://192.168.40.40
# Expected output: "Welcome to Nginx!" (HTML)

Test from external network (if WAN forwarding is active):

curl -k https://YOUR_PUBLIC_IP
# Expected output: "Welcome to Nginx!"

Traffic Flow:

Internet → pfSense (NAT) → Traefik (.40) → Nginx (.50) → Response

8. Adding More Services

To add a new backend service (e.g., n8n, API, dashboard), simply add a new router in dynamic/external_services.yml:

http:
  routers:
    nginx-router:
      rule: "Host(`192.168.40.40`)"
      service: nginx-service
      entryPoints:
        - websecure
      tls: {}

    n8n-router:
      rule: "Host(`n8n.homelab.local`)"
      service: n8n-service
      entryPoints:
        - websecure
      tls: {}

  services:
    nginx-service:
      loadBalancer:
        servers:
          - url: "http://192.168.40.50:80"
    
    n8n-service:
      loadBalancer:
        servers:
          - url: "http://192.168.20.10:5678"  # Example: n8n in VLAN 20

🐛 Advanced Features & Troubleshooting

Traefik Issues

Error: client version 1.24 is too old. Minimum supported API version is 1.44

Cause: Docker daemon v29+ requires API v1.44, but Traefik v3.0–v3.5 negotiates with older API.

Fix: Upgrade Traefik image to v3.6 or higher in docker-compose.yml:

image: traefik:v3.6

Then:

docker compose pull
docker compose up -d --force-recreate

Error: 404 page not found

Cause: Host() rule in dynamic config doesn't match the request's Host header.

Debugging:

  1. Check what Host header you're sending:

    curl -v https://192.168.40.40
    # Look for: > Host: 192.168.40.40
  2. Update rule in external_services.yml to match:

    rule: "Host(`192.168.40.40`)"
    # OR accept everything:
    rule: "PathPrefix(`/`)"
  3. Traefik auto-reloads dynamic configs (check logs to confirm).


Error: unable to generate a certificate for domains [192.168.40.50]: IP address is in reserved address block [RFC1918]

Cause: Let's Encrypt refuses to issue certificates for private IPs or .local domains.

Fix for Lab Environment:

Remove certResolver: myresolver from your router config and use Traefik's default self-signed certificate:

tls: {}  # No certResolver

Fix for Production (Public Domain Required):

  1. Own a public domain (e.g., mylab.com)
  2. Create DNS A record pointing to your public IP
  3. Ensure ports 80/443 are forwarded through your ISP router → pfSense → Traefik
  4. Use certResolver: myresolver in router config

Connectivity Tests

Verify Traefik can reach Nginx:

docker exec traefik ping -c 3 192.168.40.50
# Expected: 3 packets received, 0% loss

Check if Traefik is loading dynamic config:

docker compose logs -f | grep -i "dynamic\|nginx"
# Should show no errors about external_services.yml

Samba AD DC Issues

DNS not resolving:

# On DC
sudo systemctl status samba-ad-dc
dig @127.0.0.1 dc1.homelab.local

# On client
nslookup dc1.homelab.local 192.168.10.10

Backup domain:

sudo samba-tool domain backup online --targetdir=/backup

📈 Future Enhancements

Short-term (1–3 months)

  • Traefik Dashboard secured with authentication
  • Let's Encrypt integration for public domain
  • Secondary DC for redundancy
  • WireGuard VPN for remote access
  • Automated backups (VM snapshots + Samba domain)

Medium-term (3–6 months)

  • Additional services behind Traefik (n8n, Uptime Kuma, Grafana)
  • Log aggregation (ELK stack)
  • Monitoring (Prometheus + Grafana)
  • Container orchestration (Docker Swarm / K3s)

Long-term (6+ months)

  • Kubernetes cluster (k3s) in VLAN 20
  • IDS/IPS (Suricata) on pfSense
  • Advanced threat simulation lab
  • Multi-site VPN mesh

📚 Documentation Index

Detailed technical guides provided:

File Topic
Docs_01_pfsense_HyperV.txt pfSense initial setup & architecture overview
Docs_02_pfsense_HyperV.txt Network design & VLAN strategy
Docs_03_pfsense_HyperV.txt Address plan & VLAN configuration
Docs_04_Set_HyperV_Trunk.txt Hyper-V trunk mode setup (PowerShell)
Docs_05_Set_pfSense_FW_Rules.txt Firewall rules for Infra VLAN
Docs_06_Set_pfSense_FW_Rules_DMZ.txt DMZ rules & RFC1918 alias
Docs_07_Set_pfSense_FW_Rules_DMZ.txt Port forwarding & NAT config
Docs_08_Set_Nginx_WebServer.txt Nginx installation & basic config
Docs_09_Rename_dc_Server.txt Hostname management for AD DC
Docs_10_Deploy_Samba_DC.txt Complete Samba AD DC deployment
Docs_11_Deploy_Samba_DC_OU_Archi.txt AD organizational unit design

📞 References & Resources

Official Documentation

Security Standards

Community Resources


⚖️ License

This documentation and configuration examples are provided as-is for educational and personal use.

Use at your own discretion and risk.


📝 Project Status

Component Status Notes
pfSense Setup ✅ Complete Stable, VLAN-configured
AD DC (Samba) ✅ Complete Functional, OUs created
Firewall Rules ✅ Complete Default-deny, all VLANs
DMZ Isolation ✅ Complete Tested & verified
DNS & DHCP ✅ Complete Conditional forwarding active
Nginx (HTTP) ✅ Complete Backend service running
Traefik (Reverse Proxy) Complete Centralized routing active
NAT ✅ Complete WAN → Traefik → Nginx functional
Monitoring ⏳ Planned Prometheus/Grafana
HA/Replication ⏳ Planned Secondary DC, redundancy
VPN ⏳ Planned WireGuard/IPsec

👤 Maintainer

System Engineer
🍜 Noodle Enthusiast | ⛰️ Mountain Lover | ⛩️ Shinto Sanctuary Visitor | 🍫 Chocolate Aficionado

Location: Brussels, Belgium
Last Updated: December 31, 2025
Version: 2.0 (with Traefik integration)


Enjoy your homelab! 🚀

About

**A complete, production-ready home laboratory infrastructure based on pfSense, Hyper-V, Samba AD, VLANs, and DMZ isolation with Traefik reverse proxy.**

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published