Due to the fact that I’m a tinkerer by nature I like to have space to experiment with technology. In many cases that involves opensource or cloud-native technologies. This article describes how I implimented network setup for my environments.
The homelab consists of four different ipv4 and ipv6 subnets where three of them are related to the homelab “playgrounds”/environments if you will and one is for the local home network and is not documented in this article. The remainder of the article is more of step guide what I needed todo to accomplish the task.
The basic network assignments
# | Name | ipv4 | ipv6 |
---|---|---|---|
1 | Homelab 10 | 192.168.10.0 | 2a01:b00b:469f:a115::/64 |
2 | Homelab 20 | 192.168.20.0 | 2a01:b00b:469f:a116::/64 |
3 | Homelab 30 | 192.168.30.0 | 2a01:b00b:469f:a117::/64 |
Creating the VLAN’s
Setup of three vlan’s for the environments so that I can keep them isolated. The main purpose is that I want to be able to play around without accidentally interfere with other setups in my lab. This gives me safe spaces to “F**k things up” ;-)
/interface vlan
add comment="Homelab 10" interface=bridge name=vlan-homelab-10 vlan-id=10
add comment="Homelab 20" interface=bridge name=vlan-homelab-20 vlan-id=20
add comment="Homelab 30" interface=bridge name=vlan-homelab-30 vlan-id=30
Defining vlan’s as LAN interfaces in the interface member list
I am using rules called LAN
and WAN
in my mikrotik router that are used with firewall rules for example to ban traffic that is not coming from LAN
and so forth.
/interface list member
add comment="Homelab 10" interface=vlan-homelab-10 list=LAN
add comment="Homelab 20" interface=vlan-homelab-20 list=LAN
add comment="Homelab 30" interface=vlan-homelab-30 list=LAN
Defining ip numbers on the router
Attach ip number per vlan on the router so that we can activate dhcp server for the respective nets.
/ip address
add comment="Homelab 10" address=192.168.10.1/24 interface=vlan-homelab-10 network=192.168.10.0
add comment="Homelab 20" address=192.168.20.1/24 interface=vlan-homelab-20 network=192.168.20.0
add comment="Homelab 30" address=192.168.30.1/24 interface=vlan-homelab-30 network=192.168.30.0
Defining address pool’s
Set up address pool per environment where the dhcp range is from 100-200 in each subnet.
/ip pool
add comment="Homelab 10" name=pool-homelab-10 ranges=192.168.10.100-192.168.10.200
add comment="Homelab 20" name=pool-homelab-20 ranges=192.168.20.100-192.168.20.200
add comment="Homelab 30" name=pool-homelab-30 ranges=192.168.30.100-192.168.30.200
Define ipv4 dhcp server per vlan
Here I am using the
dhcp2dns
script to create dns entries per dhcp lease. See script at the end of this post for details.
/ip dhcp-server
add add-arp=yes address-pool=pool-homelab-10 interface=vlan-homelab-10 lease-script=dhcp2dns name=dhcp-homelab-10
add add-arp=yes address-pool=pool-homelab-20 interface=vlan-homelab-20 lease-script=dhcp2dns name=dhcp-homelab-20
add add-arp=yes address-pool=pool-homelab-30 interface=vlan-homelab-30 lease-script=dhcp2dns name=dhcp-homelab-30
Defining ipv4 network per vlan
Set up of dhcp server per subnet that utilises the definitions below.
/ip dhcp-server network
add comment="Homelab 10" address=192.168.10.0/24 dns-server=192.168.10.1 domain=lab10.samueljon.tech gateway=192.168.10.1 netmask=24
add comment="Homelab 20" address=192.168.20.0/24 dns-server=192.168.20.1 domain=lab20.samueljon.tech gateway=192.168.20.1 netmask=24
add comment="Homelab 30" address=192.168.30.0/24 dns-server=192.168.30.1 domain=lab30.samueljon.tech gateway=192.168.30.1 netmask=24
Defining ipv6 network per vlan
Of course we would like to use ipv6 as well. That is accomplished by creating ipv6 address pool.
/ipv6 pool
add comment="Homelab 10" name=pool-ipv6-homelab-10 prefix=2a01:b00b:469f:a115::/64 prefix-length=64
add comment="Homelab 20" name=pool-ipv6-homelab-20 prefix=2a01:b00b:469f:a116::/64 prefix-length=64
add comment="Homelab 30" name=pool-ipv6-homelab-30 prefix=2a01:b00b:469f:a117::/64 prefix-length=64
In order for SLAAC assignment can take place, we will have to add ipv6 address on the vlan interfaces and assign ipv6 address pool to it.
Default behaviour is to advertise the Stateless Address Auto-Configuration (SLAAC) from a subnet.
/ipv6 address
add address=::1 from-pool=pool-ipv6-homelab-10 interface=vlan-homelab-10
add address=::1 from-pool=pool-ipv6-homelab-20 interface=vlan-homelab-20
add address=::1 from-pool=pool-ipv6-homelab-30 interface=vlan-homelab-30
DHCP2DNS script
The DHCP2DNS is not created by me but copied with pride and modified. The purpose of the script is to create dns entries for ipv4 addresses when they get assigned. I am not sure who the author was but it came from one of the mikrotik’s user forums. Kudos to the person that created the script.
/system script
add dont-require-permissions=no name=dhcp2dns owner=admin policy=read,write source=" ###\
\n# Script entry point\
\n#\
\n# Expected environment variables - set internally when calling the lease script:\
\n# leaseBound 1 = lease bound, 0 = lease removed\
\n# leaseServerName Name of DHCP server\
\n# leaseActIP IP address of DHCP client\
\n# leaseActMAC MAC address of DHCP client\
\n# lease-hostname Host name provided by the DHCP client\
\n# lease-options DHCP options provided by the client\
\n###\
\n:local leaseHostName \$\"lease-hostname\"\
\n:local leaseOptions \$\"lease-options\"\
\n# DNS TTL to set for DNS entries\
\n:local dnsttl \"00:10:00\"\
\n\
\n### Utility functions ###\
\n\
\n# Generates a host name from an IP address, ie:\
\n# \"192.168.1.10\" -> \"192-168-1-10\"\
\n# Used as a replacement for missing host names\
\n# param: ip\
\n:local ip2Host do={\
\n :local ipNum [ :tonum [ :toip \$ip ] ]\
\n :return (((\$ipNum >> 24) & 255) . \"-\" . ((\$ipNum >> 16) & 255) . \"-\" . ((\$ipNum >> 8) & 255) . \"-\" . (\$ipNum & 255))\
\n}\
\n\
\n# Sanitizes a host name: length <= 63, allowed chars a-z,0-9,-\
\n# param: name\
\n:local mapHostName do={\
\n :local allowedChars \"abcdefghijklmnopqrstuvwxyz0123456789-\"\
\n :local numChars [ :len \$name ]\
\n :if (\$numChars > 63) do={ :set numChars 63 }\
\n :local result \"\"\
\n\
\n :for i from=0 to=(\$numChars - 1) do={\
\n :local char [ :pick \$name \$i ]\
\n :if ([ :find \$allowedChars \$char ] < 0) do={ :set char \"-\" }\
\n :set result (\$result . \$char)\
\n }\
\n :return \$result\
\n}\
\n\
\n# Converts a host name to all-lower-case\
\n# param: entry\
\n:local lowerCase do={\
\n :local lower \"abcdefghijklmnopqrstuvwxyz\"\
\n :local upper \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\
\n :local result \"\"\
\n :for i from=0 to=([ :len \$entry ] - 1) do={\
\n :local char [ :pick \$entry \$i ]\
\n :local pos [ :find \$upper \$char ]\
\n :if (\$pos > -1) do={ :set char [ :pick \$lower \$pos ] }\
\n :set result (\$result . \$char)\
\n }\
\n :return \$result\
\n}\
\n\
\n###\
\n\
\n:local token \"\$leaseServerName-\$leaseActMAC\"\
\n:local LogPrefix \"DHCP2DNS (\$leaseServerName) [\$leaseActMAC]\"\
\n\
\n:if ([ :len \$leaseActIP ] <= 0) do={\
\n :log error \"\$LogPrefix: empty lease address\"\
\n :error \"empty lease address\"\
\n}\
\n\
\n:if (\$leaseBound = 1) do={\
\n /ip dhcp-server network\
\n :local domain [ get [ :pick [ find \$leaseActIP in address ] 0 ] domain ]\
\n :local hostname \$leaseHostName\
\n\
\n :if ([ :len \$hostname ] > 0) do={\
\n :set hostname [ \$lowerCase entry=\$hostname ]\
\n :set hostname [ \$mapHostName name=\$hostname ]\
\n } else={\
\n :set hostname [ \$ip2Host ip=\$leaseActIP ]\
\n }\
\n\
\n :if ([ :len \$domain ] <= 0) do={\
\n :log warning \"\$LogPrefix: Empty domainname for '\$leaseActIP', cannot create static DNS name\"\
\n :error \"Empty domainname for '\$leaseActIP'\"\
\n }\
\n\
\n :local fqdn (\$hostname . \".\" . \$domain)\
\n\
\n /ip dns static\
\n :local entry [ find name=\$fqdn ]\
\n :if ( \$entry ) do={\
\n :if ([ get \$entry comment ] = \$token) do={\
\n :log warning \"\$LogPrefix: Updating existing entry for \$fqdn\"\
\n set \$entry address=\$leaseActIP ttl=\$dnsttl comment=\$token\
\n } else={\
\n :log warning \"\$LogPrefix: Conflicting entry for \$fqdn already exists, not updating\"\
\n }\
\n } else={\
\n :local placeholderComment \"--- \$leaseServerName dhcp2dns above ---\"\
\n :if ( [ :len [ find comment=\$placeholderComment ] ] = 0 ) do={\
\n add comment=\$placeholderComment name=- type=NXDOMAIN disabled=yes\
\n }\
\n :local placeholder [ find where comment=\$placeholderComment ]\
\n\
\n :log info \"\$LogPrefix: Adding entry for \$fqdn\"\
\n add address=\$leaseActIP name=\$fqdn ttl=\$dnsttl comment=\$token place-before=\$placeholder\
\n }\
\n} else={\
\n /ip dns static remove [ find comment=\$token ]\
\n}"
Credits
Photo by Albert Stoynov on Unsplash