VLAN for 2 separate networks sharing internet

I want to create 2 separate networks accessing the same Internet connection. The devices on each network should not be able to access devices on the other network, but should be able to talk with other devices on the same network.

I think I understand VLANs are the solution, but I am unsure how to properly set it up.

My hardware looks like this:

modem <--> OpenWrt (NanoPi R2S) <--> unmanaged switch <--> 2x wifi AP (EAP245)

Devices on 1 network will be exclusively wireless, the other one might see an occasional wired device for network management.

EAP245 seem to support assigning a VLAN ID based on SSID.

Is it possible to simply create 2 SSIDs and assign a VLAN ID to each on the AP? Do I need a managed switch between the APs and the router? How do I then configure OpenWrt?

I you are using an unmanaged switch all VLAN's are visible on any port of the switch.
This means that anyone, who has physical acces to the LAN cable on any AP is able to access all VLAN's.
If you are running OpenWrt on the APs too, you will be able to restrict Wifi and/or the secound LAN port of the AP to only one VLAN.
Other firmware may vary.

So in most cases its required to use a small managed switch. Of course this could be a another router with at least 3 LAN/WAN ports running OpenWrt.
I use some GS108TV3 and Archer C7V5 in a similar scenario with 5 VLAN's.

In my case it is acceptable to have every VLANs on every port of the switch, as the second network is only accessible via wireless with it's own SSID. It's basically about sharing an internet connection with a neighbour, and allowing them to have communication between their devices. They don't have access to any hardware.

Bear in mind I am not very familiar with VLANs and how packets are tagged and handled. How do you configure it in OpenWrt? Which VLAN ID should be used on the EAP245?

As long as your unmanaged switch passes tagged frames intact, that should work fine. Pretty sure everything made in the gigabit era does.

In Network -> Interfaces, Devices tab, select the "Add Device Configuration" button at the bottom. In the dialogue that comes up, Choose device type "VLAN (802.1q)", the base device is the NanoPI's LAN interface, and any number between 2 and 4096 as the VLAN ID. Accept the default interface name it offers you, save and apply. The result acts like just another interface, use it any way you like. Then tell one of your APs to use that VLAN ID. [not familiar with the stock firmware, hopefully it's obvious]. Everything to do with the other AP can just stay default.

This created a device. I have added a MAC address and the default MTU of 1500. I then created a static address interface with this device, with different IP range (192.168.1.1 vs 192.168.2.1) For the firewall rules, I have copied the default lan ==> wan rule. Internet access is still missing.

Post your complete configs:

Please copy the output of the following commands and post it here using the "Preformatted text </> " button:
grafik
Remember to redact passwords, MAC addresses and any public IP addresses you may have:

cat /etc/config/network
cat /etc/config/wireless
cat /etc/config/dhcp
cat /etc/config/firewall

Also, with unmanaged switches, some will not work properly when presented with tagged frames. They are not designed for use with VLANs and should be avoided in most cases since the behavior is undefined. Some unmanaged switches will pass those tags properly, but there are some that can cause major issues. So keep that in mind if things seem to be problematic.

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd35:f317:bd02::/48'
        option packet_steering '1'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth1'

config device
        option name 'eth1'
        option macaddr 'redacted'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config device
        option name 'eth0'
        option macaddr 'redacted'

config interface 'wan'
        option device 'eth0'
        option proto 'dhcp'

config interface 'wan6'
        option device 'eth0'
        option proto 'dhcpv6'

config device
        option type '8021q'
        option ifname 'eth1'
        option vid '20'
        option name 'eth1.20'
        option mtu '1500'
        option macaddr 'redacted'

config interface 'VLAN_FRIENDS'
        option proto 'static'
        option device 'eth1.20'
        option ipaddr '192.168.2.1'
        option netmask '255.255.255.0'
config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option filteraaaa '1'
        option ednspacket_max '1232'
        option noresolv '0'
        option cachesize '1000'
        option rebind_protection '0'
        option port '54'
        list server '192.168.1.1'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        option ra_slaac '1'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        list dhcp_option '6,192.168.1.1'
        list dhcp_option '3,192.168.1.1'
        list dns 'redacted'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'
config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option flow_offloading '1'
        option fullcone '1'
        option synflood_protect '1'

config zone
        option name 'lan'
        list network 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'

config zone
        option name 'wan'
        list network 'wan'
        list network 'wan6'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option src_ip 'fc00::/6'
        option dest_ip 'fc00::/6'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config rule
        option name 'Support-UDP-Traceroute'
        option src 'wan'
        option dest_port '33434:33689'
        option proto 'udp'
        option family 'ipv4'
        option target 'REJECT'
        option enabled 'false'

config include
        option path '/etc/firewall.user'

config include 'zerotier'
        option type 'script'
        option path '/etc/zerotier.start'
        option reload '1'

config include 'miniupnpd'
        option type 'script'
        option path '/usr/share/miniupnpd/firewall.include'
        option family 'any'
        option reload '1'

config include 'adbyby'
        option type 'script'
        option path '/var/etc/adbyby.include'
        option reload '1'

config rule 'adblock'
        option name 'adblock'
        option target 'DROP'
        option src 'wan'
        option proto 'tcp'
        option dest_port '8118'

config include 'shadowsocksr'
        option type 'script'
        option path '/var/etc/shadowsocksr.include'
        option reload '1'

config zone
        option name 'FRIENDS'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'VLAN_FRIENDS'

config forwarding
        option src 'FRIENDS'
        option dest 'wan'

The AP is configured with VLAN ID 20 for a specific SSID:

What version of OpenWrt are you using? It looks like it may be something different than the official version.

Meanwhile, you do not have a dhcp server setup for your friends network. Is that intentional?

I am using quintus-lab (quintus-lab). I was looking for a build with built-in overclocking.

I have tried adding a DHCP server configured as the lan one, but with the options modified:

        list dhcp_option '6,192.168.2.1'
        list dhcp_option '3,192.168.2.1'

Connection to the FRIENDS network seem quicker and I don't get the "missing internet connection" message, but I still can't access the web.

You do not need to specify those options - by default, they will reference the router, so that shouldn’t be changing anything. What do the hosts on that network get via dhcp (ip address, router, subnet mask, dns)?

What happens if you run the following ping tests from a host on the friends network:

I think those options were added to the lan DHCP server by the AdGuard installation script here. Is it possible those modifications are the problem?

ip: 192.168.2.226
router: 192.168.2.1
subnet: 255.255.255.0
it would seem there is no DNS server. is that possible?

PING 192.168.2.1 (192.168.2.1): 56 data bytes
64 bytes from 192.168.2.1: icmp_seq=0 ttl=64 time=3.526 ms
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=3.252 ms
64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=2.724 ms
64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=1.421 ms
PING 8.8.8.8 (8.8.8.8): 56 data bytes
ping: sendto: No route to host
ping: sendto: No route to host
Request timeout for icmp_seq 0
ping: sendto: No route to host
Request timeout for icmp_seq 1
ping: sendto: No route to host
Request timeout for icmp_seq 2
ping: cannot resolve google.com: Unknown host

I don’t see anything wrong with your config, unless I’m missing something silly.

I would recommend either trying official openwrt (and not bothering with overclocking), or ask your question with the maintainers of the build you are using - it is very likely that the problem is related to a difference between pure openwrt and this customized version.

Even the official 21.02 build would not work with the previous config. I managed to get it to work with the following modification:

        list dhcp_option '6,192.168.2.1'
        list dhcp_option '3,192.168.2.1'

must be added to the VLAN DHCP options.

also, adguardhome.yaml must be modified to add 192.168.2.1 to the DNS address as follows:

dns:
  bind_hosts:
  - 192.168.1.1
  - 192.168.2.1

Now internet access works from every device. However, devices within the FRIENDS zone cannot reach each other. here is the latest config, on vanilla OpenWrt with AdGuard.

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fdc4:8e18:9740::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth1'

config device
        option name 'eth1'
        option macaddr 'redacted'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config device
        option name 'eth0'
        option macaddr 'redacted'

config interface 'wan'
        option device 'eth0'
        option proto 'dhcp'

config interface 'wan6'
        option device 'eth0'
        option proto 'dhcpv6'

config device
        option type '8021q'
        option ifname 'eth1'
        option vid '2'
        option name 'eth1.2'
        option macaddr 'redacted'

config interface 'FRIENDS'
        option proto 'static'
        option device 'eth1.2'
        option ipaddr '192.168.2.1'
        option netmask '255.255.255.0'
config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option ednspacket_max '1232'
        option noresolv '0'
        option cachesize '1000'
        option rebind_protection '0'
        option port '54'
        list server '192.168.1.1'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        option ra_slaac '1'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        list dhcp_option '6,192.168.1.1'
        list dhcp_option '3,192.168.1.1'
        list dns 'fdc4:8e18:9740::1'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

config dhcp 'FRIENDS'
        option interface 'FRIENDS'
        option start '100'
        option limit '150'
        option leasetime '12h'
        list dhcp_option '6,192.168.2.1'
        list dhcp_option '3,192.168.2.1'
        list ra_flags 'none'
config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'
        option flow_offloading '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'FRIENDS_FW'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'FRIENDS'
        option input 'REJECT'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'
        list network 'wan6'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option src_ip 'fc00::/6'
        option dest_ip 'fc00::/6'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config rule
        option name 'Support-UDP-Traceroute'
        option src 'wan'
        option dest_port '33434:33689'
        option proto 'udp'
        option family 'ipv4'
        option target 'REJECT'
        option enabled '0'

config include
        option path '/etc/firewall.user'

config forwarding
        option src 'FRIENDS_FW'
        option dest 'wan'

config rule
        option name 'FRIENDS_DHCP and DNS'
        option src 'FRIENDS_FW'
        option dest_port '53 67 68'
        option target 'ACCEPT'

Any ideas why clients can't reach each other from within their own VLAN?

How are these hosts connected? Ethernet? WiFi?
What are the ip addresses and subnet masks for two such hosts that cannot reach each other?

If adguard is operating on “192.168.1.1”
(see your dnsmasq config):
list server '192.168.1.1'
you will have to use:
list dhcp_option '6,192.168.1.1'

on your VLAN DHCP
and not:

        list dhcp_option '6,192.168.2.1'
        list dhcp_option '3,192.168.2.1'

option 3 is not needed von your Vlan DHCP

WiFi. It goes: AP --> VLAN tag based on SSID --> unmanaged switch --> router.

Internet access has been flawless.

client 1(windows):

IP: 192.168.2.224
subnet: 255.255.255.0
Default Gateway: 192.168.2.1
DHCP server: 192.168.2.1
DNS Server: 192.168.1.1

client 2 (iphone):

IP: 192.168.2.234
subnet: 255.255.255.0
router: 162.168.2.1
DNS Server: 192.168.1.1

I have changed it, and behaviour seems identical (without extensive tests). Internet access works, hosts can't reach each other.

Unmanaged switches should not be used with tagged networks because the behavior of VLANs through an unmanaged switch is undefined. Some work fine, others don't work at all, and some sort of work. Hard to say if this is impacting your setup.

Both devices are on wifi -- are they connected to the same AP (if you have multiple APs, this could be relevant).

do you have isolation enabled on your wifi configuration? post your /etc/config/wireless config file

/etc/config/wireless does not exist:

cat: can't open '/etc/config/wireless': No such file or directory

There are 2 APs configured identically. During my tests, all relevant hosts were connected on the same AP. IP addresses of the APs are 192.168.1.2 and 192.168.1.3, netmask 255.255.255.0. While writing this, I'm wondering if this might be the problem. VLAN FRIENDS is assigning IPs in the 192.168.2.xx range. Does that mean that traffic from one host can't go to the router and back to another host through the AP? Would I need to change the net mask on some devices, or firewall rules?