$ cd ../
$ cat /backups/brain/
0041
LAN on restricted VLAN networks (Linux masquerading)

You have a network with one single ethernet plug with strict VLAN and packet MAC inspection against switches? Well, configure your PC as a router!

Get two ethernets in your PC:

  • To the internet (VLAN). Your gateway.
  • To a switch (or directly to another device like P2P). Your LAN

You will end up with two interfaces:

  • enp62s0u1u4 (Internet)
  • enp62s0u1u3u3c2 (LAN, switch or P2P)

If you don’t do a full LAN and just P2P with a different device, probably there’s a better way with SNAT (?).

Now the magic.

First, for a certified DNS setup I would recommend following https://ecomaikgolf.com/notes/0042-hide-dns-traffic/ first and then continuing with this guide.

Enable ip forwarding:

1
sudo sysctl net.ipv4.ip_forward

Bound two interfaces to the same firewall zone and add masquerading:

1
2
3
sudo firewall-cmd --permanent --zone=internal --add-interface=enp62s0u1u3u3c2 # LAN
sudo firewall-cmd --permanent --zone=internal --add-interface=enp62s0u1u4     # OUT (internet)
sudo firewall-cmd --permanent --zone=internal --add-masquerade

Define the routes and addresses for the internal LAN:

1
2
sudo ip addr add 192.168.2.1 dev enp62s0u1u3u3c2 # LAN router (you)
sudo ip route add 192.168.2.0/24 dev enp62s0u1u3u3c2 # LAN range

Now configure DHCP or add manually routes in your LAN hosts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ sudo cat /etc/dhcp/dhcpd.conf

ddns-update-style none;
ignore client-updates;
default-lease-time 172800;
max-lease-time 604800;

authoritative;

subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.10 192.168.2.100;
  option routers 192.168.2.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 192.168.2.255;
  option domain-name-servers 192.168.2.1;
}

Important, see that domain-name-servers comes from the DNS guide: https://ecomaikgolf.com/notes/0042-hide-dns-traffic/ . Change it if your system is not a DNS server. Keep in mind that the networking can block 8.8.8.8 and any other non-internal DNS, that’s why we like DNS over HTTPS.

and start the service:

1
sudo systemctl start dhcpd

now your hosts should have received addresses:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ cat /var/lib/dhcpd/dhcpd.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.4.3-P1

# authoring-byte-order entry is generated, DO NOT DELETE
authoring-byte-order little-endian;

lease 192.168.2.11 {
  starts 0 2025/05/11 01:44:14;
  ends 2 2025/05/13 01:44:14;
  tstp 2 2025/05/13 01:44:14;
  cltt 0 2025/05/11 01:44:14;
  binding state active;
  next binding state free;
  rewind binding state free;
  hardware ethernet [...];
}

Now some iptables magic:

1
2
sudo iptables --append FORWARD --in-interface enp62s0u1u3u3c2 -j ACCEPT # LAN interface
sudo iptables --table nat --append POSTROUTING --out-interface enp62s0u1u4 -j MASQUERADE # OUT (internet)

And now your LAN hosts should have internet, masqueraded as (through) your PC.

But, if you also configured DNS over HTTPS with your PC (router) as DNS server for DoH, you also need to edit /etc/systemd/resolved.conf and set the systemd-resolved to listen on the local address:

1
2
[Resolve]
DNSStubListenerExtra=192.168.2.1

finally, allow DNS traffic in the firewalld zone:

1
sudo firewall-cmd --zone=internal --add-service=dns

finally, you will see in the LAN devices that 192.168.2.1 is the DNS:

1
2
3
Global:
Link 2 (eno2): 192.168.2.1
...

and that querying works via that:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
; <<>> DiG ... <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42357
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;google.com.			IN	A

;; ANSWER SECTION:
google.com.		141	IN	A	142.251.208.110

;; Query time: 9 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Mon May 12 15:20:13 CEST 2025
;; MSG SIZE  rcvd: 55

Keep in mind this is doing:

1
(LAN) 127.0.0.1:53 -> (PC) 192.168.2.1:53 -> (PC) 127.0.0.1:5553 -> (INT) https://cloudflare-dns.com/dns-query

NOTE: I might have missed some steps. Will work on a proper blog post.

NOTE2: I’m no networking expert so this might be the worst thing you’ve ever seen. And I would agree.

$ cd ../