WireGuard PBR on CHR: Traffic Marked but Not Leaving via Exit Tunnel

I’m trying to route an entire WireGuard client network (10.20.0.0/24) through another Mikrotik router (R2) by sending this traffic from my CHR “hub” router through a second WireGuard tunnel.

Both WireGuard tunnels work perfectly on their own, and all routing between R1 ↔ R2 works.

The only issue appears when CHR tries to forward 10.20.0.0/24 over the R2 tunnel.

Goal

Send the whole network:

10.20.0.0/24 → WG tunnel → CHR → WG exit tunnel → R2 → Internet

while keeping all other CHR traffic routing normally.

Problem

As soon as I enable PBR on CHR to route 10.20.0.0/24 into the R2 WG tunnel:

  • devices in 10.20.0.0/24 lose Internet access,

  • mangle marks work (packets are tagged correctly),

  • the custom routing table selects the correct route,

  • the return route on R2 is correct (10.20.0.0/24 → 10.9.0.1),

  • both WireGuard tunnels remain up and stable,

  • but CHR does NOT send any packets toward R2.

Additional findings:

  • Sniffer on CHR shows traffic from 10.20.0.x, correctly marked for PBR —

    but nothing leaves via wg-exit-r2.

  • Sniffer on R2 shows zero packets arriving from CHR for 10.20.x.x.

  • NAT counters on R2 stay at zero.

  • Disabling PBR immediately restores full connectivity.

It looks like RouterOS 7 refuses to forward traffic from one WG interface to another, even though all routes and firewall rules seem correct.

**
Question**

Does RouterOS 7 have any limitations or special requirements for:

  • routing traffic between two WireGuard interfaces?

  • using PBR / mangle with WireGuard traffic?

  • needing routing rules instead of plain mangle?

  • or is this topology simply unsupported without a different design?

Any guidance or known working examples would be greatly appreciated.

Configuration:

Configuration:  
vpn hub (R1)  

Wireguard

  name="wg-es-root" mtu=1420 listen-port=<port> private-key="" public-key=""  

name="wg-exit-r2" mtu=1420 listen-port=<port> private-key="" public-key=""  

name="wg-es-client" mtu=1420 listen-port=<port> private-key="" public-key="“  

Peers

  interface=wg-es-root name="peer90" public-key="“ private-key="" endpoint-address="" endpoint-port=0 current-endpoint-address=<port> current-endpoint-port=<port> allowed-address=10.3.57.2/32 preshared-key="" persistent-keepalive=10s client-endpoint="" rx=140.4MiB tx=87.0MiB last-handshake=1m2s  

interface=wg-exit-r2 name="peer-exit-r2" public-key="" endpoint-address="" endpoint-port=0 current-endpoint-address=<ip> current-endpoint-port=<port> allowed-address=10.9.0.2/32 preshared-key="" persistent-keepalive=10s client-endpoint="" rx=8.7MiB tx=8.8MiB last-handshake=51s  

interface=wg-es-client name="peer98" public-key="" private-key="" endpoint-address="" endpoint-port=0 current-endpoint-address=<ip> current-endpoint-port=<port> allowed-address=10.20.0.2/32 preshared-key="" client-endpoint="" rx=17.5MiB tx=193.8MiB last-handshake=9m6s   

Firewall
 NAT
 chain=srcnat action=masquerade out-interface=ether1 log=no log-prefix=""

Filters

chain=input action=accept connection-state=established,related log=no log-prefix="" 
chain=forward action=accept connection-state=established,related 
chain=input action=drop src-address-list=TCP port scanner in-interface=ether1 log=no log-prefix="" 
chain=input action=add-src-to-address-list protocol=tcp psd=21,3s,3,1 address-list=TCP port scanner address-list-timeout=1w3d 
in-interface=ether1 log=no log-prefix="" 
chain=input action=add-src-to-address-list protocol=udp psd=21,3s,3,1 address-list=TCP port scanner address-list-timeout=1w3d 
in-interface=ether1 log=no log-prefix="" 
chain=input action=accept protocol=udp dst-port=<port> log=no log-prefix="" chain=input action=accept protocol=udp dst-port=<port> log=no log-prefix="" chain=input action=accept protocol=udp dst-port=<port> log=no log-prefix="" chain=input action=drop connection-state=invalid log=no log-prefix=""chain=forward action=drop connection-state=invalid chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface=ether1

Managle
chain=prerouting action=mark-routing new-routing-mark=rtab-exit-es passthrough=no src-address-list=exit-es log=no log-prefix="" 

Routing

Tables
name="main" fib 
name="rtab-exit-es" fib 

IP Route
dst-address=0.0.0.0/0 routing-table=rtab-exit-es gateway=10.9.0.2 immediate-gw=10.9.0.2%wg-exit-r2 distance=1 scope=30 
target-scope=10 suppress-hw-offload=no

   Finish Router (R2)

Wireguard
name="Client-to-CHR" mtu=1420 listen-port=<port> private-key=""  public-key="" 

name="wg-exit-r1" mtu=1420 listen-port=<port> private-key="" public-key=""

Peers
interface=Client-to-CHR name="peer1" 
      public-key="" private-key="" 
      endpoint-address=<static IP hub> endpoint-port=<port wireguard hub>
      current-endpoint-address=<ip> current-endpoint-port=<port>
      allowed-address=10.3.57.1/32,<root network> preshared-key="" 
      persistent-keepalive=10s client-endpoint="" rx=29.3MiB tx=103.2MiB 
      last-handshake=1m57s 

interface=wg-exit-r1 name="wg-exit-to-CHR" 
      public-key="" private-key="" 
      endpoint-address=<static IP hub> endpoint-port=<port wireguard hub>
      current-endpoint-address=<ip> current-endpoint-port=<port> 
      allowed-address=10.9.0.1/32,10.20.0.0/24 preshared-key="" 
      persistent-keepalive=10s client-endpoint="" rx=8.8MiB tx=8.7MiB 
      last-handshake=1m26s 

Firewall

NAT
chain=srcnat action=masquerade out-interface-list=WAN log=no log-prefix="" 

Filters

chain=forward action=passthrough 
chain=input action=accept protocol=udp dst-port=<port> 
chain=input action=accept protocol=udp dst-port=<port> 
chain=input action=accept connection-state=established,related 
chain=forward action=accept connection-state=established,related 

Ip route
dst-address=10.20.0.0/24 routing-table=main gateway=10.9.0.1 immediate-gw=10.9.0.1%wg-exit-r1 distance=1 scope=30 target-scope=10 suppress-hw-offload=no

Sorry very convoluted description and dont understand, a network diagram would have been very helpful.

Is the CHR is the public IP and hub for two connected routers, on the SAME wireguard interface?
or
Is the CHR the public IP and hub for two connected routers, on different wireguard interfaces?

In the case of A, relay rule
add chain=forward action=accept in-interface=wireguardMain out-interface=wireguardMain

In the caase B, relay rule
add chain=forward action=accept in-interface=wireguardR1 out-interface=wireguardR2

this assumes only care when R1 needs traffic routed to R2 (originates from R1)
If the reverse is true as well (originates, not return traffic) then you need a second rule.
add chain=forward action=accept in-interface=wireguardR2 out-interface=wireguardR1

Traffic is point to point, so one has to allow the first connection on firewall rules and then permit rentry into the same or other tunnel.

Thanks for the clarification — here is the exact situation and what I tested:

Topology recap:

  • CHR (R1) is a central WireGuard hub with three separate WG interfaces:

    • wg-es-root (management link to R2)

    • wg-exit-r2 (exit tunnel R1 → R2)

    • wg-es-client (client network 10.20.0.0/24)

  • R2 is behind NAT and connects back to R1 on two WireGuard tunnels:

    • Client-to-CHR (management)

    • wg-exit-r1 (exit return path)

The goal is to route 10.20.0.0/24 from the client → R1 → R2 and let R2 NAT this traffic to the Internet.

Everything works individually:

  • Client ↔ R1: OK

  • R1 ↔ R2 (both WG tunnels): OK

  • But when PBR is applied on R1 to send 10.20.0.0/24 through wg-exit-r2, Internet stops working for the client.

What I tried based on your suggestion:

I added the relay rules on R1 firewall filter:
chain=forward action=accept in-interface=wg-es-client out-interface=wg-exit-r2
chain=forward action=accept in-interface=wg-exit-r2 out-interface=wg-es-client

Unfortunately this did not fix the problem.

The counters of the rule wg-es-client → wg-exit-r2 are increasing, so R1 is indeed forwarding packets into the exit tunnel — but R2 does not receive anything on wg-exit-r1 (sniffer stays empty).

So at the moment packet flow looks like:
10.20.0.2 → wg-es-client → R1 → wg-exit-r2 (seen on sniffer)
… but nothing arrives on R2 wg-exit-r1

This suggests the issue is somewhere between:

  • WireGuard allowed-address on R1,

  • or the exit WG tunnel on R1 not actually sending the marked traffic to R2,

  • or a conflict because multiple peers on R1 advertise overlapping allowed-address ranges.

If needed I can provide full configs again, but this is the current status:

  • PBR working on R1

  • Forward rules added (counters increasing)

  • No traffic received on R2 on exit WG tunnel

Any idea what could prevent WG on R1 from actually forwarding these packets to R2, despite the firewall seeing them leaving wg-exit-r2?

R1 → R2
/tool sniffer quick interface=wg-exit-r2 src-ip-address=10.20.0.2
Columns: INTERFACE, TIME, NUM, DIR, SRC-ADDRESS, DST-ADDRESS, PROTOCOL, SIZE, C>
INTERFACE TIME NU DI SRC-ADDRESS DST-ADDRESS PROTOC SI C
wg-exit-r2 2.806 11 -> 10.20.0.2:51855 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 2.806 12 -> 10.20.0.2:59649 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 3.137 13 -> 10.20.0.2:51355 8.8.8.8:53 (dns) ip:udp 61 0
wg-exit-r2 3.137 14 -> 10.20.0.2:51563 8.8.8.8:53 (dns) ip:udp 61 0
wg-exit-r2 3.241 15 -> 10.20.0.2:55182 8.8.8.8:53 (dns) ip:udp 64 0
wg-exit-r2 3.242 16 -> 10.20.0.2:49918 8.8.8.8:53 (dns) ip:udp 64 1
wg-exit-r2 4.152 17 -> 10.20.0.2:51355 8.8.8.8:53 (dns) ip:udp 61 0
wg-exit-r2 4.152 18 -> 10.20.0.2:51563 8.8.8.8:53 (dns) ip:udp 61 0
wg-exit-r2 4.291 19 -> 10.20.0.2:55182 8.8.8.8:53 (dns) ip:udp 64 1
wg-exit-r2 4.291 20 -> 10.20.0.2:49918 8.8.8.8:53 (dns) ip:udp 64 1
wg-exit-r2 4.539 21 -> 10.20.0.2:60268 8.8.8.8:53 (dns) ip:udp 65 1
wg-exit-r2 4.539 22 -> 10.20.0.2:49293 8.8.8.8:53 (dns) ip:udp 65 1
wg-exit-r2 4.903 23 -> 10.20.0.2:49204 8.8.8.8:53 (dns) ip:udp 56 1
wg-exit-r2 4.903 24 -> 10.20.0.2:63712 8.8.8.8:53 (dns) ip:udp 56 1
wg-exit-r2 4.904 25 -> 10.20.0.2:51855 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 4.904 26 -> 10.20.0.2:59649 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 6.243 27 -> 10.20.0.2:51355 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 6.243 28 -> 10.20.0.2:51563 8.8.8.8:53 (dns) ip:udp 61 1
wg-exit-r2 6.389 29 -> 10.20.0.2:55182 8.8.8.8:53 (dns) ip:udp 64 1
wg-exit-r2 6.389 30 -> 10.20.0.2:49918 8.8.8.8:53 (dns) ip:udp 64 1

Client → R1
/tool sniffer quick interface=wg-client-es src-ip-address=10.20.0.
2
Columns: INTERFACE, TIME, NUM, DIR, SRC-ADDRESS, DST-ADDRESS, PROTOCOL, SIZE
INTERFACE TIME NUM DI SRC-ADDRESS DST-ADDRESS PROTOC SI
wg-client-es 2.262 11 <- 10.20.0.2:49219 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.262 12 <- 10.20.0.2:57687 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.262 13 <- 10.20.0.2:53492 8.8.8.8:53 (dns) ip:udp 66
wg-client-es 2.262 14 <- 10.20.0.2:62984 8.8.8.8:53 (dns) ip:udp 66
wg-client-es 2.262 15 <- 10.20.0.2:57212 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.262 16 <- 10.20.0.2:52866 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.784 17 <- 10.20.0.2:60771 8.8.8.8:53 (dns) ip:udp 56
wg-client-es 2.784 18 <- 10.20.0.2:60091 8.8.8.8:53 (dns) ip:udp 56
wg-client-es 2.784 19 <- 10.20.0.2:55421 8.8.8.8:53 (dns) ip:udp 61
wg-client-es 2.784 20 <- 10.20.0.2:50125 8.8.8.8:53 (dns) ip:udp 61
wg-client-es 2.784 21 <- 10.20.0.2:49219 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.784 22 <- 10.20.0.2:57687 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.835 23 <- 10.20.0.2:53492 8.8.8.8:53 (dns) ip:udp 66
wg-client-es 2.836 24 <- 10.20.0.2:62984 8.8.8.8:53 (dns) ip:udp 66
wg-client-es 2.836 25 <- 10.20.0.2:57212 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 2.836 26 <- 10.20.0.2:52866 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 3.342 27 <- 10.20.0.2:63624 8.8.8.8:53 (dns) ip:udp 61
wg-client-es 3.342 28 <- 10.20.0.2:63573 8.8.8.8:53 (dns) ip:udp 61
wg-client-es 3.448 29 <- 10.20.0.2:52136 8.8.8.8:53 (dns) ip:udp 64
wg-client-es 3.449 30 <- 10.20.0.2:57061 8.8.8.8:53 (dns) ip:udp 64

R2 from R1:

/tool sniffer quick interface=wg-exit-r
1 src-ip-address=10.20.0.2

R2 → R1
/tool sniffer quick interface=wg-exit-r
1 dst-ip-address=10.20.0.2

Okay, let me get this straight
You have R1 CHR
You have R2 behind NAT on a mikrotik Router??
You have R3 behind NAT on an unknown Router but has a subnet of 10. that needs to go out the internet of R2??

In other words, where is this subnet 10 coming from................

Plus post both MT configs
/export file=anynameyouwish (minus router serial number, any public WANIP information, keys, dchp lease lists)

Thanks for the reply — here is the simplified explanation:

  • R1 (CHR) – central VPN hub with a public IP.

  • R2 (MikroTik behind NAT) – connects back to R1 using two WireGuard tunnels.

  • There is no third router.

The network 10.20.0.0/24 is just the client network directly connected to R1 on the wg-es-client interface.

These are end devices, not another router.

My goal:

10.20.0.0/24 → R1 → via wg-exit-r2 → R2 → Internet

Everything works by itself:

  • clients ↔ R1 OK

  • R1 ↔ R2 OK

The problem only appears when I enable PBR on R1 — then traffic is forwarded into wg-exit-r2 (confirmed in sniffer), but nothing arrives on R2.

I can provide a full /export if needed (sanitized).

Like pulling teeth.
is CHR a cloud server device Y/N
is CHR a computer sitting in a house Y/N
does the CHR have a public IP from the internet ISP modem Y/N
does the CHR provide internet for all attached devices to this computer network y/N
does the CHR have any subnets. Y/N and which ones ??????

finally, what is providing the DHCP network to the devices with 10.20.0.0 subnet??

Basically what I dont get is a client network physically attached to the CHR but connected by wireguard simply does not compute. None of my local devices attached to my router need wireguard to connect to my router, they are local!!

How do they physically connect to the R1 CHR, by ethernet cable ( is your CHR a computer with multiplle nic cards?? ), Is there another router that provides a home network but without internet that is
connected to the CHR on a second nic.

How does the CHR physically connect to the internet

CHR is a MikroTik CHR running on a VPS. It is a cloud server, not a physical device. It has only one real network interface – the virtual NIC provided by the VPS. This NIC has a single public IP.

There are no local devices physically connected to the CHR. It does not provide internet to any LAN. All networks exist only inside WireGuard tunnels. Every WireGuard interface on CHR is its own virtual subnet. Examples:

wg-es-root = 10.3.57.0/30
wg-exit-r2 = 10.9.0.0/30
wg-es-client = 10.20.0.0/24

These are not physical networks. There is no ethernet, no home LAN, no WiFi – just WireGuard tunnels.

The 10.20.0.0/24 client network is simply a WireGuard network for remote clients. There is no DHCP. Clients get static IPs because they are defined directly in WG peer config (for example 10.20.0.2/32). So this network exists only inside the CHR as a WG interface. It is not “physically attached”.

Clients connect to CHR only via the internet, using WireGuard to the public IP of the CHR. CHR connects to the internet via the single VPS NIC.

So in short: CHR is only a virtual VPN hub with one physical interface. All other subnets are virtual WireGuard subnets. The 10.20.0.0/24 network is just a WG client network, not a physical LAN.

So:

  1. Yes
  2. No
  3. Yes
  4. No
  5. Yes — but only virtual subnets inside WireGuard interfaces.
  6. No dhcp

Problem solved.

Problem was in allowed address in peer on R1.

I cannot help you then.
There are no users on the CHR and no devices attached.
Having nobody on a wireguard interface with its host is meaningless.
Nobody I know has a local subnet on a router CHR or not, wireguard to the same router??
I am thinking this is a prank post now.
I am outta here is my first reaction...

But I will play...
So you remote clients lets say an array of clients on remote devices that you want to use the Internet of R2, for some strange reason you dont want them to use the internet of R1?? the CHR.

connect to the CHR, and then go out the internet of R1. That would have been much easier to say.

+++++++++++++++++++++++++++++++++++++++++++++++++

So lets make this clear, there is NO client subnet on CHR, thats BS.
There is a wireguard interface that serves a bunch of people and their devicies that need to reach R2. I say this because WEIRDLY, none of them are to use the outgoing internet of the CHR.

Very doable.
What I dont understand is why you dont have them on the same wireguard interface??
In other words there are requirements you are not stating. Does anybody on R2 need to go out the internet of the CHR, I dont think so, at least not stated.
Does anybody on R2 need to reach the remote devices laptops that are coming into the CHR via wireguard, I dont think so, at least not stated.

Hence all we have is bunch of devices need to reach R2 and because R2 does not have a public IP, we use CHR to glue them together. However, to be clear there has been NO requirement stated that these remote devices need to reach R2, they only are supposed to go out the internet of R2.

But clearly, I dont have the right picture quite yet, as by this statement. Besides going out internet you state: "while keeping all other CHR traffic routing normally".

What other CHR traffic routing normally???? USE FACTUAL language, not vague statements

As I stated already, provide both configs, clear set of requirements and this is a done deal in 5 minutes.

As I write upper - I solved it, but ok, we can talk about it for transparency.CHR (R1) is a virtual router on vps servers with public IP.I use it to communicate a lot of end devices divided on interfaces wireguard.

For example at this moment:

Interface wireguard for company xyz for:

  • administration network devices
  • connect other end devices to they network, becouse they company don't have public IP but users need to use VPN

That problem, what I had was with tunneling one of wireguard tunnel. In this situation I had to forward all trafic client in network 10.20.0.0/24 to exit in Wan interface on R2 witch don't have public IP, so I couldn't make directly interface betwen client and R2.

My R1 works in netherlands, R2 works in spain. Client he had to represent himself with a spainish IP.

If you want to know exacly how works my chr I can tell you something more but this is not a problem at topic.

I sent picture about this topology.

end devices (works as peer to CHR)

root: 100.100.100.2 network: 100.100.100.0/24
client: 10.20.0.2 network 10.20.0.0/24
xyz: 10.0.5.2 network 10.0.5.0/24
xyz-1: 10.0.5.3 network 10.0.5.0/24
xyz10: 10.0.10.2 network 10.0.10.0/24
xyz10-1: 10.0.10.3 network 10.0.10.0/24

CHR
wg-root-r1: 100.100.100.1/24
wg-client-R1: 100.100.125.1/24
wg-company-xyz: 10.0.5.1/24
wg-company-xyz10: 10.0.10.1/24
wg-root-r2: 100.100.110.1/30
wg-client-es: 100.100.120.1/30

R2
wg-root-R2: 100.100.110.2/30
wg-return-R1: 100.100.120.2/30
ether1 → ISP

all IPs are for examples

My fault was in peer allowed address configuration on R1 for tunnel wg-client-es. I change it to 0.0.0.0/0 and forwarding via PBR starts work perfectly.

I will be happy to answer any other questions.

Thanks for help.

Best regards

Starting to make much more sense.
So company X has users that need to reach company X remotely by secure means and they use your CHR service for that. However that means Company X has a wireguard capable router to be in the loop.
It doesn't have to be a MT router but any router, they could even put a CHR on computer within the company and at least establish a working link to your CHR for that purpose.

Note: remote user to remote user (laptop to laptop) makes very little sense.

You have a client that needed an IP in SPain. Your CHR gets a netherlands WANIP, but you have some resource (client router or another router of yours) in SPain that is R2.
THus you can route your client through your R1 CHR and out the internet of R2.

All makes sense, my question was, what are the use cases for users on R2, do any of them need internet out the CHR (to browse).

What about all the rest of the remote clients that connect to R1 (CHR), do they all simply use it to connect to client routers? Do some of them need internet access out the R1 (CHR)?

Configuration of the CHR and of the MT (R2) are dependent upon the requirements/use cases in total.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  1. Wireguard SPain (should exist on R2 but have no local usage ), Okay I see that you use a separate management wireguard interface to configure both CHR and R2, although you could simply use the R2 connection do to so but you prefer the separation as best practice. COncur!!!

Client4Spain connects to CHR and then gets sent to R2, and out the internet on R2.

CHR

/interface wireguard
add interface=wgES  listening port=45678
/ip address
add address=10.60.80.1/24  interface=wgES network=10.60.80.0
/firewall
add chain=input action=accept comment="handshake" dst-port=45678 protocol=udp
add chain=forward action=accept comment="relay"  in-interface=wgES out-interface=wgES
/wireguard peers
add allowed-address=10.60.80.2 interface=wgES name=Client4Spain public-key=
add allowed-address=10.60.80.3 interface=wgES name=R2 public-key=

R2 (in Spain)

/interface wireguard
add interface=wgWWW  listening port=13231
/ip address
add address=10.60.80.3/24  interface=wgES network=10.60.80.0
/firewall
add chain=forward action=accept comment="internet for wgWWW"  in-interface=wgWWW \
  out-interface-list=WAN
/wireguard peers
add allowed-address=10.60.80.0/24  interface=wgES endpoint-address=CHR \
endpoint-port=45678 persistent-keep-alive=30s name=remoteclients public-key=

But is that enough? Lets follow an example.
On the client side, the remote client will have to set 0.0.0.0/0 on his device (to reach any internet address). He connects to the CHR via the proper settings.
a. chr allowed addresses ( accepts src-address 10.60.80.2 )
b. traffic hits the LAN of CHR
c. destination address of packet is WWW ( anything )
d. chr forward chain allows traffic to exit the tunnel and re-enter the same tunnel.
e. BUT what prevents www traffic from going out CHR*** ( at least route wise if not also firewall rules wise )

*** Problem how does the CHR know to send this traffic to R2?

/routing table
add fib name=redirect
/routing rule
add action=lookup-only-in-table src-address=10.60.80.2  table=redirect
/ip route
add dst-address=0.0.0.0/0 gateway=wgES routing-table=redirect

Which Means we need to adjust our CHR peer settings to be:
/wireguard peers
add allowed-address=10.60.80.2 interface=wgES name=Client4Spain public-key=
add allowed-address**=0.0.0.0/0 i**nterface=wgES name=R2 public-key=

Not the typical discrete allowed address normally used for client peers. However in this case its really a one way traffic thing, only originating from the remote client. The routing rules are needed to ensure the remote client traffic does not use the WAN of the CHR and more precisely to ensure the traffic goes back out the wireguard tunnel, where allowed addresses helps select the correct peer.

not excatly.

End devices in company are pc / laptops - not routers , becouse they have only ISP routers - cost reduction.

So for comuniaction bettwen locations we use CHR as like vpn hub for this clients.

Exactly looking like:

Company X have some shops and one is head quarter (head shop) - main database.

Computers in shops need comuniaction with main database for exchange information.

I not tunneling all trafic from computers to chr - just "creat a local network for this" via chr.

It's work like radminVPN or hamachi - topology.

In others compans I have end routers so there I can managment all networks in location.

This is a long topic - I think that it might be interesting but not here. This topic is about problem with pbr via wireguard.

Yes, my client (endpoint device - computer), need represent as spanish IP. Some webs works only here (websites of local goverment office). Here we have:

Router ISP and second router physical mikrotik hAP-ax-lite.

hAP-ax-lite (R2) works only like VPN gateway - anyone alse users don't use him.

Local network in spain works on ISP router.

Just root network for administration has all traffic tunneling via CHR - it's more comfortable than all time add new networks to peer on end devices. But it's work only for peers (end computers) - no one more devices are full tunneling via chr.

At this moment configuration looks like:

CHR

/interface wireguard
add listen-port=x mtu=1420 name=wg-client-es
add listen-port=x mtu=1420 name=wg-root-es
add listen-port=x mtu=1420 name=wg-exit-r2

/ip address
add address=10.3.57.1/30 interface=wg-root-es network=10.3.57.0
add address=10.20.0.1/24 interface=wg-client-es network=10.20.0.0
add address=10.9.0.1/30 interface=wg-exit-r2 network=10.9.0.0

/interface wireguard peers
add allowed-address=10.3.57.2/32 interface=wg-root-es name="" persistent-keepalive=10s public-key=
add allowed-address=10.20.0.2/32 interface=wg-client-es name="" public-key=""
add allowed-address=0.0.0.0/0 interface=wg-exit-r2 name="" persistent-keepalive=10s public-key=

/routing table
add disabled=no fib name=rtab-exit-es

/ip route
add disabled=no dst-address=0.0.0.0/0 gateway=10.9.0.2 routing-table=rtab-exit-es suppress-hw-offload=no

/ip firewall mangle
add action=mark-routing chain=prerouting new-routing-mark=rtab-exit-es passthrough=no src-address-list=exit-es

R2 (spain)

/interface wireguard
add listen-port=<port> mtu=1420 name=Client-to-CHR
add listen-port=<port> mtu=1420 name=wg-exit-r1

/ip address
add address=10.3.57.2/30 interface=Client-to-CHR network=10.3.57.0
add address=10.9.0.2/30 interface=wg-exit-r1 network=10.9.0.0

/interface wireguard peers
add allowed-address=10.3.57.1/32,<root network> comment=wg-admin endpoint-address=<public ip chr> endpoint-port=<port chr> interface=Client-to-CHR name=peer1 persistent-keepalive=10s public-key=""
add allowed-address=10.9.0.1/32,10.20.0.0/24 endpoint-address=<public ip chr> endpoint-port=<port chr> interface=wg-exit-r1 name=wg-exit-to-CHR persistent-keepalive=10s public-key=""

/ip route
add disabled=no distance=1 dst-address=<root network> gateway=10.3.57.1 routing-table=main scope=30 suppress-hw-offload=no target-scope=10
add disabled=no dst-address=10.20.0.0/24 gateway=10.9.0.1 routing-table=main suppress-hw-offload=no

Deliberately I don't send " /ip firewall filters" because I observed as wireguard work good without them.

Obviously I have it add (accept ports from wireguard), but it's look like not obligatory.

Exactly YES !

When I created this topic, peer between R1 R2 had allowed-address like this:

/interface wireguard peers
add allowed-address=10.9.0.2/30 interface=wg-exit-r2 name="" persistent-keepalive=10s public-key=

When we started talk about this problem, I trying to solve it.
I try with allowed-address=0.0.0.0/0 and it's started works.
Never before I don't used allowed-address=0.0.0.0/0 on peer between routers - only in endpoint peers for tunneling all trafic.

I don't know what push me in this way, but it was a good leason for me.

Before, I looked on allowed-address in wireguard like:

here you need to add interface ip from second device to have comuniaction and if you need use more locals networks at this device - add them too.

It sounds very shallow, but it has always worked.

I hope someone who will have the same or similar problem - he could find answer here.

Yes its not typical to set peers to 0.0.0.0/0 at the host router (for handshake) for a connected client peer router. However in this case since there are no other conflicting requirements it makes sense.
Your client will be coming with all possible addresses and thus we have ensure that is possible as your CHR wireguard routing is the key to that part. The other part is ensuring that traffic goes back out the same interface to the spain router and for that we need a routing rule, table and ip route.

In terms of the other scenario, nothing strange there, you can use the CHR to connect any two wireguard clients to each other, easy peasy. There is no subnet on the router that has clients or devices on it, as you described, only wireguard interface networks, enough of them to serve the different clients.