How to set up wired client with presence on multiple VLANs

I've got one router which is currently set up such that all the wired clients are on the default VLAN, and the wifi AP exposes two SSIDs. Connect to one SSID, you're on the default VLAN; connect to the other SSID, you're on a secondary VLAN. Each VLAN is configured to be able to communicate with the public Internet but not with the other VLAN.

Now I want to designate one wired client as specially able to talk to both VLANs, but, crucially, it should have a different IP address on each VLAN and some of the services it offers will only be visible on one or the other. But all this should go over a single physical network cable.

What do I need to do to set this up, on both the router and the designated client? The client runs Linux and it's fine if it has to have statically assigned IP addresses on either or both VLANs.

Not sure what you're wanting to do is possible without another interface. Why do you need a different IP address? If your primary VLAN is your safe one, the easiest thing to do would be to create a traffic rule for the specific client to traverse the VLAN. Here's an example I have which allows any client on my wg0 interface to connect to my LXC interface to a specific client on a specific port.

config rule
  option src 'wg0'
  option dest 'lxc'
  option name 'ag.home from wg0'
  list dest_ip '10.0.4.250'
  option target 'ACCEPT'
  list proto 'tcp'
  list proto 'udp'
  option dest_port '80'

A related question is I assume you've got a trunk line connecting your router firewall to your access point. Is that right?

The box that should have a presence on both VLANs runs several different services. If I can give it a separate IP address on each VLAN, then I can set it up so that only the specific services that are needed by the untrusted devices on the secondary VLAN are accessible to those devices. (Concretely, the secondary VLAN is for a bunch of IoT widgets that need to be able to talk to Home Assistant over unsecured HTTP; I want to set it up such that the Home Assistant reporting and control endpoints are the only things they can see.)

The AP and the router are the same device. Here's the full current configuration:

/etc/config/firewall (all the config rule stanzas are OpenWRT's defaults)
config defaults
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	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 'laniot'
	list network 'laniot'
	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 forwarding
	option src 'laniot'
	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 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'
/etc/config/network
config globals 'globals'
	option dhcp_default_duid '[redacted]'
	option ula_prefix '[redacted]'
	option packet_steering '1'

config device
	option name 'lan1'
	option macaddr '[redacted]'

config device
	option name 'lan2'
	option macaddr '[redacted]'

config device
	option name 'lan3'
	option macaddr '[redacted]'

config device
	option name 'lan4'
	option macaddr '[redacted]'

config device
	option name 'wan'
	option macaddr '[redacted]'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'

config bridge-vlan
	option device 'br-lan'
	option vlan '1'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'

config bridge-vlan
	option device 'br-lan'
	option vlan '47'

config interface 'loopback'
	option device 'lo'
	option proto 'static'
	list ipaddr '127.0.0.1/8'

config interface 'lan'
	option device 'br-lan.1'
	option proto 'static'
	list ipaddr '10.0.0.1/24'
	option ip6assign '64'
	option multipath 'off'

config interface 'laniot'
	option proto 'static'
	option device 'br-lan.47'
	list ipaddr '10.0.47.1/24'
	option ip6assign '64'
	option multipath 'off'

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

config interface 'wan6'
	option device 'wan'
	option proto 'dhcpv6'
/etc/config/wireless
config wifi-device 'radio0'
        option type 'mac80211'
        option path 'soc/soc:pcie@82000000/pci0000:00/0000:00:02.0/0000:02:00.0'
        option band '2g'
        option channel 'auto'
        option country 'US'
        option cell_density '1'
        option htmode 'HT20'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'lan'
        option mode 'ap'
        option ssid '[redacted]'
        option encryption 'sae-mixed'
        option disabled '0'
        option macaddr '[redacted]'
        option key '[redacted]'
        option ieee80211w '1'
        option wpa_disable_eapol_key_retries '1'
        option wds '1'
        option ocv '0'

config wifi-iface 'iot_radio0'
        option device 'radio0'
        option network 'laniot'
        option mode 'ap'
        option ssid '[redacted]'
        option encryption 'sae-mixed'
        option disabled '0'
        option key '[redacted]'
        option ieee80211w '1'
        option wpa_disable_eapol_key_retries '1'
        option ocv '0'

config wifi-device 'radio1'
        option type 'mac80211'
        option path 'soc/soc:pcie@82000000/pci0000:00/0000:00:03.0/0000:03:00.0'
        option band '5g'
        option channel 'auto'
        option htmode 'VHT80'
        option country 'US'
        option cell_density '1'

config wifi-iface 'default_radio1'
        option device 'radio1'
        option network 'lan'
        option mode 'ap'
        option ssid '[redacted]'
        option encryption 'sae-mixed'
        option disabled '0'
        option macaddr '[redacted]'
        option key '[redacted]'
        option ieee80211w '1'
        option wpa_disable_eapol_key_retries '1'
        option wds '1'
        option ocv '0'

I don't have any experience with the setup you're describing: two IP addresses on two separate VLANs. I am assuming you have two network interfaces on that device. I can't see how else you would do it. I use a managed switch to take care of wired connection VLAN associations.

Just one physical network interface, but I can stack a virtual interface on top of that, set it to tag packets with the secondary VLAN's ID, and assign it a different IP address and default route. Very much the same idea as how, in the router-side configuration, there are two br-lan devices stacked on the bridge device.

On the router side, the main thing I don't know how to do is tell OpenWRT that a specific port should accept both tagged and untagged packets, then shunt them to the appropriate VLAN.

One VLAN is untagged, all others are tagged.
Or tag all VLAN on that port...

I'm sorry, that doesn't help me any. Yes, that does sound like what I want to achieve. Whadda I gotta put in /etc/config/network to make that happen? Or describe it in terms of LuCI config screens, that'd be fine too.


Lets take lan3 as an example.

vlan 1 and vlan 47 tagged:

config bridge-vlan
	option device 'br-lan'
	option vlan '1'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3:t'
	list ports 'lan4'

config bridge-vlan
	option device 'br-lan'
	option vlan '47'
	list ports 'lan3:t'

vlan 1 untagged, and vlan 47 tagged:

config bridge-vlan
	option device 'br-lan'
	option vlan '1'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'

config bridge-vlan
	option device 'br-lan'
	option vlan '47'
	list ports 'lan3:t'

Not quiet sure, but there should be a port and vlan overview page where you should just select each port on a vlan... I don't use LuCI :person_shrugging:

Aha, this looks promising. I shall experiment with it and report back.

There is such a screen but it's very cryptic and I couldn't find any documentation for it...

Select Untagged + Is Primary VLAN for 'regular'/non-vlan aware devices to connect to a given port. You can have zero or one untagged network on a port.

Select Tagged if you are creating a trunk (carrying multiple networks). These are only useful for VLAN aware devices (such as managed switches and computers that can be configured with tagged networks). You can have zero, one or many tagged networks on a port.

Not Member should be self explanatory.

What's the difference (in behavior) between "Untagged + Is Primary VLAN" and just "Untagged"?

Technically, the PVID (Primary VLAN) specifics the VLAN to which untagged ingress traffic should be assigned, while the egress is controlled by the tagged/untagged status.

In practice, there doesn't seem to be a difference between untagged and untagged + PVID. But I always recommend explicitly specifying untagged + PVID because it guarantees the desired operation.