Traffic rule question, only allow one-way sessions

I broke out this from my WG topic, as WG part is resolved.
Basically, I have site-to-site Wireguard link that works fine.
Link is between Site A (192.168.0.x) and site B (192.168.1.x). Right now, traffic is open in both directions.
I would like to create a traffic rule that allows site A to create a session to site B (basically , site A to ping IP's in site B) but not other way around.

P.S.
Creating a zone for whole WG interface was proposed, but my WG server has multiple peers with different needs so I would prefer to solve this with traffic rules, if possible.

Thanks

It is necessary to have separate zones to do any meaningful firewalling. If most peers are allowed to forward, you could have a forwarding which will be the default, and rules to deny certain peers based on their src_ip. (Unlike most IP based firewalling) this is secure against a peer attempting to elevate access by changing its IP, since then it would not be in the wireguard allowed_ips and Wireguard would block everything from the peer.

If you do this approach, the deny rules must be listed first in the file above the config forwarding. Firewall rules are checked in order and the first one to match is the final decision.

1 Like

OK, understood. If I move whole WG interface to separate zone, can I still do fine grained config on different WG peers? (I have 4 peers, using 10.0.0.2,3,4,5 in WG)

The Wireguard config would not change. The firewall would act on packets from the inward facing wgX interface after they have been decrypted and left Wireguard.

Do I set up new zone on (WireGuard) server router or client router?
My current WG interface on client (router B) is configured like this:

On site B, create a rule that will be inserted into the (main) forward chain.

config rule
        option name 'Block-B-to-A'
        option src '*'
        option dest '*'
        option src_ip '192.168.1.0/24'
        option dest_ip '192.168.0.0/24'
        list proto 'all'
        option target 'REJECT'
2 Likes

Thanks a million!

BTW, is it possible to create such a rule on router A instead of router B?

(In case router B is physically compromised, it is better to block it on server node)

Yes, but better just duplicate the (same) rule on Router A. This way, the traffic will originally be stopped on router B (and will not pass through the tunnel at all), but in case of intrusion, it will be stopped by router A.

1 Like

Thank you for your help. I am almost there! Adding the rule to Router B (cottage) did indeed stop traffic from B to A.

But when I duplicated the rule to Router A and tried to test it (by only aving it enabled on router B) it did not not stop the traffic. (I double-checked and restarted the firewall as well). Any hint on what I am doing wrong?

Of course you have to reverse the sense of src and dest when implementing a rule on the other end of the link, and be sure to put your block rule above the default allow all forwards. (Or if you are writing it as an allow rule, the default needs to be to block).

The direction is always the same - router B => router A (192.168.1.0/24 => 192.168.0.0/24), so you don't need to reverse anything.

Disable the rule on router B and if you can still access LAN A from LAN B, please post the result of this command executed on router A:

nft list chain inet fw4 forward

I was still able to access LAN A from LAN B. This is the output of "nft list chain inet fw4 forward":


root@OpenWrt1:~# nft list chain inet fw4 forward
table inet fw4 {
        chain forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
                ip saddr 192.168.1.0/24 ip daddr 192.168.0.0/24 counter packets 37 bytes 3048 jump handle_reject comment "!fw4: Block-B-to-A"
                iifname { "br-lan", "wg_lan" } jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
                iifname "eth1" jump forward_wan comment "!fw4: Handle wan IPv4/IPv6 forward traffic"
                iifname "eth0.5" jump forward_GuestZone comment "!fw4: Handle GuestZone IPv4/IPv6 forward traffic"
                iifname "eth0.4" jump forward_IoTZone comment "!fw4: Handle IoTZone IPv4/IPv6 forward traffic"
                jump handle_reject
        }
}

This is on router A, right?
There are hits on the rule, so some traffic has definitely been rejected.

If the rule on Router A doesn't work as expected, I have only one explanation; The wireguard interface on Router B is assigned to a firewall zone where masquerading is enabled, so Router A sees this traffic originating from Router B's wireguard IP address.

Is that the case?

Hi Pavel,

Many tanks for trying to help a newbie like me.

WireGuard interface on router B is member of these two firewall zones:

Should I move it to separate zone? In that case, how should be configured?

In general, assigning an interface to more than one firewall zone is a mistake, but in this case that is not the cause of the problem.

When you say you can access LAN A from LAN B, do you mean you can access it from a host on LAN B or from router B itself?

I can access any IP on LAN A (192.168.0.x) from any IP on LAN B (192.168.1.x) despite having this rule on LAN A router:

config rule
        option name 'Block-B-to-A'
        option src '*'
        option dest '*'
        option src_ip '192.168.1.0/24'
        option dest_ip '192.168.0.0/24'
        list proto 'all'
        option target 'REJECT'

Only way to block B to A traffic is to enable this rule on router B. That is fine, but there is a potential security risk with having client device deciding what is allowed and what is not allowed.

Basically, I would like to prohibit one of four WG peers (which is using 10.0.5.5 to connect LAN A to B) from accessing LAN A.

Please run this on router B and post the result.

for zn in $(uci show firewall | grep \=zone | cut -d "[" -f2 | cut -d "]" -f1); do echo zone $zn; uci show firewall.@zone[$zn]; done

Router B:

root@R:~# for zn in $(uci show firewall | grep \=zone | cut -d "[" -f2 | c
ut -d "]" -f1); do echo zone $zn; uci show firewall.@zone[$zn]; done
zone 0
firewall.cfg02dc81=zone
firewall.cfg02dc81.name='lan'
firewall.cfg02dc81.input='ACCEPT'
firewall.cfg02dc81.output='ACCEPT'
firewall.cfg02dc81.forward='ACCEPT'
firewall.cfg02dc81.network='lan' 'WireGuard'
zone 1
firewall.cfg03dc81=zone
firewall.cfg03dc81.name='wan'
firewall.cfg03dc81.input='REJECT'
firewall.cfg03dc81.output='ACCEPT'
firewall.cfg03dc81.forward='REJECT'
firewall.cfg03dc81.masq='1'
firewall.cfg03dc81.mtu_fix='1'
firewall.cfg03dc81.network='wan' 'wwan'
zone 2
firewall.cfg0fdc81=zone
firewall.cfg0fdc81.name='WireGuard'
firewall.cfg0fdc81.input='ACCEPT'
firewall.cfg0fdc81.output='REJECT'
firewall.cfg0fdc81.forward='REJECT'
firewall.cfg0fdc81.network='lan'

OK, I got it almost-almost-almost to work :smiley:

When I enable rule on router A, devices on network B cannot ping devices on network A except router A. Also, if I ping A from router B shell everything is still open/pingable.

Basically everything behaves as it should, except router A (only) is still pingable from B unless rule is enabled on both A and B.