FW rule to access VLAN not working properly

The following configuration is working well except that 192.168.10.0/24 can not reach a host on 192.168.20.0/24 but the gateway address of the latter can be reached. This behavior can be mitigated by deleting all FW rules so I can be sure that this is the issue. I will paste the config sans the bottom part so maybe someone could have a quick look at it? Thanks in advance.

firewall {
    ipv4 {
        name GUEST-ROUTER {
            default-action "accept"
        }
        name GUEST-WAN {
            default-action "accept"
        }
        name IoT-ROUTER {
            default-action "accept"
        }
        name IoT-WAN {
            default-action "accept"
        }
         
        name LAN-IoT {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow traffic from LAN to IoT"
                destination {
                    address "192.168.20.0/24"
                }
                source {
                    address "192.168.10.0/24"
                }
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name LAN-ROUTER {
            default-action "accept"
        }
        name LAN-WAN {
            default-action "accept"
        }
        name ROUTER-GUEST {
            default-action "accept"
        }
        name ROUTER-IoT {
            default-action "accept"
        }
        name ROUTER-LAN {
            default-action "accept"
        }
        name ROUTER-WAN {
            default-action "accept"
        }
        name ROUTER-WORK {
            default-action "accept"
        }
        name WAN-GUEST {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name WAN-IoT {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name WAN-LAN {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name WAN-ROUTER {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name WAN-WORK {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
        name WORK-ROUTER {
            default-action "accept"
        }
        name WORK-WAN {
            default-action "accept"
        }
    }
    zone GUEST {
        default-action "drop"
        from ROUTER {
            firewall {
                name "ROUTER-GUEST"
            }
        }
        from WAN {
            firewall {
                name "WAN-GUEST"
            }
        }
        interface "eth0.30"
    }
    zone IoT {
        default-action "drop"
        from LAN {
            firewall {
                name "LAN-IoT"
            }
        }
        from ROUTER {
            firewall {
                name "ROUTER-IoT"
            }
        }
        from WAN {
            firewall {
                name "WAN-IoT"
            }
        }
        interface "eth0.20"
    }
    zone LAN {
        default-action "drop"
        from ROUTER {
            firewall {
                name "ROUTER-LAN"
            }
        }
        from WAN {
            firewall {
                name "WAN-LAN"
            }
        }
        interface "eth0"
    }
    zone ROUTER {
        default-action "drop"
        from GUEST {
            firewall {
                name "GUEST-ROUTER"
            }
        }
        from IoT {
            firewall {
                name "IoT-ROUTER"
            }
        }
        from LAN {
            firewall {
                name "LAN-ROUTER"
            }
        }
        from WAN {
            firewall {
                name "WAN-ROUTER"
            }
        }
        from WORK {
            firewall {
                name "WORK-ROUTER"
            }
        }
        local-zone
    }
    zone WAN {
        default-action "drop"
        from GUEST {
            firewall {
                name "GUEST-WAN"
            }
        }
        from IoT {
            firewall {
                name "IoT-WAN"
            }
        }
        from LAN {
            firewall {
                name "LAN-WAN"
            }
        }
        from ROUTER {
            firewall {
                name "ROUTER-WAN"
            }
        }
        from WORK {
            firewall {
                name "WORK-WAN"
            }
        }
        interface "eth0.99"
    }
    zone WORK {
        default-action "drop"
        from ROUTER {
            firewall {
                name "ROUTER-WORK"
            }
        }
        from WAN {
            firewall {
                name "WAN-WORK"
            }
        }
        interface "eth0.40"
    }
}
interfaces {
    ethernet eth0 {
        address "192.168.10.1/24"
        address "192.168.1.110/24"
        description "LAN"
        hw-id "bc:24:11:78:b3:56"
        vif 20 {
            address "192.168.20.1/24"
            description "IoT"
        }
        vif 30 {
            address "192.168.30.1/24"
            description "GUEST"
        }
        vif 40 {
            address "192.168.40.1/29"
            description "WORK"
        }
        vif 99 {
            address "dhcp"
            description "WAN"
        }
    }
    loopback lo {
    }
}
nat {
    source {
        rule 100 {
            outbound-interface {
                name "eth0.99"
            }
            source {
                address "192.168.10.0/24"
            }
            translation {
                address "masquerade"
            }
        }
        rule 200 {
            outbound-interface {
                name "eth0.99"
            }
            source {
                address "192.168.20.0/24"
            }
            translation {
                address "masquerade"
            }
        }
        rule 300 {
            outbound-interface {
                name "eth0.99"
            }
            source {
                address "192.168.30.0/24"
            }
            translation {
                address "masquerade"
            }
        }
        rule 400 {
            outbound-interface {
                name "eth0.99"
            }
            source {
                address "192.168.40.0/29"
            }
            translation {
                address "masquerade"
            }
        }
    }
}
service {
    dhcp-server {
        shared-network-name GUEST {
            subnet 192.168.30.0/24 {
                default-router "192.168.30.1"
                name-server "1.1.1.1"
                range 0 {
                    start "192.168.30.2"
                    stop "192.168.30.99"
                }
            }
        }
        shared-network-name IoT {
            subnet 192.168.20.0/24 {
                default-router "192.168.20.1"
                name-server "1.1.1.1"
                range 0 {
                    start "192.168.20.2"
                    stop "192.168.20.99"
                }
            }
        }
        shared-network-name LAN {
            subnet 192.168.10.0/24 {
                default-router "192.168.10.1"
                name-server "1.1.1.1"
                range 0 {
                    start "192.168.10.2"
                    stop "192.168.10.99"
                }
            }
        }
        shared-network-name WORK {
            subnet 192.168.40.0/29 {
                default-router "192.168.40.1"
                name-server "1.1.1.1"
                range 0 {
                    start "192.168.40.2"
                    stop "192.168.40.6"
                }
            }
        }
    }
    dns {
        forwarding {
            allow-from "192.168.10.0/24"
            allow-from "192.168.20.0/24"
            allow-from "192.168.30.0/24"
            allow-from "192.168.40.0/29"
            cache-size "0"
            listen-address "192.168.10.1"
            listen-address "192.168.20.1"
            listen-address "192.168.30.1"
            listen-address "192.168.40.1"
            name-server 1.1.1.1 {
            }
        }
    }
    ntp {
        allow-client {
            address "127.0.0.0/8"
            address "169.254.0.0/16"
            address "10.0.0.0/8"
            address "172.16.0.0/12"
            address "192.168.0.0/16"
            address "::1/128"
            address "fe80::/10"
            address "fc00::/7"
        }
        server time1.vyos.net {
        }
        server time2.vyos.net {
        }
        server time3.vyos.net {
        }
    }
    ssh
}
system {
    config-management {
        commit-revisions "100"
    }
    conntrack {
        modules {
            ftp
            h323
            nfs
            pptp
            sip
            sqlnet
            tftp
        }
    }
    console {
        device ttyS0 {
            speed "115200"
        }
    }
    host-name "vyos"
    login {
        user vyos {
            authentication {
                encrypted-password "$6$rounds=XXXXXXXXXXXXXXXXXXJEhUFnRK7qyfZ475JkmkXXXXXXXXXXXXXXXXXXXXXXi25h3R.2mdKXK.Gl0"
                plaintext-password ""
            }
        }
    }
    name-server "192.168.10.1"
    syslog {
        global {
            facility all {
                level "info"
            }
            facility local7 {
                level "debug"
            }
        }
    }
}


// Warning: Do not remove the following line.
// vyos-config-version: "bgp@6:broadcast-relay@1:cluster@2:config-management@1:conntrack@5:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@8:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:reverse-proxy@1:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2"
// Release version: 1.4.2

And here is the output from the log:

vyos@vyos# run sh log firewall
Jul 04 12:47:22 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30185 DF PROTO=TCP SPT=56470 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:23 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30186 DF PROTO=TCP SPT=56470 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:25 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30187 DF PROTO=TCP SPT=56470 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:27 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30188 DF PROTO=TCP SPT=56471 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:28 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30189 DF PROTO=TCP SPT=56471 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:30 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30190 DF PROTO=TCP SPT=56471 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:32 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30191 DF PROTO=TCP SPT=56475 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:33 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30192 DF PROTO=TCP SPT=56475 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
Jul 04 12:47:35 kernel: [ipv4-NAM-LAN-IoT-5-A]IN=eth0 OUT=eth0.20 MAC=bc:24:11:78:b3:56:b0:22:7a:6a:66:3f:08:00 SRC=192.168.10.4 DST=192.168.20.3 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=30193 DF PROTO=TCP SPT=56475 DPT=554 WINDOW=64240 RES=0x00 SYN URGP=0
[edit]

Ok, figured it out by myself. I was missing a rule for IoT-LAN so I have added:

zone LAN {
        default-action "drop"
        from ROUTER {
            firewall {
                name "ROUTER-LAN"
            }
        }
        from WAN {
            firewall {
                name "WAN-LAN"
            }
        }
        from IoT {
            firewall {
                name "IoT-LAN"
            }
        }
        interface "eth0"
    }

and

   name IoT-LAN {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }

You can avoid that little “gotcha” in the future by allowing stateful traffic at the global level. This will allow any return traffic provided the original traffic was permitted by your firewall policies. There wouldn’t be a need to allow the stateful return traffic per from/to zone:

set firewall global-options state-policy established action 'accept'
set firewall global-options state-policy related action 'accept'

This is entirely personal preference, but I like to view my named chains as policies rather than an explicit zone mapping. This can save you a lot of redundant config when you have zone pairings that have the same policy. For instance, in your config, all of these:

name GUEST-ROUTER
name GUEST-WAN
name IoT-ROUTER
name IoT-WAN  
name WORK-ROUTER
name WORK-WAN   
name LAN-ROUTER
name LAN-WAN
name ROUTER-GUEST
name ROUTER-IoT
name ROUTER-LAN
name ROUTER-WAN
name ROUTER-WORK   

Could become:

name ACCEPT_ALL

And all of these:

name LAN-IoT
name WAN-GUEST
name WAN-IoT
name WAN-LAN
name WAN-ROUTER
name WAN-WORK

Could become (or just ALLOW_ICMP if allowing state at the global level):

name ACCEPT_ICMP_AND_STATE

And those polices would of course be this:

firewall {
    ipv4 {
        name ACCEPT_ALL {
            default-action "accept"
        }
        name ACCEPT_ICMP_AND_STATE {
            default-action "drop"
            rule 5 {
                action "accept"
                description "Allow EST/Related Traffic"
                state "established"
                state "related"
            }
            rule 20 {
                action "accept"
                protocol "icmp"
                state "new"
            }
        }
2 Likes

@L0crian Thanks for giving me some advice on writing better rules. It makes it much easier to read and understand the workflow. I will try to amend the rules (after deleting the current FW section) and see if it works - well, I guess it will.

##FW Rules

##ACCEPT_ALL
set firewall ipv4 name ACCEPT_ALL default-action accept

##ACCEPT_ICMP_AND_STATE
set firewall ipv4 name ACCEPT_ICMP_AND_STATE default-action drop
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 5 action accept
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 5 state established
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 5 state related
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 5 description "Allow EST/Related Traffic"
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 20 action accept
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 20 description "Allow ICMP"
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 20 protocol icmp
set firewall ipv4 name ACCEPT_ICMP_AND_STATE rule 20 state new


##ACCEPT_TRAFFIC_LAN_IoT
set firewall ipv4 name ACCEPT_TRAFFIC_LAN_IoT default-action drop
set firewall ipv4 name ACCEPT_TRAFFIC_LAN_IoT rule 5 action accept
set firewall ipv4 name ACCEPT_TRAFFIC_LAN_IoT rule 5 description "Allow LAN to IoT"
set firewall ipv4 name ACCEPT_TRAFFIC_LAN_IoT rule 5 destination address 192.168.20.0/24
set firewall ipv4 name ACCEPT_TRAFFIC_LAN_IoT rule 5 source address 192.168.10.0/24


##FW Zones

##GUEST
set firewall zone GUEST default-action drop
set firewall zone GUEST from ROUTER firewall name ACCEPT_ALL
set firewall zone GUEST from WAN firewall name ACCEPT_ICMP_AND_STATE
set firewall zone GUEST interface 'eth0.30'

##IoT
set firewall zone IoT default-action drop
set firewall zone IoT from LAN firewall name ACCEPT_TRAFFIC_LAN_IoT
set firewall zone IoT from ROUTER firewall name ACCEPT_ALL
set firewall zone IoT from WAN firewall name ACCEPT_ICMP_AND_STATE
set firewall zone IoT interface 'eth0.20'

##LAN
set firewall zone LAN default-action drop
set firewall zone LAN from IoT firewall name ACCEPT_ICMP_AND_STATE
set firewall zone LAN from ROUTER firewall name ACCEPT_ALL
set firewall zone LAN from WAN firewall name ACCEPT_ICMP_AND_STATE
set firewall zone LAN interface 'eth0'

##ROUTER
set firewall zone ROUTER default-action drop
set firewall zone ROUTER from GUEST firewall name ACCEPT_ALL
set firewall zone ROUTER from IoT firewall name ACCEPT_ALL
set firewall zone ROUTER from LAN firewall name ACCEPT_ALL
set firewall zone ROUTER from WAN firewall name ACCEPT_ICMP_AND_STATE
set firewall zone ROUTER from WORK firewall name ACCEPT_ALL
set firewall zone ROUTER local-zone

##WAN
set firewall zone WAN default-action drop
set firewall zone WAN from GUEST firewall name ACCEPT_ALL
set firewall zone WAN from IoT firewall name ACCEPT_ALL
set firewall zone WAN from LAN firewall name ACCEPT_ALL
set firewall zone WAN from ROUTER firewall name ACCEPT_ALL
set firewall zone WAN from WORK firewall name ACCEPT_ALL
set firewall zone WAN interface 'eth0.99'

##WORK
set firewall zone WORK default-action drop
set firewall zone WORK from ROUTER firewall name ACCEPT_ALL
set firewall zone WORK from WAN firewall name ACCEPT_ICMP_AND_STATE
set firewall zone WORK interface 'eth0.40'



2 Likes