Source: This solution is based on the following post : http://wiki.mikrotik.com/wiki/Dynamic_DNS_Update_Script_for_DNSoMatic.com_behind_NAT
Overview:
In case you need to implement a Site-to-Site VPN link between two sites that are connected to the Internet only via dynamic IP address, you need to resolve two issues for each site:
- monitor the other peer public IP address so you can catch that it has changed
- monitor your own public IP address so you can reset the encrypted keys and re-establish the tunnel
Design:
Details:
The two issues are resolved by using two scripts that run every minute on each RouterOS.
- first script checks the other peer public IP address with a DNS name resolution and it compares the result with the old IP address. If it has changed, than it modifies the RouterOS configuration by changing the ipsec peer IP address.
- second script checks the site public IP address by using an http request to checkip.dyndns.org and compares the result with the old IP address. If it has changed, than it resets the ipsec connections in order to re-establish the vpn tunnel.
IP Configuration:
Router1
/ip address
add address=10.0.3.1/24 comment=interco disabled=no interface=ether1 network=10.0.3.0
add address=192.168.1.1/24 comment=HQ disabled=no interface=ether2 network=192.168.1.0
Router2
/ip address
add address=10.0.4.1/24 comment=interco disabled=no interface=ether1 network=10.0.4.0
add address=192.168.2.1/24 comment=Factory disabled=no interface=ether2 network=192.168.2.0
IPSec Configuration:
Router 1:
/ip ipsec peer
add address=10.0.2.1/32 auth-method=pre-shared-key dh-group=modp1024 disabled=no \
dpd-interval=disable-dpd dpd-maximum-failures=5 enc-algorithm=3des exchange-mode=main \
generate-policy=no hash-algorithm=md5 lifebytes=0 lifetime=1d my-id-user-fqdn="" \
nat-traversal=yes port=500 proposal-check=obey secret=mysecret send-initial-contact=yes
/ip ipsec policy
add action=encrypt disabled=no dst-address=192.168.2.0/24 dst-port=any ipsec-protocols=esp \
level=require priority=0 proposal=default protocol=all sa-dst-address=10.0.2.1 \
sa-src-address=10.0.3.1 src-address=192.168.1.0/24 src-port=any tunnel=yes
Router2:
/ip ipsec peer
add address=10.0.1.1/32 auth-method=pre-shared-key dh-group=modp1024 disabled=no \
dpd-interval=2m dpd-maximum-failures=5 enc-algorithm=3des exchange-mode=main \
generate-policy=no hash-algorithm=md5 lifebytes=0 lifetime=1d my-id-user-fqdn="" \
nat-traversal=yes port=500 proposal-check=obey secret=mysecret send-initial-contact=yes
/ip ipsec policy
add action=encrypt disabled=no dst-address=192.168.1.0/24 dst-port=any ipsec-protocols=esp \
level=require priority=0 proposal=default protocol=all sa-dst-address=10.0.1.1 \
sa-src-address=10.0.4.1 src-address=192.168.2.0/24 src-port=any tunnel=yes
Script Configuration:
Router1:
The following script checks if the Factory public IP address has changed, and if so, modifies the configuration in order to re-establish the vpn tunnel.
/system script
add name=checkmypeer-router-update policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive source="\
\n:global currentpeerip [:resolve router2.alsacecom.fr]\r\
\n:global previouspeerip\r\
\n:if (\$currentpeerip != \$previouspeerip) do={\r\
\n:log info \"CHECKPEERIP: Update required \$currentpeerip\"\r\
\n:set previouspeerip \$currentpeerip\r\
\n/ip ipsec policy set 0 sa-dst-address=\$currentpeerip sa-src-address=10.0.3.1\r\
\n/ip ipsec peer set 0 address=\"\$currentpeerip/32\" port=500\r\
\n/ip ipsec remote-peers kill-connections\r\
\n}"
The following script checks if the HQ public IP address has changed, and if so, resets the ipsec keys in order to re-establish the vpn tunnel.
/system script
add name=checkmyip-router-update policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive source="\
\n:global previousmyip\r\
\n# Print values for debug\r\
\n# get the current IP address from the internet (in case of double-nat)\r\
\n/tool fetch mode=http address=\"checkip.dyndns.org\" src-path=\"/\" url=\"http://checkip.dyndns.org/dyndns.checkip.html\"\r\
\n:local result [/file get dyndns.checkip.html contents]\r\
\n# parse the current IP result\r\
\n:local resultLen [:len \$result]\r\
\n:local startLoc [:find \$result \": \" -1]\r\
\n:set startLoc (\$startLoc + 2)\r\
\n:local endLoc [:find \$result \"</body>\" -1]\r\
\n:global currentmyip [:pick \$result \$startLoc \$endLoc]\r\
\n:if (\$currentmyip != \$previousmyip) do={\r\
\n:set previousmyip \$currentmyip\r\
\n:log info \"CHECKMYIP: Update required \$currentmyip\"\r\
\n/ip ipsec remote-peers kill-connections\r\
\n}"
Each script then runs every minute:
/system scheduler
add comment="" disabled=no interval=1m name=checkmypeer-schedule on-event=\
"checkmypeer-router-update" policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive \
start-date=jan/01/1970 start-time=00:00:01
/system scheduler
add comment="" disabled=no interval=1m name=checkmyip-schedule on-event=checkmyip-router-update \
start-date=jan/01/1970 start-time=00:00:01
Router2:
The following script checks if the HQ public IP address has changed, and if so, modifies the configuration in order to re-establish the vpn tunnel.
/system script
add name=checkmypeer-router-update policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive source="\
\n:global currentpeerip [:resolve router1.alsacecom.fr]\r\
\n:global previouspeerip\r\
\n:if (\$currentpeerip != \$previouspeerip) do={\r\
\n:log info \"CHECKPEERIP: Update required \$currentpeerip\"\r\
\n:set previouspeerip \$currentpeerip\r\
\n/ip ipsec policy set 0 sa-dst-address=\$currentpeerip sa-src-address=10.0.4.1\r\
\n/ip ipsec peer set 0 address=\"\$currentpeerip/32\" port=500\r\
\n/ip ipsec remote-peers kill-connections\r\
\n}"
The following script checks if the Factory public IP address has changed, and if so, resets the ipsec keys in order to re-establish the vpn tunnel.
/system script
add name=checkmyip-router-update policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive source="\
\n:global previousmyip\r\
\n# Print values for debug\r\
\n# get the current IP address from the internet (in case of double-nat)\r\
\n/tool fetch mode=http address=\"checkip.dyndns.org\" src-path=\"/\" url=\"http://checkip.dyndns.org/dyndns.checkip.html\"\r\
\n:local result [/file get dyndns.checkip.html contents]\r\
\n# parse the current IP result\r\
\n:local resultLen [:len \$result]\r\
\n:local startLoc [:find \$result \": \" -1]\r\
\n:set startLoc (\$startLoc + 2)\r\
\n:local endLoc [:find \$result \"</body>\" -1]\r\
\n:global currentmyip [:pick \$result \$startLoc \$endLoc]\r\
\n:if (\$currentmyip != \$previousmyip) do={\r\
\n:set previousmyip \$currentmyip\r\
\n:log info \"CHECKMYIP: Update required \$currentmyip\"\r\
\n/ip ipsec remote-peers kill-connections\r\
\n}"
Each script then runs every minute:
/system scheduler
add comment="" disabled=no interval=1m name=checkmypeer-schedule on-event=\
"checkmypeer-router-update" policy=\
ftp,reboot,read,write,policy,test,winbox,password,sniff,sensitive \
start-date=jan/01/1970 start-time=00:00:01
/system scheduler
add comment="" disabled=no interval=1m name=checkmyip-schedule on-event=checkmyip-router-update \
start-date=jan/01/1970 start-time=00:00:01
/ip ipsec peer
add address=10.0.1.1/32 auth-method=pre-shared-key dh-group=modp1024 disabled=no dpd-interval=2m \
dpd-maximum-failures=5 enc-algorithm=3des exchange-mode=main generate-policy=no hash-algorithm=md5 \
lifebytes=0 lifetime=1d my-id-user-fqdn="" nat-traversal=yes port=500 proposal-check=obey secret=test \
send-initial-contact=yes