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 successfully tested the setup on 2x Mikrotik hAP lite classic devices, each running behind different routers ( in one case Draytek Vigor 2700 and Ubee EVW3226, in another case TP-Link TD-W8951NB and Compal CH7465LG )
  • 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. But GCM is more secure than CBC, so I recommend to upgrade the RouterOS to the latest version and try with GCM at first.

Update 2:

  • RouterOS 6.38 (2016-Dec-30) added IKEv2 support as key exchange mode for IPSec. This mode can be used to improve the security of the tunnel establishment, so I’ve updated the examples in this article accordingly. IKEv2 is also more recent and updated version of the key exchange mode than previously available modes. Except the security improvements, it has embedded the “dead peer detection” and “NAT traversal”, which makes the configuration easier. Additionally, IKEv2 NAT traversal ensures that if connection cannot be created directly between two peers, port 4500/UDP is used. Therefore in RouterOS firewall you need to allow only 4500/UDP.
  • RouterOS 6.41 (2017-Dec-22) introduced possibility to use DNS name as IPSec peer address instead IP address. If you will use DNS names in /ip ipsec peer configurations, you can skip the respective part in ipsec-peer-update script mentioned later in this guide, but it is still required to update the IP address of sa-dst-address in IPSec policy, in case the remote router’s public IP has changed. Examples here do not use DNS names in IPSec peer addresses.

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 auth-method=pre-shared-key secret=REPLACE_THIS_WITH_RANDOM_SECRET dh-group=modp4096 enc-algorithm=aes-256,aes-128 exchange-mode=ike2 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 auth-method=pre-shared-key secret=REPLACE_THIS_WITH_RANDOM_SECRET dh-group=modp4096 enc-algorithm=aes-256,aes-128 exchange-mode=ike2 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. For IKEv2 this traffic is 4500/UDP, but for other IKE modes, this could also include 500/UDP.

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=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=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.


32 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.

Mathew · June 19, 2018 at 23:42

Hi Pessoft,

Thanks for the guide. I didnt find anything with this type of topology in mind. I tried to do everything here but cant establish IPsec IKEv2 connection between routers (ping). I dont have dynamic public ips so i used static public IP for SA and peers on both sides. Unfortunately at Remote Peers i have local address ether1-gateway address and remote address correct static public address and also no installed SAs. Can you please help me? This is same on both Mikrotik routers. Thanks in advance

    Pessoft · June 20, 2018 at 00:05

    Hi Mathew,
    Based on your input, it seems that addresses in Remote Peers are looking good. Check in which state your remote peer is using /ip ipsec remote-peers print value-list. If it is established, then peer connection is fine. Otherwise have a look at logs what they say and also verify network between Mikrotiks: Are both local and remote ports in remote peer view using 4500/UDP? Are ISP routers forwarding 4500/UDP traffic to Mikrotik routers? Can you see packet counts increasing in Mikrotik firewall rules allowing 4500/UDP? Are there visible attempts to establish SA? This could give some information about what can be blocking the connection.

      Mathew · June 20, 2018 at 17:58

      i have 4500 and it is increasing count and also peer connection is established. Log shows after 2 SA messages no policy found/generated

        Pessoft · June 20, 2018 at 22:01

        It seems that peer connection works well, so the next step should be Policy review using /ip ipsec policy print. Is private network behind Mikrotik set as source address and remote network behind Mikrotik as destination address? Is SA destination address set to remote public IP? This applies also vice-verse on the other Mikrotik. Can you see in the logs what policy is missing and verify the policy configuration accordingly? It might be also beneficial to check whether Mikrotik Router OS version is up-to-date on both sides.

Mathew · June 20, 2018 at 23:46

Everything working. Thanks

Charles · August 7, 2018 at 01:35

Great guide. Thanks.

Everything is working once the tunnel is created except that, whilst I can ping addresses apart from each router, I can’t ping one router from the other and vice versa.

Any ideas why that might be?

    Pessoft · August 9, 2018 at 21:16

    Hi,
    At first I suggest to check firewall configuration, whether it allows ICMP ping from ( and to ) the other router. Next thing is routing: in the section “Netwatch and Route” of this article is a route created, which makes the routers reachable between each other. Also Torch tool could help identify whether ICMP pings leave router via a correct interface.

Lucky · October 26, 2018 at 18:11

Hi,
Can you explain exactly what part of the update script can be ommited if DNS names are used in peer configurations ?

    Pessoft · October 30, 2018 at 08:48

    Hi,
    ipsec-peer-update script updates 2 values: IP address of remote peer and SA destination address. If DNS names are used in remote peer configuration, parts of script related to update of remote peer can be omitted. So the command to create the script might look like this:

    /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 policyuid\
        \n:set policyuid   [/ip ipsec policy find comment=\"\$peerid\" and sa-dst-address!=\"\$peerip\"]\
        \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}"
    

Miguel · November 9, 2018 at 05:50

Thank you!!!! it’s a great guide. Everything working!

Leave a Reply

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