EoIP with one side behind 1-to-1 NAT: am I doing something wrong?

I’ve two networks, and I want them to be joined over the Internet using EoIP over IPsec. I prefer using no Wireguard, OpenVPN or L2TP, because, in my (relatively little, so feel free to correct me) experience, it just complicates things unnecessarily and reduces speeds compared to just EoIP over IPsec. I use hAP ac2 on one side and a hEX on the other.

I have experience setting up a tunnel (i.e. clicking a few buttons, screwing up MTU on bridges and bringing down both networks for a few days and frantically trying to fix it all) with both sides having a real static IP address, assigned directly to the routers at opposite ends of the tunnel. The problem I am facing now is that I want to set up a similar thing, but one side is behind 1:1 NAT set up by my ISP.

Now, if you search for similar topics on this forum, you will find plenty. People are setting up all kinds of stuff (without bothering to post configs). But where this topic differs is… I actually kinda did set it up already, stumbling upon my solution by accident. The problem is, what I did is so dumb, so easy and feels so wrong, I’m not sure if it’s the right way to do it.

Let’s say side A has a real public IP, and side B is behind 1:1 NAT. Side A’s real public IP is X.X.X.X. Side B’s real public IP is Y.Y.Y.Y. Side B’s fake NATted IP is Z.Z.Z.Z.

On side A I did:

/interface eoip
add allow-fast-path=no ipsec-secret=SECRET name=eoip-on-A remote-address=Y.Y.Y.Y tunnel-id=0
/interface bridge
set [find name=bridge] mtu=1500
/interface bridge port
add bridge=bridge interface=eoip-on-A
/ip firewall filter
add action=accept place-before=1 chain=input ipsec-policy=in,ipsec protocol=gre

On side B I did:

/interface eoip
add allow-fast-path=no ipsec-secret=SECRET name=eoip-on-B remote-address=X.X.X.X tunnel-id=0
/interface bridge
set [find name=bridge] mtu=1500
/interface bridge port
add bridge=bridge interface=eoip-on-B
/ip firewall filter
add action=accept place-before=1 chain=input ipsec-policy=in,ipsec protocol=gre

And it all just magically works. On side A, in IP > IPsec, I see an active peer, local address X.X.X.X, remote Y.Y.Y.Y. On side B, an active peer, local address Z.Z.Z.Z, remote X.X.X.X. On both sides, RX/TX numbers in the active peers tab seem to be in line with my expectations for what they should be (I start downloading a large file through EoIP, number go up quickly, I stop, number stop).

My question is, is this okay to use? This feels wrong for some reason. Like disabling the “drop all not from LAN” rule, “one weird trick that fixes all network problems that sysadmins don’t want you to know” that actually just opens up a huge security hole. Surely, if it was that easy, someone would have posted this already. But the only real pieces of information I could find on EoIP behind 1:1 NAT would have you either set up an L2TP connection or do IKE. Other topics don’t lead anywhere and leave you with nothing.

I’m leaving this on for now, since everything seems encrypted, and at least relatively secure (only two IPs in the entire world are accepted by the two rules). But I want to hear your thoughts. Am I doing something wrong?

I should note that

/ip firewall filter
add action=accept place-before=1 chain=input ipsec-policy=in,ipsec protocol=gre

is really just equivalent to

/ip firewall filter
add action=accept place-before=1 chain=input src-address=Y.Y.Y.Y protocol=gre

on side A and

/ip firewall filter
add action=accept place-before=1 chain=input src-address=X.X.X.X protocol=gre

on side B. In fact, I originally tested the ip-based rules and made them into policy-based after the fact because it seemed more appropriate.

In reality, I have the rule placed after ‘drop invalid’ rule and not at the top of the list.

A minor quibble

Not really:
The first says the packet has to have been originally received with ipsec security,
with the ipsec configuration defining where it was allowed to come from, its encryption etc.

The second says it has to appear to have come from Y.Y.Y.Y but doesn’t have to have been encrypted.

The part that may be confusing is there are TWO “outer” tunnels – one with ESP and another with GRE.

A 1:1 NAT should not be a problem since you just need ports 500 and 4500 for the “outermost” ESP tunnel. If you needed NAT-T — which you would not with one-to-one NAT — I’m not sure if IPSec Secret on EoIP interface also set nat-traversal=yes in /ip/ipsec. The IPSec tunnel contains GRE (the 2nd/inner tunnel) while this goes through firewall, it’s after it’s arrives via IPSec, so NAT not really an issue for the GRE part.

FWIW, the docs actually describe the subtle difference in rules under “ipsec-secret” on https://help.mikrotik.com/docs/display/ROS/Filter#Filter-Properties :

For example, if a router receives an IPsec encapsulated Gre packet, then rule ipsec-policy=in,ipsec will match Gre packet, but a rule ipsec-policy=in,none will match the ESP packet.

So, am I then correct in my understanding that the in,ipsec rules will only match GRE packets that have been received with valid ipsec authentication, identification, encryption and stuff? Theoretically, if I were to cut my fiber in half and splice in a little man-in-the-middle box that pretends to be X.X.X.X, and configure it to send GRE packets to side B, would B then reject the GRE packets, provided the man-in-the-middle box doesn’t know the correct PSK? I guess my question is, is there any possibility of someone exploiting this that I should be aware of?

The outer tunnel is IPSec – so it’s encrypted before you get to GRE (and EoIP and the underlying LAN). So unless the IPSec secret is a “hackable” or well-known password, you should be okay.

Okay, thank you! This makes me more at ease with using this setup.

I still don’t get why the input-chain gre accept rule isn’t necessary without 1-to-1 NAT, though… I see that there are two rules for ipsec policies in the forward chain in defconf. I would presume they do the job in a NAT-less setup. But why forward? Isn’t the tunnel between the routers themselves as endpoints? What’s different with NAT?

P.S. Just a bit of information I should add to this topic, EoIP uses IPsec in transport mode, and NAT Traversal checkbox is checked by default (I believe it’s in… proposals? in IP > IPsec), though it doesn’t appear to do anything in particular in this scenario.

Geez, I could have checked nat-traversal=yes.

There is the packet flow diagram might kinda help: https://help.mikrotik.com/docs/display/ROS/Packet+Flow+in+RouterOS#PacketFlowinRouterOS-FlowofRoutedPacket

But IPSec get weird in the Packet Flow… And I’m not sure myself if the IPSec & GRE are done at the same time in the “decapsulate” step, or whether it takes another loop through the packet flow (e.g. firewall). Maybe someone else know for sure.