In the context of a more and more automated and digitalized world, the network defaults might not just be enough. With some pretty basic ideas, we could harden the security easy enough.
Typical home networks offer a single entry point to the network for every device and allow unrestricted interactions between devices.
In a really dark assumption, your smart fridge has the ability to scan your network and download any photos of you and your loved ones and publish them somewhere over the internet.
In other words, IoT devices where you don't have too much control over what they do can scan your network, together with the work laptop and any guest device. Even assuming that your providers have the best intentions, they still have their own vulnerabilities which you might inherit.
Our solution to this problem is to make a set of rules, mainly based on the principle of least privilege. So we will aim for a zero trust network where what is allowed is explicitly defined. Apart from that, we will aim for some basic security hardening.
The commands and screenshots in this article are mainly for using a Mikrotik hAP ax3 device running RouterOS version 7. But following the principles described, you can adapt the commands to your network specs.
To have the smooth transition to the new network, we will keep the old configuration, define another one, then move the devices to the new one, test that everything is fine, then remove the old configuration.
Ask GPT
In the past few years, AI has been a part of our lives and has evolved into being really useful. I think we are still far from being replaced by AI, but we are even further from working without it. With the knowledge and the "overview context window" humans have, we can get to good results much-much faster.
Thus, it's essential to use it:
I own a Mikrotik hAP ax3 which is at the root of my network. I have a work computer, a personal windows laptop, a personal macbook, a nas, a chromecast and two raspberry pis. I own an android phone. I also own a printer.
one of the raspberry pis contains some services like owncloud, other docker apps and the pihole which is used for dns by the router.
apart from all these I have another cudy router for which I would like a connection to the home network when the traveling. right now I have a direct connection from my macbook to the pi with tailscale, but I want this improved in the future.
I want the work computer isolated from my network. I want a configuration for my network with separation of concerns for high security (e.g. my laptop computer should be isolated from any resources, same for the devices visiting), but be able to add easily new devices I own.
I currently have the base configuration with 2.4g and 5g wifis for the router with a lan connection to the ISP for internet, via PPP. I am thinking that only one network called Parallax, which by default separates the devices and only allows internet for each device. Then, some groups could be created where the computers be assigned manually by mac, e.g. a group which will be able to access everything and the mikrotik admin interface, a group which will be able to access everything, a group which will be able to access only the printer, a group which will be able to access the printer and the router etc. I also want one lan port which will automatically allow access to all resources of the network, including the mikrotik admin interface.
I want my IPs to start with 10.x.x.x and I want them grouped by the group they are a part of. also, I want the lan IPs identifiable.
first of all, ask me one my one questions you need for clarifying my request. when you are clear on what I want, ask me if I want to add anything else, then explain how do implement the solution. I prefer the command line, but for each operation also explain how to do the changes in the web interface.
I asked this of OpenAI's ChatGPT, but any might suffice. Please know the "ask me one my one questions you need for clarifying my request" which has often proven useful for me.
This is a pretty basic prompt, which has the main goal of describing the situation. It lacks the "You are a security and network expert.." intro, as lately the big players in the AI field do good without it, as well.
Such a prompt will help you with clarifying the problem you want to fix and often give you good pointers and advice.
Solution overview
What we aim to implement is grouping for devices and isolating them from the other groups. We could do this by creating separate networks, which is the most secure approach, but comes with the main downfall that if you need to create exceptions, you need to add new networks and move the devices from one network to another.
Our approach is to have a single point of entry where all devices connect and allow them only access to the internet by default. Then, based on the MAC of each device, assign them to groups.
So we will keep in mind the following principles:
- default deny (least priviledge) - this is the root idea of the changes that we want to implement, mainly allow
LAN -> Internet, but disallowLAN -> LAN; - segmentation - separate the devices in groups created by trust levels, not device types;
- control east-west traffic - by keeping ports closed and other methods, routers protect the network form the outside world, but not from internal attacks;
- minimize broadcast exposure - broadcast protocols (mDNS, SSDP, NetBIOS, ARP) can leak information and this is a known risk in the model we are using, mainly for convenience, especially since this is a home network;
- protect infrastructure devices and the Control Plane - e.g. the router should not be accessible to any device;
- separate identity from connectivity - this is another known risk for our implementation, mainly because we use the MAC for identity, which can be spoofed. However, for convenience, we will allow this;
- secure the DNS layer - this is a big attack surface, so we should pay close attention to it. We will implement a PI hole with secure DNS fallbacks;
- reduce attack surfaces - reduce the number of open ports from services in the network;
- logging and visibility - make sure we have a mechanism for detecting malfunctions;
- patch and update - keep your systems as up to date as possible;
- backup configurations
The groups we will create are:
- Core - trusted devices which can also access the router admin;
- All - most of the devices in the network;
- Virtual - we will have virtual machines and to easily identify them, they will be a part of this group;
- Guest - IoT devices and the work laptops, the default rights. A future improvement could be to move these to completely separated network, for higher security.
Create the network
The first step for the implementation is to create the network. For that, we need a network name. The chosen one for our network will be Parallax, a villain in the DC Universe and also a beloved effect back in the jQuery days. 🙂
Read more:
- https://en.wikipedia.org/wiki/Parallax_(character)
- https://pixelcog.github.io/parallax.js/
- https://www.space.com/30417-parallax.html
The proper way to create the network is to add another one in parallel, implement the configuration we want, connect our devices to the new network, then sunset the old one.
However, this is my home network where downtime doesn't really matter. So to save time, I will go with resetting the router to the defaults and then adding the new network.
The router defaults to 192.168.88.1, which we will change to a 10.x.x.x.
With Mikrotik it can be done in the quick set interface. Change the IP address for the router, but remember to change the DHCP Server Range as well, otherwise you might have trouble connecting to the admin interface.
Read more:
Implement the segmentation
The first choice we have to make is between having a single SSID (Parallax) or having multiple SSIDs (Parallax, Parallax-IoT, Parallax-Guest etc). With multiple SSIDs, the security is slightly better, but you lose some of the control you have over how the connected devices interact.
Thus, the choice is to have only one SSID. Optionally, later we could add Parallax-Guest, to make sure the devices which are unknown don't have access to anything in the network. We will also use an L3 zero trust, which means that we will not have VLANs, which means that devices will still be able to discover each other, but will not be able to "talk" to each other.
The default rules we will implement are the following:
- all devices can access the interent;
- any device cannot access anything in the network.
The exceptions will be established via groups, by manually assigning IPs to MAC addresses.
The IP address architecture is the following:
- 10.10.0.0/24
- group name:
core; - has full access to the network and can also access the router admin;
- for ethernet connections, we will start with 100 (e.g. 10.10.0.102) and wifi will be at the beginning (e.g. 10.10.0.4);
- group name:
- 10.20.0.0/24
- group name:
all; - these are the trusted devices which can access the whole network and talk to each other;
- for ethernet connections, we will start with 100 (e.g. 10.20.0.102) and wifi will be at the beginning (e.g. 10.20.0.4);
- group name:
- 10.30.0.0/24
- group name:
virtual; - we will set the virtual machine hosts in the all group, but each of the VMs will be in the virtual group;
- reserved for VMs / containers;
- group name:
- 10.40.0.0/24
- group name:
guest; - can only access the internet.
- group name:
Access matrix for groups:
| From ↓ / To → | Core | All | Virtual | Guest | Internet | Router |
|---|---|---|---|---|---|---|
| Core | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| All | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Virtual | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ |
| Guest | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
IP addressing
Set the IP addressing (core is already set):
/ip address
add address=10.20.0.1/24 interface=bridge comment=All
add address=10.30.0.1/24 interface=bridge comment=Virtual
add address=10.40.0.1/24 interface=bridge comment=GuestCode language: PHP (php)
DHCP
Set the guest pool:
/ip pool
add name=guest_pool ranges=10.40.0.100-10.40.0.254
Then set the DHCP server:
/ip dhcp-server
add name=dhcp1 interface=bridge address-pool=guest_pool lease-time=12hCode language: PHP (php)
In case you get something like failure: server or relay with such interface already exists, then:
# check the dhcp server info
/ip dhcp-server print
# update it to use your guest pool
/ip dhcp-server set 0 address-pool=guest_pool lease-time=12hCode language: PHP (php)
Setup the DNS server to the router itself for now:
/ip dhcp-server network
set [find address=10.10.0.0/24] dns-server=10.10.0.1
add address=10.20.0.0/24 gateway=10.20.0.1 dns-server=10.10.0.1
add address=10.30.0.0/24 gateway=10.30.0.1 dns-server=10.10.0.1
add address=10.40.0.0/24 gateway=10.40.0.1 dns-server=10.10.0.1Code language: JavaScript (javascript)
ether2 as core
As a failsafe for accessing the administration, anything that is physically connected to the ethernet2 port will be in the core group. To achieve this, we will add another DHCP server especially for the ether2 port.
The LAN layout is the following:
- ether2 core
- ether3 all
- ether4 all
- ether5 all
- wifi Parallax
# 1. Create the new bridge with dedicated admin settings
/interface bridge
add name=bridge-core comment="Core Management Bridge" protocol-mode=none pvid=1 vlan-filtering=no
# 2. Reassign ether2
# We must first REMOVE it from any existing bridge before adding it to the new one
/interface bridge port
remove [find interface=ether2]
add bridge=bridge-core interface=ether2 comment="Physical Admin Access"
# 3. Assign the Management IP
/ip address
add address=10.10.0.1/24 interface=bridge-core comment="Core Management Gateway"
# 4. Networking Infrastructure (Pool & DHCP)
/ip pool
add name=core_pool ranges=10.10.0.100-10.10.0.254
/ip dhcp-server
add address-pool=core_pool interface=bridge-core lease-time=12h name=dhcp-core disabled=no
/ip dhcp-server network
add address=10.10.0.0/24 dns-server=10.10.0.1 gateway=10.10.0.1
# 5. Define the "BASE" Management List
# Using a dedicated list is safer than the generic 'LAN' list
/interface list
add name=BASE comment="Trusted Admin Interfaces"
/interface list member
add interface=bridge-core list=BASE
# 6. THE MISSING STEP: Explicit Firewall Authorization
# This ensures that even if 'Drop All' is active, bridge-core can reach the router
/ip firewall filter
add action=accept chain=input comment="CRITICAL: Allow Admin Access from bridge-core" in-interface-list=BASE place-before=0
# 7. Secure Management Services
# Restrict WinBox and Discovery to ONLY the BASE list
/ip neighbor discovery-settings
set discover-interface-list=BASE
/tool mac-server
set allowed-interface-list=BASE
/tool mac-server mac-winbox
set allowed-interface-list=BASE
/ip service
set winbox address=10.10.0.0/24 disabled=no
Please note that this part of the setup might need some tweaks.
Static IPs
We can assign manual IPs to our devices, by using the MAC address of each device. First we list the devices:
/ip dhcp-server lease printCode language: PHP (php)
Then, for each of the devices we want to make static:
# convert to static (where 0 is the position of the device)
/ip dhcp-server lease make-static 0
# change to the desired ip of the group
/ip dhcp-server lease set 0 address=10.10.0.50 comment="Macbook Air"Code language: PHP (php)
You can also do this via the web interface:
- Go to
IP > DHCP Server > Leases; - Find your device and click on it;
- Press "Make static"
- Change the address to
10.10.0.50and add the comment.
Firewall
One of the most important things to keep in mind is not to lock yourself out of the admin area. In case that happens, you need to reset your router's configuration and start from scratch.
Define the address lists
/ip firewall address-list
add list=core address=10.10.0.0/24
add list=all address=10.20.0.0/24
add list=virtual address=10.30.0.0/24
add list=guest address=10.40.0.0/24
add list=lan_subnets address=10.10.0.0/24
add list=lan_subnets address=10.20.0.0/24
add list=lan_subnets address=10.30.0.0/24
add list=lan_subnets address=10.40.0.0/24Code language: PHP (php)
Protect the router
/ip firewall filter
# 1. Accept established and related connections to the router
add action=accept chain=input connection-state=established,related,untracked comment="Accept established/related to router"
# 2. Drop invalid packets
add action=drop chain=input connection-state=invalid comment="Drop invalid packets"
# 3. Allow ICMP (Ping) for troubleshooting
add action=accept chain=input protocol=icmp comment="Allow ping to router"
# 4. Allow DNS queries from all local subnets
add action=accept chain=input dst-port=53 protocol=udp src-address-list=lan_subnets comment="Allow DNS (UDP)"
add action=accept chain=input dst-port=53 protocol=tcp src-address-list=lan_subnets comment="Allow DNS (TCP)"
# 5. Allow core to access Router Admin (WinBox, Web, SSH, etc.)
add action=accept chain=input src-address-list=core comment="Allow core group full router access"
# 6. Drop everything else (Default Deny)
add action=drop chain=input comment="Drop all other input"Code language: PHP (php)
Enforce the matrix:
/ip firewall filter
# 1. FastTrack (Optional but recommended for speed, bypasses rules for established connections)
add action=fasttrack-connection chain=forward connection-state=established,related hw-offload=yes comment="FastTrack"
# 2. Accept established/related/untracked
add action=accept chain=forward connection-state=established,related,untracked comment="Accept established/related"
# 3. Drop invalid traffic
add action=drop chain=forward connection-state=invalid comment="Drop invalid"
# 4. Allow all subnets to access the Internet
# Note: Ensure your PPPoE/WAN interface is in the "WAN" interface list.
add action=accept chain=forward in-interface-list=!WAN out-interface-list=WAN src-address-list=lan_subnets comment="Allow LAN to Internet"
# 5. Enforce core Access (core can access everything)
add action=accept chain=forward src-address-list=core dst-address-list=lan_subnets comment="core to everywhere"
# 6. Enforce 'all' Group Access (all to core, all to virtual)
add action=accept chain=forward src-address-list=all dst-address-list=core comment="all to core"
add action=accept chain=forward src-address-list=all dst-address-list=virtual comment="all to virtual"
# 7. Explicit Zero Trust Default Deny (Blocks guest to all/core/virtual, virtual to all/core, etc.)
add action=drop chain=forward src-address-list=lan_subnets dst-address-list=lan_subnets comment="Drop unauthorized East-West traffic"
Reset
In case anything goes wrong, you can reset your rules with:
/ip firewall filter remove [find]
/ip firewall filter
add chain=input action=accept connection-state=established,related,untracked comment="defconf: accept established,related,untracked"
add chain=input action=drop connection-state=invalid comment="defconf: drop invalid"
add chain=input action=accept protocol=icmp comment="defconf: accept ICMP"
add chain=input action=accept dst-address=127.0.0.1 comment="defconf: accept to local loopback"
add chain=input action=drop in-interface-list=!LAN comment="defconf: drop all not coming from LAN"
add chain=forward action=accept ipsec-policy=in,ipsec comment="defconf: accept in ipsec policy"
add chain=forward action=accept ipsec-policy=out,ipsec comment="defconf: accept out ipsec policy"
add chain=forward action=fasttrack-connection connection-state=established,related hw-offload=yes comment="defconf: fasttrack"
add chain=forward action=accept connection-state=established,related,untracked comment="defconf: accept established,related,untracked"
add chain=forward action=drop connection-state=invalid comment="defconf: drop invalid"
add chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface-list=WAN comment="defconf: drop all from WAN not DSTNATed"Code language: JavaScript (javascript) 
