Linux Router
Table of Contents
To goal of this is to configure our Linux server as a router, LAN1 acting as a WAN and other interface like LAN2 to assign IP or WLAN as a hotspot.
DNS Server
Pi-hole
There are many option to run DNS server, but with my broke setup we’ll configure Pi-hole. I recommend Bind9 for advance functionality. Head over to their website for elaborate documentation.
1services:
2 pihole:
3 container_name: pihole
4 image: pihole/pihole:latest
5 ports:
6 # DNS Ports
7 - "53:53/tcp"
8 - "53:53/udp"
9 # Default HTTP Port
10 - "80:80/tcp"
11 # Default HTTPs Port. FTL will generate a self-signed certificate
12 - "443:443/tcp"
13 # Uncomment the below if using Pi-hole as your DHCP Server
14 #- "67:67/udp"
15 # Uncomment the line below if you are using Pi-hole as your NTP server
16 #- "123:123/udp"
17 environment:
18 # Set the appropriate timezone for your location from
19 # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones, e.g:
20 TZ: 'Europe/London'
21 # Set a password to access the web interface. Not setting one will result in a random password being assigned
22 FTLCONF_webserver_api_password: 'correct horse battery staple'
23 # If using Docker's default `bridge` network setting the dns listening mode should be set to 'ALL'
24 FTLCONF_dns_listeningMode: 'ALL'
25 # Volumes store your data between container upgrades
26 volumes:
27 # For persisting Pi-hole's databases and common configuration file
28 - './etc-pihole:/etc/pihole'
29 # Uncomment the below if you have custom dnsmasq config files that you want to persist. Not needed for most starting fresh with Pi-hole v6. If you're upgrading from v5 you and have used this directory before, you should keep it enabled for the first v6 container start to allow for a complete migration. It can be removed afterwards. Needs environment variable FTLCONF_misc_etc_dnsmasq_d: 'true'
30 #- './etc-dnsmasq.d:/etc/dnsmasq.d'
31 cap_add:
32 # See https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
33 # Required if you are using Pi-hole as your DHCP server, else not needed
34 - NET_ADMIN
35 # Required if you are using Pi-hole as your NTP client to be able to set the host's system time
36 - SYS_TIME
37 # Optional, if Pi-hole should get some more processing time
38 - SYS_NICE
39 restart: unless-stopped
Run the container.
1docker compose up -d
Let assume your IP is 192.168.254.15. To check if the DNS server is running you can run this command.
Check from the server if port 53 is active
1$ netstat -tulp
2netstat -tulpn | grep 53
3(Not all processes could be identified, non-owned process info
4 will not be shown, you would have to be root to see it all.)
5tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN -
6tcp 0 0 192.168.254.15:53 0.0.0.0:* LISTEN -
Using dig or nslookup.
1$ dig @192.168.254.15 -p 53 google.com
2
3; <<>> DiG 9.20.15-1~deb13u1-Debian <<>> @192.168.254.15 -p 53 google.com
4; (1 server found)
5;; global options: +cmd
6;; Got answer:
7;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15974
8;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
9
10;; OPT PSEUDOSECTION:
11; EDNS: version: 0, flags:; udp: 1232
12;; QUESTION SECTION:
13;google.com. IN A
14
15;; ANSWER SECTION:
16google.com. 149 IN A 142.251.221.14
17
18;; Query time: 18 msec
19;; SERVER: 192.168.254.15#53(192.168.254.15) (UDP)
20;; WHEN: Mon Jan 26 15:27:39 PST 2026
21;; MSG SIZE rcvd: 55
22
23
24$ nslookup google.com 192.168.254.15
25Server: 192.168.254.15
26Address: 192.168.254.15#53
27
28Non-authoritative answer:
29Name: google.com
30Address: 142.251.221.46
31Name: google.com
32Address: 2404:6800:4017:805::200e
dnsmasq as DNS Forwarder
With dnsmasq configured as a forwarder DNS can be resolved to your local IP (let the IP set to 192.168.254.15), as a example let our upstream DNS server to be 8.8.8.8.
First we need to install dnsmasq and start service.
1apt install dnsmasq
2systemctl enable --now dnsmasq
You will get error when you start the service, depending what network service you are using configure it to use dnsmasq.
networkd
1# /etc/systemd/network/10-eth0.network
2Name=eth0
3
4[Network]
5Address=192.168.1.1/24
6DNS=192.168.254.15
7Domains=~.
8IPForward=yes
Network Manager
1# /etc/NetworkManager/NetworkManager.conf
2[main]
3dns=dnsmasq
Also edit your config to point it to your local IP.
Now let as configure dnsmasq.
1# /etc/dnsmasq.conf
2listen-address=127.0.0.1,192.168.254.15
3bind-interfaces
4
5interface=eth0
6dhcp-range=192.168.1.100,192.168.1.200,12h
Look at the next section as dnsmasq can also be configured as DHCP Server.
DHCP Server
WAN and LAN
Now let’s assume we have two ethernet and we want our Linux server behave like a gateway, eth0 as WAN and eth1 as LAN. First make sure IP forwarding is enabled, most probably enabled if you are using docker.
1echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-router.conf
2sudo sysctl --system
Set IP for ethernets using netplan, you can use other method. In here we let the server get WAN IP from the ISP, it can also be set to static. And the IP subnet propagated to the other ethernet is 192.168.10.0/24 as seen in the later section (IP range from 192.168.10.100 to .200).
/etc/netplan/01-router.yaml
1network:
2 version: 2
3 renderer: networkd
4
5 ethernets:
6 eth0:
7 dhcp4: true
8
9 eth1:
10 dhcp4: no
11 addresses:
12 - 192.168.10.101/24
Apply configuration.
1netplan apply
Now we configure dnsmasq.
/etc/dnsmasq.conf
1# Serve ONLY the LAN
2interface=eth1
3bind-interfaces
4
5# DHCP range
6dhcp-range=192.168.10.100,192.168.10.200,12h
7
8# DHCP options
9dhcp-option=option:router,192.168.10.1
10dhcp-option=option:dns-server,192.168.10.1
11
12# DNS forwarding
13no-resolv
14server=192.168.254.15
15server=8.8.8.8
16
17# Hygiene
18domain-needed
19bogus-priv
Start dnsmasq service
1systemctl enable --now dnsmasq
WAN/LAN and Hotspot
Unlike the previous example that has two ethernets, in here we assume we have one ethernet (eth0) acting as WAN/LAN and wireless nic (wlan0) as hotspot.
Like the previous config, we just change the interface to wlan0.
/etc/dnsmasq.conf
1# Serve ONLY the LAN
2interface=wlan0
3bind-interfaces
4
5# DHCP range
6dhcp-range=192.168.10.100,192.168.10.200,12h
7
8# DHCP options
9dhcp-option=option:router,192.168.10.1
10dhcp-option=option:dns-server,192.168.10.1
11
12# DNS forwarding
13no-resolv
14server=192.168.254.15
15server=8.8.8.8
16
17# Hygiene
18domain-needed
19bogus-priv
Start dnsmasq.
1systemctl enable --now dnsmasq
Install hotspod.
1apt install hotspot
Edit hotspotd configuration.
/etc/hotspotd/hotspotd.conf
1# Interface used for the hotspot
2interface=wlan0
3
4# Hotspot IP configuration
5address=192.168.10.1
6netmask=255.255.255.0
7
8# Bridge (optional – only if you really use one)
9# Comment this out if not bridging
10# bridge=br0
11
12# Wireless settings
13ssid=yourSSID
14country_code=PH
15driver=nl80211
16
17hw_mode=g
18channel=7
19ieee80211n=1
20wmm_enabled=1
21
22# Security: WPA2-PSK ONLY
23wpa=2
24wpa_key_mgmt=WPA-PSK
25rsn_pairwise=CCMP
26wpa_pairwise=CCMP
27wpa_passphrase=averysecurepassword
Start hotspotd service.
1systemctl enable --now hotspotd