Last weekend I went to Shenzhen to play and happened to see my friend’s router; he told me it’s a soft router. Domestic websites can go through domestic lines, foreign websites through foreign lines. At home this weekend I happened to have time to research router functions. I know what readers want to hear, but I don’t plan to cover it. You can use my approach to build a simulated router with virtualbox for simulation and debugging.
This blog mainly wants to introduce implementing router functions in a virtual machine, plus a scheme for home-router ad filtering.
Using the OpenWRT system would make things much easier, and the whole process would be idiot-simple, because everyone has prepared the solutions for you. So the virtual machine used here is Ubuntu server; once you’re used to Linux, any system works. Tinkering with routers was a high-school dream of mine — I find it fairly interesting, though it’s nothing new.
Network Structure
The network structure is as follows:

Creating the Virtual Machines
We need to create two virtual machines: one as the router, the other as an ordinary computer. They can be created cleverly.
First you need at least one Ubuntu machine; then right-click to clone it, immediately adding a new virtual machine. You can also try the snapshot feature.

NIC Configuration
The router needs two NICs
The first for accessing the external network:

The second provides the routing function:
![][4]
For the ordinary computer
Only one NIC is needed:
![][5]
Note this NIC needs dhcp disabled; the concrete configuration is: Management => Host Network Manager => uncheck the dhcp feature
![][6]
Implementing Router Functions
When we normally use a router to access the internet, the router itself generally has IP 192.168.1.1, then assigns us IP 192.168.1.xxx via the dhcp protocol.
So in the router we need: 1. fix the NIC’s IP address, 2. establish a dhcp service.
Fixing the NIC IP Address
Newer Ubuntu versions use the netplan tool; the config file is:
1 | root@UbuntuRoute:/home/corvo# cat /etc/netplan/00-installer-config.yaml |
Here enp0s3 is the NIC the router uses to access external websites; enp0s8 is the NIC connected to the subnet.
Establishing the dhcp Server
In Ubuntu, you can install the isc-dhcp-server server tool and modify the following configuration, indicating the dhcp server works for the enp0s8 NIC.
1 | root@UbuntuRoute:/home/corvo# tail -2 /etc/default/isc-dhcp-server |
Then you need to specify the network segment dhcp can allocate:
1 | root@UbuntuRoute:/home/corvo# tail -8 /etc/dhcp/dhcpd.conf |
Confirming the Ordinary Computer’s Connection
1 | corvo@UbuntuClient:~$ ip addr show |
Adding Packet Forwarding to the Router
Our computer has now obtained an ip address; the next step is internet access, mainly two steps, both performed on the router:
1 | # allow the kernel to forward packets between NICs |
Next you can try browsing the internet on the ordinary computer:
1 | corvo@UbuntuClient:~$ curl ip.sb |
Building an Internal DNS Server and Ad Filtering
My earlier blog already introduced the DNS service: https://corvo.fun/2018/07/30/a-discussion-on-dns-queries/
Establishing the dns Server
In the example above we were lazy with the dns server, using 114.114.114.114; of course you can also build your own dns service — generally using dnsmasq.
1 | # install dnsmasq |
At this point you should be unable to access any website, because the dnsmasq service isn’t configured yet. I added the upstream dns server in the config file, then restarted dnsmasq.
1 | UbuntuRoute# tail -3 /etc/dnsmasq.conf |
Modifying the dns Server Target
Since we used a dhcp server, the part to modify is the dhcp server’s configuration; after modifying, the dhcp service needs restarting:
1 | root@UbuntuRoute:/home/corvo# tail -8 /etc/dhcp/dhcpd.conf |
Wait a few minutes, or restart that user computer, and you’ll find its dns address has changed:
1 | corvo@UbuntuClient:~$ resolvectl status | tail -3 |
One Implementation of Ad Filtering
Some approaches I’ve encountered are implemented via dns hijacking — e.g. this blacklist, recording the domains of advertising and analytics sites; using dnsmasq, their domains are returned as 0.0.0.0:
1 | wget -O /etc/dnsmasq.d/notracking.conf https://raw.githubusercontent.com/notracking/hosts-blocklists/master/dnsmasq/dnsmasq.blacklist.txt |
Then turn on dnsmasq’s include feature, adding conf-dir=/etc/dnsmasq.d/,*.conf.
Afterwards restarting dnsmasq achieves the desired effect, e.g.:
1 | # effect on the router |
The ad filtering function is basically implemented.
Summary
I mainly wanted to introduce the router’s simple implementation principle, and along the way introduce building and using an internal dns server. Knowing only these should be insufficient for your purposes;
I suggest learning more about iptables — you can easily implement all kinds of traffic-splitting effects. Of course, you also need to master dnsmasq.
[4]: https://rawforcorvofeng.cn/Snipaste_2020-12-06_22-04-33.png [5]: https://rawforcorvofeng.cn/Snipaste_2020-12-06_22-05-57.png [6]: https://rawforcorvofeng.cn/Snipaste_2020-12-06_22-07-45.png