i am at a pickle and would really appreciate some help.
I have a CHR hosted on Hetzner VM which i am trying to connect to a local site. The CHR has 2 interfaces one (ether0) is WAN and the other (ether1) is LAN. LAN interface has the address 192.168.254.2.
I have established an IPsec tunnel which is stable. Problem is traffic is not passing through the tunnel. I cannot ping devices on site b normally. I can only ping them via:
ping src-address=192.168.254.2 address=siteb ip . Trying to ping from site b to the CHR does not work at all.
Now i have added the following NAT rule on top: /ip firewall nat add action=accept chain=srcnat out-interface=ether1 ipsec-policy=out,ipsec
I also have firewall filter rules to accept ipsec traffic in and out, (/ip firewall filter add action=accept chain=input ipsec-policy=in,ipsec and /ip firewall filter add action=accept chain=input ipsec-policy=in,ipsec)
and added another for
/ip firewall filter add action=accept chain=input protocol=ipsec-esp
i also tried adding raw rules to preroute traffic between the source and destination subnets with no track.
Could anyone tell me what i am doing wrong? I have been scouring the forum trying to find the solution but have not found it.
edit: forgot to add that siteb is a Mikrotik router under NAT with similar rules (except the first NAT one).
Post anonymized exports of configurations of both routers.
Do both of them have public IP addresses directly one their WANs? Some ISPs block other IP protocols than ICMP, TCP and UDP, so maybe ESP does not get through, but since you can ping through the tunnel at least unders ome circumstances, the reason will be different.
edit/ since i can ping when using as source the address of the LAN port, it leads me to something being wrong with my routing or rules but i cannot find what. CHR.rsc (6.66 KB) siteb.rsc (12.2 KB)
First,I’d recommend to add in-interface=ether2 to the two rules in chain input of /ip/firewall/filter that allow access to the DNC ports (TCP and UDP 53), otherwise you’ll soon receive a notification from Hetzner that your network interface has been disconnected because it was sending suspicious traffic.
Second, you may want to remove the public IP of SiteB from the export from CHR.
I also added the in-interface=ether2 to the filter rules. Which strangely resulted in my inability to ping devices in siteb even when using as source the ether2 address.
OK. 12 out of 10 network engineers would tell you that your results are much better if you know what you are doing. So a bit of theory first:
in all firewall chains, the default behavior is accept, and unlike in Linux netfilter, this is not configurable. So to block traffic that did not match any action=accept rule in filter, you need to ad an explicit action=drop one to the end of the list. On multiple places in your two configurations, such a rule is either present but disabled or missing completely, so what is not accepted explicitly is accepted by default anyway in those chains.
the connection tracking module of the firewall is the cornerstone of both the stateful firewall approach and NAT treatment. If a packet that could otherwise initiate a tracked connection matches an action=notrack rule in raw, it does not create a tracked connection in the firewall, so no NAT treatment is possible and the value of its connection-state metaheader is set to untracked. So the action=accept (if) connection-state=established,related rule cannot handle responses to such a packet because the connection tracking module cannot recognize them as responses. But they may themselves create a tracked connection if the raw rules are not “symmetrical”. So you have to
either prevent the IPsec payload packets initiating new connections from matching the src-nat/masquerade rule, either using action=accept rules before the src-nat/masquerade ones or by adding an ipsec-policy=out,none match condition to the src-nat/masquerade ones
or exclude both directions of IPsec payload traffic from connection tracking completely, but then you have to place appropriate rules into filter chains input and forward that will accept this traffic without relying to connection-state=established (the rules in the default firewall configuration, accept ipsec-policy=in,ipsec and accept ipsec-policy=out,ipsec, are present in forward but if you want to be able to ping/access also the router itself using the payload addresses, you have to add them also to input). On the other hand, these “accept any IPsec payload” rules may be actually too permissive for your use case, i.e. you may want to apply some restrictions even to packets that have arrived as IPsec payload.
if both IPsec peers have public addresses, which seems to be your case, they only use UDP for the control session - IKE(v1) or IKEv2. To transport the encrypted payload traffic, they use bare ESP (because it leaves more space in the MTU for the payload than UDP-encapsulated ESP). But if no payload traffic exists for a long time (by default, 10 minutes), the corresponding connection for ESP times out from the tracking table. So once a payload packet arrives from the LAN side on one (local) peer, that peer encrypts it into ESP and sends the ESP to the other (remote) peer, which creates the tracked connection in its own firewall so an eventual ESP packet from the remote peer would be able to get in, but unless there is an accept rule for ESP in chain input of filter on the remote peer, the remote peer drops the ESP packet rather than extracting the payload from it, so the response payload packet will never get sent, so it will not get encapsulated into ESP and sent to the local peer. In your case, the accept ESP rule is only present on the CHR, so if you attempt to ping from the CHR side to the Site B side, the above prevents the ping from succeeding unless you are “fast enough” to do that before the ESP pinholes created by a request packet in the opposite direction time out.
when the router itself sends a packet that initiates a new connection, it first chooses the route and only then the source address to use. So when pinging from the router, you must either set the src-address manually or you have to add routes towards the remote subnets reachable via IPsec with pref-src set to a local address that matches the IPsec policies.
So sort out the above and if it still does not work as expected, come back with new exports.
And of course the general recommendation, especially when you do not understand the way IPsec traffic works, is to not use a direct IPsec tunnel but instead use some other tunnel type (GRE, IPIP, L2TP, or even EoIP) over IPsec transport.
That will make it all work much more intuitively!