Small Business Linux Network — End-to-End Configuration

Scenario. One Linux box acts as a router / firewall / DHCP / DNS. It trunks VLANs to a managed switch: USERS (VLAN10), SERVERS (VLAN20), MGMT (VLAN99). We use nftables for firewall/NAT, dnsmasq for DHCP/DNS, and systemd-networkd (with Netplan and NetworkManager alternatives shown). Commands are Debian/Ubuntu-oriented but portable.

1) Addressing & Plan

Private IPv4 (RFC1918)

  • 10.0.0.0/8
  • 172.16.0.0/12 (172.16.0.0–172.31.255.255)
  • 192.168.0.0/16

These are non-routed on the public Internet by design (use one range and subnet it).

Private IPv6 (ULA, RFC4193)

Choose a ULA /48 from fd00::/8 (e.g., fd12:3456:789a::/48). Use one /64 per VLAN for SLAAC.

  • VLAN10: fd12:3456:789a:10::/64
  • VLAN20: fd12:3456:789a:20::/64
  • VLAN99: fd12:3456:789a:99::/64

Example Subnets & Gateways

2) Topology

                 Internet / ISP
                       |
                 [ WAN: eth0 ]
              Linux Router / Firewall
                 [ LAN: eth1 trunk ]
                 /         |          \
            VLAN10      VLAN20       VLAN99
             USERS       SERVERS       MGMT
        192.168.10.0/24 192.168.20.0/24 192.168.99.0/24
        fd12:...:10::/64 fd12:...:20::/64 fd12:...:99::/64
  

3) Router: Base System Prep

  1. Packages:
    sudo apt update
    sudo apt install -y nftables dnsmasq iproute2 bridge-utils vlan net-tools
  2. Enable IP forwarding (IPv4 & IPv6):
    sudo tee /etc/sysctl.d/99-router.conf <<'EOF'
    net.ipv4.ip_forward=1
    net.ipv6.conf.all.forwarding=1
    EOF
    sudo sysctl --system
  3. Quick checks:
    ip -br link
    ip -br addr
    ip route && ip -6 route
    nft list ruleset || true

4) Router: VLAN Interfaces & IPs

Assume eth1 is a trunk to your managed switch. Define VLAN subinterfaces with systemd-networkd:

# /etc/systemd/network/10-eth1.network
[Match]
Name=eth1
[Network]
VLAN=eth1.10
VLAN=eth1.20
VLAN=eth1.99

# /etc/systemd/network/20-eth1.10.netdev
[NetDev]
Name=eth1.10
Kind=vlan
[VLAN]
Id=10

# /etc/systemd/network/21-eth1.20.netdev
[NetDev]
Name=eth1.20
Kind=vlan
[VLAN]
Id=20

# /etc/systemd/network/22-eth1.99.netdev
[NetDev]
Name=eth1.99
Kind=vlan
[VLAN]
Id=99

# /etc/systemd/network/30-vlan10.network
[Match]  Name=eth1.10
[Network]
Address=192.168.10.1/24
Address=fd12:3456:789a:10::1/64

# /etc/systemd/network/31-vlan20.network
[Match]  Name=eth1.20
[Network]
Address=192.168.20.1/24
Address=fd12:3456:789a:20::1/64

# /etc/systemd/network/32-vlan99.network
[Match]  Name=eth1.99
[Network]
Address=192.168.99.1/24
Address=fd12:3456:789a:99::1/64

Apply: sudo systemctl restart systemd-networkd

Alternative: Netplan (renderer: networkd)
# /etc/netplan/01-router.yaml
network:
  version: 2
  renderer: networkd
  ethernets: { eth1: {} }
  vlans:
    vlan10:
      id: 10
      link: eth1
      addresses: [192.168.10.1/24, fd12:3456:789a:10::1/64]
    vlan20:
      id: 20
      link: eth1
      addresses: [192.168.20.1/24, fd12:3456:789a:20::1/64]
    vlan99:
      id: 99
      link: eth1
      addresses: [192.168.99.1/24, fd12:3456:789a:99::1/64]
# Then:
sudo netplan apply

5) Router: DHCP, DNS, and IPv6 RA (dnsmasq)

# /etc/dnsmasq.d/smb.conf
# GENERAL
domain-needed
bogus-priv
no-resolv
server=1.1.1.1
server=9.9.9.9

# VLAN10 (USERS) DHCPv4
interface=eth1.10
dhcp-range=eth1.10,192.168.10.50,192.168.10.250,255.255.255.0,12h
dhcp-option=tag:eth1.10,option:router,192.168.10.1
dhcp-option=tag:eth1.10,option:dns-server,192.168.10.1

# VLAN20 (SERVERS) DHCPv4 (optional; servers may be static)
interface=eth1.20
dhcp-range=eth1.20,192.168.20.50,192.168.20.200,255.255.255.0,12h
dhcp-option=tag:eth1.20,option:router,192.168.20.1
dhcp-option=tag:eth1.20,option:dns-server,192.168.20.1

# IPv6 RA + DHCPv6 (stateless) for both VLANs
interface=eth1.10
dhcp-range=fd12:3456:789a:10::,ra-stateless,ra-names,12h
interface=eth1.20
dhcp-range=fd12:3456:789a:20::,ra-stateless,ra-names,12h

# Optional static leases (example)
# dhcp-host=AA:BB:CC:DD:EE:FF,host123,192.168.20.10

Enable and reload:

sudo systemctl enable dnsmasq
sudo systemctl restart dnsmasq

6) Router: Firewall & NAT (nftables)

# /etc/nftables.conf
flush ruleset
table inet filter {
  sets {
    lan_ifaces { type ifname; elements = { "eth1.10", "eth1.20", "eth1.99" } }
  }
  chains {
    input {
      type filter hook input priority 0;
      policy drop;
      ct state established,related accept
      iif lo accept
      # Allow DHCP/DNS from LANs
      iifname @lan_ifaces udp dport {67, 53} accept
      iifname @lan_ifaces tcp dport 53 accept
      # Allow SSH from MGMT only
      iif "eth1.99" tcp dport 22 accept
    }
    forward {
      type filter hook forward priority 0;
      policy drop;
      ct state established,related accept
      # Inter-VLAN policy (example: USERS <-> SERVERS allowed to 80/443/22 only)
      iif "eth1.10" oif "eth1.20" tcp dport {22,80,443} accept
      iif "eth1.20" oif "eth1.10" tcp dport {80,443} accept
      # LANs to WAN allowed
      iifname @lan_ifaces oif "eth0" accept
    }
    output {
      type filter hook output priority 0;
      policy accept;
    }
  }
}
table ip nat {
  chains {
    prerouting { type nat hook prerouting priority -100; }
    postrouting {
      type nat hook postrouting priority 100;
      # Masquerade IPv4 from LANs to WAN
      oif "eth0" ip saddr { 192.168.10.0/24, 192.168.20.0/24, 192.168.99.0/24 } masquerade
    }
  }
}

Apply & persist:

sudo systemctl enable nftables
sudo systemctl restart nftables

7) Switch & AP Notes (brief)

8) Server Configuration (static IPs)

Option A — Netplan (Ubuntu Server)
# /etc/netplan/01-ensX.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    ensX:
      addresses: [192.168.20.10/24, fd12:3456:789a:20::10/64]
      nameservers:
        addresses: [192.168.20.1, fd12:3456:789a:20::1]
      routes:
        - to: 0.0.0.0/0
          via: 192.168.20.1
        - to: ::/0
          via: fd12:3456:789a:20::1
# then
sudo netplan apply
Option B — NetworkManager (nmcli)
# Replace ethX with actual device name
nmcli con add type ethernet ifname ethX con-name srv-static ipv4.addresses 192.168.20.10/24 \
  ipv4.gateway 192.168.20.1 ipv4.dns "192.168.20.1" ipv4.method manual \
  ipv6.addresses fd12:3456:789a:20::10/64 ipv6.gateway fd12:3456:789a:20::1 \
  ipv6.dns fd12:3456:789a:20::1 ipv6.method manual
nmcli con up srv-static
Option C — Raw ip (temporary)
sudo ip addr add 192.168.20.10/24 dev ethX
sudo ip -6 addr add fd12:3456:789a:20::10/64 dev ethX
sudo ip route replace default via 192.168.20.1
sudo ip -6 route replace default via fd12:3456:789a:20::1

9) Workstation Configuration (DHCP)

NetworkManager (typical desktop)
nmcli dev status             # find device (e.g., eth0 or wlan0)
nmcli con add type ethernet ifname eth0 con-name dhcp-auto ipv4.method auto ipv6.method auto
nmcli con up dhcp-auto
Systemd-networkd (thin clients / kiosks)
# /etc/systemd/network/10-dhcp.network
[Match]
Name=eth0
[Network]
DHCP=yes
IPv6AcceptRA=yes
# then:
sudo systemctl restart systemd-networkd

10) Verification

# From a client on VLAN10
ip addr
ip route
ping -c3 192.168.10.1
ping -c3 1.1.1.1
ping -c3 google.com
dig @192.168.10.1 example.com
curl -I https://example.com

# From the router
ip -br addr
ip route && ip -6 route
nft list ruleset
journalctl -u dnsmasq --since "10 min ago"

11) Troubleshooting Cheats

12) Minimal Security Policy Ideas


References (APA)

  1. IETF. (1996). RFC 1918: Address Allocation for Private Internets. Internet Engineering Task Force.
  2. IETF. (2005). RFC 4193: Unique Local IPv6 Unicast Addresses. Internet Engineering Task Force.
  3. Systemd Project. (n.d.). systemd-networkd, systemd.netdev, systemd.network (man pages). Freedesktop.org.
  4. Netplan.io. (n.d.). Netplan reference documentation.
  5. Netfilter Project. (n.d.). nftables — Packet filtering framework (documentation).
  6. Dnsmasq Project. (n.d.). dnsmasq: DNS forwarder and DHCP server (man page & docs).
  7. iproute2 Maintainers. (n.d.). ip(8), ip-address(8), ip-link(8), ip-route(8) (man pages).