IPSec is working - now how should I have done it?

After beating my head against a software wall (which is much more painful than a stone wall) - I finally got the remote access I needed functioning. However - I refuse to believe that the unholy union of software and setup I brought into being conforms to the will of Cerf & Kahn. So I beseech the prophets of this forum to show me a better path.

The goal: access remote LAN 192.168.42.0/24 via IPSec.

First, I established a IKEv2 connection, with explicit policy template, proposal, peer, identify, mode - all the fun stuff. My primary router is the responder - so the mode config lists the “local” networks that need to access the remote. The local router has IPSec endpoint 10.21.3.1 and the remote is 10.21.3.8.

This worked - just fine. Didn’t need anything else - the primary router NAT rules were predefined, worked with other IPSec clients, and since the “identity” included a “notrack-chain=prerouting” nothing else was needed. If it matters, I will mention that I have no masquerade rules on that router - everything is explicit srcnat. But…I could not come up with any combination of routing definitions or NAT that would allow me to reach 192.168.42.1 from the main router. Googling, googling, googling, fighting, fighting, fighting…

Before I continue - my first question: is it possible to achieve my goal with the above setup (just with the right magic incantation of routing & NAT rules)?

I found a reference to GRE as the possible solution. I’m inferring that of the tunnel options GRE has the least overhead when compared to IPIP or EoIP (and I don’t know if there’s any other comparable choices). So…I tried GRE. Because I had a working IKEv2 connection I chose to use it to transport the GRE. I simply set the remote addresses at each end to the opposing IPSec endpoints - and the tunnel came up.

Next question (if nothing I said above is objectionable): leaving everything else at the defaults the MTU came up at 1398. Do I want to leave it there? Do I change anything else at the GRE level?

Now I added addresses to the GRE of 10.41.0.1 (local) and 10.41.0.2 (remote). And…they can reach each other. I added a route to the remote LAN 192.168.42.0/24 via 10.41.0.2…and the router can see it! Major milestone reached!

But nothing else can. Sigh. Ok…start poking with srcnat. First, on the local router, I set a srcnat with dst-address=10.41.0.0/24 to-address=10.41.0.1. That allows the local network to reach the remote 10.41.0.2…which isn’t really needed but ok. So then I add a srcnat with dst-address=192.168.42.0/24 to-address=10.41.0.1…and I can see packets hitting the remote but not coming back. So then the last item was adding on the remote router a srcnat with dst-address=192.168.42.0/24 to-address 192.168.42.1…and it all works! It works!

But it’s ugly. Incredibly ugly. I have to believe there’s a better way. Please, please, help me to see the light and show me the path to network enlightenment.

Your steps are OK but instead of doing a NAT you can just add a route.
You add a route for the destination network via the tunnel, and traffic will just pass through that without being translated.
Of course this assumes that the devices on each of the tunnel have their specific router as their default gateway, so they know how to route traffic back.

I love GRE for Mikrotik to Mikrotik IPSec tunnels.

/interface gre
add allow-fast-path=no ipsec-secret=<PSK> local-address=<local DDNS hostname>.sn.mynetname.net *OR* <local public IP> name=<tunnel name> remote-address=<remote DDNS hostname>.sn.mynetname.net *OR* <remote public IP>

Then

/ip address
add address=172.30.30.1/30 interface=<tunnel name> #local tunnel IP

Then

/ip route
add dst-address=<remote subnet> gateway=172.30.30.2 #next hop remote tunnel IP

Do the same on the other router and that should work.

Mikrotik’s GRE+IPSec implementation uses the default IPSec policy and profile. Because of this, if you have different versions of RouterOS, sometimes you have to tweak the default IPSec settings so they match.

I tried that - just routing by itself was insufficient without at least one srcnat. I haven’t tried removing some of the defined rules yet (still tired from yesterday) but the fact that the rules are matching current traffic makes me believe they’re still needed - at least given my current setup.

I still haven’t quite figured out when “pure” routing is enough vs when srcnat is required. I’m at the point where I just try routing then start throwing srcnat at the problem until things work. But I’d really like to understand the why part so I’m doing less trial-and-error guesswork.

Other than reduced configuration - is there any difference between using the built-in IPSec functionality of the tunnels vs manually creating the IPSec connection and running the tunnel over that? I’m operating under the (probably mistaken) belief that IKEv2 can only be setup manually and the IKEv2 is “better”.

If the only protocol required to be supported is IPv4 - am I saving/improving much if I use IPIP instead of GRE?

The built-in functionality creates the IPsec policy in transport mode (where the source and destination addresses of the payload packet are not sent to the peer), so you cannot use it if there is NAT somewhere between the peers. To set up a GRE/IPIP/EoIP tunnel between such peers, you need to manually set up the IPsec part and use tunnel mode of the policy (tunnel=yes).


Yes, the built-in functionality uses only IKE(v1) in main mode (exchange-mode=main). I also have a feeling that IKEv2 is “better” but I am no cryptoanalyst so it’s just a belief. What is most important for security is to use certificates (not possible with built-in functionality) or at least long and random shared secrets. I have seen somewhere on the web a generator of shared secrets which allows the peers’ administrators not to send them to each other - both of them just have to copy-paste the secret from that web at the same minute or so. Of course they have to agree on how many byte positions they will shift these 3rd-party-provided keys if that 3rd party would be recording them and using them for vocabulary attacks.


You save 4 bytes of overhead per packet (Mikrotik only uses the mandatory GRE header fields), and some headache coming from the “security patch” causing GRE packets to be treated unexpectedly in firewall (“new” incoming GRE packets are marked as “invalid”).

When using plain ipsec tunnel mode (no gre/ipip/…), you’ll have to make sure the router picks the correct local address to be matched with ipsec policy.
This only applies to connections initiated on the device itself.

Remote LAN = 192.168.42.0/24
Local LAN interface = bridgeLocal

/ip route add dst-address=192.168.42.0/24 gateway=bridgeLocal

When you have a site behind NAT connecting to another site without NAT, you can set the local address to the address of the router at each end (so the RFC1918 address at the NATted end) and the remote address will be the public IP of eachother. Then it will just work with the default auto-generated settings.
So:
“central” router without NAT:
Local address 1.2.3.4
Remote address 4.5.6.7
IPsec secret: whatever you choose

“connecting” router with NAT:
Local address 192.168.1.2 (for example)
Remote address 1.2.3.4
IPsec secret: whatever you choose

Right you are. I’ve mixed together two things, the NAT traversal (which can be addressed the way you suggest) and the dynamically changing local WAN address. So on the peer where the WAN address is changing, it used to be necessary to update the local-address on the /interface gre row e.g. using the lease script on the dhcp client, or you could link the tunnel end to some private address (which was static) and use tunnel mode.

When you have different local network addresses on each site and you have explicit tunnels between them (GRE or IPIP, over IPsec of course) you will not require NAT.
The traffic towards the other network can just be sent through the tunnel and delivered on the other network, and vice-versa.
But of course there are some pitfalls:

  • the systems at the other network have to know how to route the traffic back (i.e. the routers you are now configuring have to be the default gateway for them)
  • the firewalls on those systems have to trust the new network addresses you are now adding (often by default firewalls allow more from addresses on their local network than from addresses on other networks)
  • the issue of the smaller MTU of the tunnel has to be handled properly: systems must not block ICMP “fragmentation needed” (as sometimes happens when clueless admins have configured firewalls to “drop all ICMP” thinking that ICMP means “ping”)

It is usually a good idea to install this mangle rule on all routers:

/ip firewall mangle
add action=change-mss chain=forward comment=\
    "Clamp MSS to MTU on all forwards" new-mss=clamp-to-pmtu passthrough=yes \
    protocol=tcp tcp-flags=syn

That will trim the MSS sent on a TCP connection setup to the smallest MTU along the path (in this case your tunnel MTU), avoiding the need for fragmentation and path MTU discovery.