This guide describes the following situation:

  • VPN site-to-site tunnel using IPSec setup is created in MikroTik routers between two private networks: 10.10.10.0/24 and 10.10.20.0/24
  • Both private networks use MikroTik router as a gateway
  • Each MikroTik router is behind a NAT and have private network range on WAN ports as well: 192.168.10.0/24 and 192.168.20.0/24
  • Each MikroTik router has IPSec protocol, NAT-Traversal (4500/UDP) and IPSec IKE (500/UDP) traffic forwarded from its gateway (ISP Router)
  • Both public network connections change public IP occasionally

IPSec Tunnel with Peers behind NAT

Some more remarks:

  • I didn’t find any guide which would describe this setup, so I created one.
  • Before the start, make sure that you have a separate access to each router, in case you will break your connection.
  • Examples contain some additional security settings which can provide better security, often for the cost of performance ( pfs-groups modp4096, etc ). Before you use or change these settings, make sure you know what you are doing.
  • IPSec tunnel setup in examples uses pre-shared-key authentication method, which has been chosen only for demonstrative purpose and more secure method should be considered. In any case, make sure that if you are going to use PSK method then you need to use a different secret than the one in the examples – also don’t forget that the secret needs to be the same on both sides.
  • Names of interfaces on MikroTik routers in this example are:
    • WAN: ether1-gateway
    • LAN: bridge-local
  • I tested setup on 2x Mikrotik hAP lite classic devices, each running behind different routers ( Draytek Vigor 2700 and Ubee EVW3226 )
  • Also there is a lot of useful documentation about IPSec VPN on MikroTik Wiki – check it out.

Update 1:

  • I have experienced tunnel instability when upload link ( provided by ISP ) has been overloaded and when IPSec tunnel was configured with AES GCM. This issue occurred for me at least on Router OS versions 6.38 – 6.39.1. Therefore I have updated the example to use AES CBC, which proved to be stable.

IPSec

VPN Tunnel

IPSec tunnel will provide secure site-to-site VPN. If peer address and policy SA destination address is not yet known, use 127.99.99.99/32 instead as a temporary placeholder ( like in this example ). Later on addresses will be updated automatically by script.

MikroTik router 1
/ip ipsec
peer add comment="vpn01" address=127.99.99.99/32 local-address=0.0.0.0 nat-traversal=yes auth-method=pre-shared-key secret=REPLACE_THIS_WITH_RANDOM_SECRET lifebytes=1073741824 dh-group=modp4096 enc-algorithm=aes-256,aes-128 hash-algorithm=sha512
proposal add name="secure-proposal" auth-algorithms=sha512 enc-algorithms=aes-256-cbc pfs-group=modp4096
policy add comment="vpn01" dst-address=10.10.20.0/24 src-address=10.10.10.0/24 tunnel=yes proposal=secure-proposal sa-dst-address=127.99.99.99 sa-src-address=0.0.0.0
MikroTik router 2
/ip ipsec
peer add comment="vpn01" address=127.99.99.99/32 local-address=0.0.0.0 nat-traversal=yes auth-method=pre-shared-key secret=REPLACE_THIS_WITH_RANDOM_SECRET lifebytes=1073741824 dh-group=modp4096 enc-algorithm=aes-256,aes-128 hash-algorithm=sha512
proposal add name="secure-proposal" auth-algorithms=sha512 enc-algorithms=aes-256-cbc pfs-group=modp4096
policy add comment="vpn01" dst-address=10.10.10.0/24 src-address=10.10.20.0/24 tunnel=yes proposal=secure-proposal sa-dst-address=127.99.99.99 sa-src-address=0.0.0.0

Firewall

Source NAT on traffic going from local to remote private network must be avoided by placing the accept rule as first in nat table. This is necessary for example if you have masquerading done by MikroTik router. Also the same thing applies for a destination NAT in case some dstnat rules are present on MikroTik router. In addition, IPSec IKE traffic needs to be allowed by firewall.

MikroTik router 1
/ip firewall
nat add comment="vpn01" action=accept chain=srcnat dst-address=10.10.20.0/24 src-address=10.10.10.0/24 place-before=0
nat add comment="vpn01" action=accept chain=dstnat dst-address=10.10.10.0/24 src-address=10.10.20.0/24 place-before=0
filter add comment="ipsec-ike-natt" chain=input dst-port=500,4500 in-interface=ether1-gateway protocol=udp
filter add comment="vpn01" chain=forward dst-address=10.10.10.0/24 in-interface=ether1-gateway ipsec-policy=in,ipsec src-address=10.10.20.0/24
MikroTik router 2
/ip firewall
nat add comment="vpn01" action=accept chain=srcnat dst-address=10.10.10.0/24 src-address=10.10.20.0/24 place-before=0
nat add comment="vpn01" action=accept chain=dstnat dst-address=10.10.20.0/24 src-address=10.10.10.0/24 place-before=0
filter add comment="ipsec-ike-natt" chain=input dst-port=500,4500 in-interface=ether1-gateway protocol=udp
filter add comment="vpn01" chain=forward dst-address=10.10.20.0/24 in-interface=ether1-gateway ipsec-policy=in,ipsec src-address=10.10.10.0/24

Public IP Change Adaptation

IP Cloud

IP Cloud is used as a dynamic DNS system for lookup of remote site’s public IP. This step can be skipped if different DDNS system is used. Time update via IP Cloud is disabled for a case when NTP is used, however you can enable it if necessary.

MikroTik router 1 and MikroTik router 2
/ip cloud set ddns-enabled=yes update-time=no

Afterwards, you can use following command to get dns-name value of a local router, which will be used in configuration of script on remote router:

/ip cloud print

IPSec Remote Address Update Script

Following script updates IPSec peer address and policy SA destination address, if remote peer’s address has changed. Make sure to fill out correct peerid and peerhost variables:

  • peerid: Identifies IPSec peer and policy records, which will get updated, by comment field value. In this example it is “vpn01”.
  • peerhost: Remote router’s value of dns-name from IP Cloud setup. If different DDNS solution than MikroTik IP Cloud is used for remote site, enter remote DDNS hostname here. In this example it is “0123456789.sn.mynetname.net”. Be aware that peerhost is different for each router.
MikroTik router 1 and MikroTik router 2
/system script add name="ipsec-peer-update-vpn01" policy=read,write source=":local peerid    \"vpn01\"\
    \n:local peerhost  \"0123456789.sn.mynetname.net\"\
    \n:local peerip    [:resolve \$peerhost]\
    \n:local peeruid\
    \n:set peeruid     [/ip ipsec peer   find comment=\"\$peerid\" and address!=\"\$peerip/32\"]\
    \n:local policyuid\
    \n:set policyuid   [/ip ipsec policy find comment=\"\$peerid\" and sa-dst-address!=\"\$peerip\"]\
    \n:if (\$peeruid != \"\") do={\
    \n  /ip ipsec peer set \$peeruid address=\"\$peerip/32\"\
    \n  :log info \"Script ipsec-peer-update updated peer '\$peerid' with address '\$peerip'\"\
    \n}\
    \n:if (\$policyuid != \"\") do={\
    \n  /ip ipsec policy set \$policyuid sa-dst-address=\"\$peerip\"\
    \n  :log info \"Script ipsec-peer-update updated policy '\$peerid' with address '\$peerip'\"\
    \n}"

Schedulers

These schedulers periodically execute following commands:

  • ipsec-peer-update: Starts script, which updates IPSec addresses with remote DDNS IP
  • ip-cloud-forceupdate: Executes forced updated of IP Cloud DDNS IP. Forced IP Cloud update is used, because MikroTik router behind NAT not always checks public IP in required intervals. Therefore by scheduler and force update, this interval is enforced.

Configured intervals should reflect how promptly routers will detect and process public IP change, but also they should avoid any excessive usage. In case of often VPN connection break downs, because of public IP changes, it should be considered to use static public IPs instead and thus avoid IP changes altogether.

MikroTik router 1 and MikroTik router 2
/system scheduler
add disabled=yes interval=1m name=ipsec-peer-update-vpn01 on-event="/system script run ipsec-peer-update-vpn01" policy=read,write
add disabled=yes interval=10m name=ip-cloud-forceupdate on-event="/ip cloud force-update" policy=read,write

Netwatch and Route

Netwatch checks availability of remote MikroTik router’s LAN IP address. In case remote router is unavailable, Netwatch enables schedulers for update of IPSec remote address and IP Cloud DDNS IP. When remote router is available again, schedulers are disabled again. Netwatch is not able to identify correct interface for remote router’s LAN IP, therefore route needs to be added as well. Make sure that gateway is set to your local router’s LAN interface or bridge.

MikroTik router 1
/ip route add comment="vpn01" distance=1 dst-address=10.10.20.0/24 gateway=bridge-local
/tool netwatch add comment=ipsec-peer-update-vpn01 down-script="/system scheduler enable ipsec-peer-update-vpn01\
    \n/system scheduler enable ip-cloud-forceupdate" host=10.10.20.1 up-script="/system scheduler disable ip-cloud-forceupdate\
    \n/system scheduler disable ipsec-peer-update-vpn01"
MikroTik router 2
/ip route add comment="vpn01" distance=1 dst-address=10.10.10.0/24 gateway=bridge-local
/tool netwatch add comment=ipsec-peer-update-vpn01 down-script="/system scheduler enable ipsec-peer-update-vpn01\
    \n/system scheduler enable ip-cloud-forceupdate" host=10.10.10.1 up-script="/system scheduler disable ip-cloud-forceupdate\
    \n/system scheduler disable ipsec-peer-update-vpn01"

Result

Netwatch on both Mikrotik routers should detect unavailability of remote router and trigger down-script, enabling IPSec update script and IP Cloud force update. If public IP did not change since IP Cloud has been set up, IPSec update script should have immediately correct public IP of remote site, otherwise it will wait for IP Cloud forced update. IPSec update script then updates IPSec peer address and IPSec policy SA destination address with resolved public IP address of remote IP Cloud hostname. As soon as IPs on both sides are updated with the current public IPs, routers will start to initialize IPSec communication with each other, negotiating encryption and establishing the VPN tunnel. When the tunnel is up, Netwatch will detect presence of remote router via VPN tunnel and disable schedulers, until next public IP change will break the tunnel and trigger the Netwatch again. While tunnel is up, hosts in both private networks can communicate with each other.


22 Comments

dabar · September 18, 2016 at 20:31

thank you for sharing!!

george · October 14, 2016 at 07:14

I would appreciate a variation of this setup where only one of the routers uses dynamic IP while the other has known static IP (a “central office”).

    Pessoft · November 4, 2016 at 00:16

    Setup mentioned in the article should work also in the case when one of the routers is connected using the static IP. In such scenario, for the router connected via static IP you don’t need IP Cloud (dynamic DNS) and ip-cloud-forceupdate scheduler and for the router connected via dynamic IP you don’t need ipsec-peer-update scheduler and temporary placeholder IP set in ipsec section ( 127.99.99.99/32 ) can be configured directly ( with the known static IP ).

Joao · November 19, 2016 at 22:56

Hi,

i am stuck on phase1 with IPSEC error: phase1 negotiation failed due to time up……

both of routers are behind nat with ports (udp500, udp4500) opened and static ip addresses.

Pessoft, please contact me by email, i need to get this working.

Thanks

chris · January 21, 2017 at 04:49

The best mikrotik site-site ipsec guide I have seen out there.
I have followed all the step and the connection is up but I can not ping the remote site. Can you help please?

    Pessoft · January 24, 2017 at 00:24

    Thanks.
    At first try to check IPSec. On both sides you should see in remote-peers established connection ( /ip ipsec remote-peers print ) and pair of mature installed SAs ( /ip ipsec installed-sa print ). Then try to ping remote Mikrotik’s internal IP and also IP of some device in remote network. If both, peers and SAs, are correct and ping still does not work via IPSec tunnel, but does locally, then it can be a routing issue. Also, I had issues with the IPSec NAT-T tunnel running on Mikrotik RouterOS 6.38 and had to upgrade to 6.38.1.

kk · January 23, 2017 at 07:58

thanks, the script works well.

Kevin · February 28, 2017 at 10:32

Hello,
Firstly, thanks for your doc, I have followed all the step and can get remote site public ip via IP Cloud each other but the ipsec phase I is still fail. can you help please ?
Secondary, I have one question for this solution. if I setup another Mikrotik box in one of the site and paste same config besides the ether1-gateway IP, the ipsec tunnel will be establish with which one?

    Pessoft · February 28, 2017 at 23:50

    Hello,
    Mikrotiks on both sites need to have IPSec traffic forwarded from their gateway routers ( in example above are these gateways called ISP routers ), so at first I suggest to check that there is 500/UDP and 4500/UDP forwarding configured on these gateways. Also check in which state are remote peers on Mikrotiks ( terminal command /ip ipsec remote-peers print ).
    Regarding your second question: IPSec tunnel in config is configured to connect to remote site in case there is traffic going from local private network to remote private network ( in example above: if traffic will go from host in 10.10.10.0/24 network to network host in 10.10.20.0/24 network, then tunnel will be established from Mikrotik router 1 to Mikrotik router 2 and traffic sent through this tunnel – this works also vice versa ). So if you will have additional Mikrotik box in one of the sites with the same config as the other Mikrotik on the same site, it should work let’s say as its backup ( i.e. if there will be traffic going through additional box from local to remote private network, tunnel will be established to remote site ).

DQ · February 28, 2017 at 10:34

Thanks Pressoft! I was not luck, your post was not working well on my side. I have almost same environment as shown in your topology. After I configured bother MT routers the IPSec tunnel was not up. in the logging file I could find that the phase one packet was sent out in both sides the routers could not receive response packets. What could be the potential reason?

I also have some questions which confused to me. Hope to get your answers.
1. What is the purpose of IP 127.99.99.99/32? is it a real IP or just an sample IP?
2. Is the IP an IP of a public stun server?
3. By using script and DDNS the MT router can know the public IP of peer, but how does the up lever NAT router know the received IPSec negotiation packets need to be forwarded to its direct connected MT router if there is no NAT translation table established before? vice verse.

Thanks a lot!

    Pessoft · March 1, 2017 at 00:16

    Hi DQ,
    At first make sure that 500/UDP and 4500/UDP traffic is being forwarded from gateways of your MTs to MT routers.
    1. 127.99.99.99/32 is just a temporary placeholder IP, it will get replaced by IP of remote peer by the script
    2. There is no STUN server used in the configuration, each MT knows about the IP of remote peer from the DDNS name of remote host.
    3. There actually needs to be forwarding configured before ( in the article it is in the top – situation description point 4: Each MikroTik router has IPSec protocol, NAT-Traversal (4500/UDP) and IPSec IKE (500/UDP) traffic forwarded from its gateway (ISP Router) ). This is usually done on routers using configuration called port forwarding or DMZ host.

Anton · May 27, 2017 at 22:49

This was the most useful guilde I have ever encountered! Works like a charm and it updates FAST!

    Anton · May 27, 2017 at 22:49

    guide*

Eduardo · July 25, 2017 at 15:36

Hello!.
I just connect two nets using this tutorial without problems. This is a great guide.
Thanks a lot!.

Stephane · October 17, 2017 at 12:37

Thanks a lot.

Great job, great sharing .. please do share for us beginner Mikrotik admin, some of your useful tips.

Dablah · November 13, 2017 at 23:57

Solo puedo decir, muchas gracias!

hardoverflow · December 1, 2017 at 06:31

Thanks for your great guide! One question about routing. On every site i have a few vlans configured. Is it possible to route them over the ipsec tunnel ?

    Pessoft · December 8, 2017 at 22:36

    Hi and thank you. Regarding VLAN routing, I didn’t test such configuration, but generally VLANs are working on OSI layer 2 and are terminated on routers when IP routing occurs. So VLANs on 2 sites are usually different logical networks. It might be worth a try to create a tunnel interface (GRE) on top of the IPSec and bridge the VLANs with tunnel. But as mentioned, I didn’t test such setup on Mikrotik platform, so it’s just a guess 😉 Another possibility (as an example) is to make sure that network in the VLAN 100 on the site A is configured correctly in terms of routing and firewall rules, that it can communicate with network in the VLAN 100 on the site B – and vise versa.

zack12821 · December 4, 2017 at 11:45

Thanks Pressoft! I but not luck, your post was not working well on my side. I have same environment as shown in your topology is about one week that i trying to make it work but way , os 6.40.5

not packet send on ipfirewall, ipsec nagociat fail due to time up

    Pessoft · December 8, 2017 at 23:13

    Hi! I tested the setup also on the 6.40.5 and it works well. Your description points out that IPSec communication is not flowing between the two routers. Here are the hints to check:
    – verify that routers between Mikrotiks and Internet forward port 4500/UDP to Mikrotik device
    – verify that firewall on Mikrotik accepts 4500/UDP
    – if router on one site is more susceptible to block communication or difficult to configure, set on the opposing site Mikrotik’s IPSec peer configuration to be “passive” and also disable there “Send Initial Contact”
    – try to change the IPSec peer exchange mode on both sites to IKEv2

felixput · December 12, 2017 at 14:41

Hi Pessoft,

Thanks a lot for your guide, it’s really helpful. I got the IPsec connection established and I can reach both routers from both sides.
Unfortunately, I couldn’t ping any devices that other than the router from another side. When I check the connection, there is a ping request however it never got replied.

Can you help me on this one? Thanks

    Pessoft · December 15, 2017 at 00:22

    Hi Felix,

    Try to test between hosts on both sides. Using the Torch tool you should see incoming icmp packets on gateway interface. This should help you identify on which side is the issue or whether it is general. Also make sure that you have NAT firewall rules set and in the order prior to your masquerading or other src/dst nat rules, which could influence routing of the packets.

Leave a Reply

Your email address will not be published. Required fields are marked *