Tutorial IPv6 DDNS (noip.com) and VPN server for CG-NAT IPv4

  • ATTENTION! As of November 1, 2020, you are not able to reply to threads 6 months after the thread is opened if there are more than 500 posts in the thread.
    Threads will not be locked, so posts may still be edited by their authors.
    Just start a new thread on the topic to post if you get an error message when trying to reply to a thread.


Occasional Visitor

First a bit of background for this tutorial: I have a AsusWRT-Merlin router and want to use OpenVPN to create a site-to-site VPN network to another AsusWRT-Merlin router in another city. I used the WebUI to create a OpenVPN server on my end and a OpenVPN client on the remote one, and since the ISP asssing IPs dynamically I setup DDNS on both. I've done this by using a remote desktop software (teamviewer) to access a pc connected to the remote router.
After the initial successful setup, because I wanted to further tinker with the settings for the site-to-site and not wanting to use the remote desktop software, I decided to enable a OpenVPN server on the remote router and connect to it while doing changes to the OpenVPN client. This worked wonderfully and I made some changes which made the site-to-site unusable so another way to access the router was definitely a good idea.
After some time however, both our ISP accounts were assigned to carrier-grade NAT pool so the VPN server could no longer be accessed using the IPv4. I asked the ISP for an internet routable IPv4 address for me, but I had no reason to do the same for the other account account so I let it that way. This is still the situation to this day.

One time I started to think about using IPv6 to once again make the remote VPN server accessible so I started to look into if this thing is possible and how to do it if it is. First thing is if the ISP offers IPv6 services; the second is if OpenVPN supports IPv6; the third is if DDNS supports IPv6; last but not least how to make it all work in AsusWRT-Merlin firmware. The ISP offers it, OpenVPN supports it, the ddns service I use (noip.com) supports it and AsusWRT-Merlin does as well, but not by default using the WebUI, but by using scripts to manage all the necessary steps.

I used many resources, like AsusWRT-Merlin's Wiki on github and of course searches on the internet, since I'm not a very proficient script writer and there may very well be major bugs in them (since minor ones are almost a certainty), but from the testing I've done it works, so I decided to share with others by writing this post.

Lastly before I begin, this tutorial assumes one has at least a medium understanding of using the router, such as setting up DDNS and OpenVPN from the WebGUI, enabling scripts, setting up SSH (or at least telnet) and connecting to it, creating and editing files from the terminal.
Making the VPN Server use IPv6 instead of IPv4 is actually pretty easy, one just havs to specify it in the proto statement as indicated by the manual (For forcing IPv4 or IPv6 connection suffix tcp or udp with 4/6 like udp4/udp6/tcp4/tcp6.), however there isn't a way to make the change in the WebUI, so the openvpn-event script has to handle this.
After some trials I found that I need to open the port set for the VPN Server in the firewall. This script adds this rule in the firewall before the last line (which is to drop all packets) when the server is started (i.e. script type is up) and deletes every instance if there are more of them in all other scenarios.

- I use UDP as the protocol, change PROTO variable to tcp at the beginning of the script if one wants to use this protocol;
- I use OpenVPN Server 1, change VPN_SERVER variable to 2 at the beginning of the script if one wants to use this server.

Of course, all clients that want to connect to this server must use IPv6 as well, so in their configuration file one must use the same proto as in the server (either tcp6 or udp6).
The DDNS script is more complex since the only information one needs to set in the WebUI is the Server set to Custom and the Host Name, with everything else handled by the script.
Since I use noip.com the script is only valid for this ddns service provider because I use their rules for sending the request and interpreting the response. Based on these I decided to use two new nvram variables, ddns_last_update_code and ddns_last_update_time for deciding if the request should be sent or not on this execution of the script. So make sure the router has a bit of nvram space available; check in WebUI -> Tools page-> Sysinfo tab-> Internal Storage section -> NVRAM usage entry.

First, the script checks if the time is synchronized (using nvram variable ntp_ready), and if not, by default waits 50 seconds for it to synchronize (10 retries of 5 seconds each). One can change these by modifying the variables TRIES and SLEEP in the beginning of the wait_for_ntp_sync procedure.
Second it checks the last update code, last update time and current time and based on these and the previously mentioned rules for sending the request and interpreting the respone, the script decides whether to move on or exit.
Then it gets the host name, WAN interface, IPv4 address and IPv6 address of said interface and selects which IP, if any, to update. Only internet routable, private network use (RFC 1918) and carrier-grade NAT (RFC 6598) IPv4 addresses are used by default.
Now it creates the URL to be used for requesting the update, after which send the URL together with the user agent and trusted certificate store to be used and finally checks the answer and updates the two nvram variables with the relevant information for next time execution of the script.

- one has to add one's username and password for the noip account at the beginning of the script. These should have the special characters used by the shell escaped: ` ' $ \ and " should be preceded by \ and % should be preceded by % (e.g. if the password is `'$\"% then one should write PASSWORD="\`\'\$\\\"%%");
- one has to add a user agent acording to noip's rules for sending the request User-Agent: Company NameOfProgram/OSVersion-ReleaseVersion [email protected];
- one can change the LOG_TAG variable to something one prefer to be passed to the logger program.

If one hasn't done so already, one has to change the hostname to a AAAA (IPv6) record type instead of a DNS Host (A) one on the noip.com website.
I cannot attach extensionless files on the forum, so .txt it is. One should rename the files if one intends to transfer them to the router, they should be ddns-start and openvpn-event, and they should be created in the /jffs/scripts folder.
Also, remember to allow the newly created files to be executed by executing chmod a+rx /jffs/scripts/* command at the terminal.

I also have some unknowns, such as which logger level is which? I assumed 0 to be emergency, 1 to be alert ... 7 to be debug.
Another one is: would it be better to use curl instead of wget to send the request?
Also, are the username and password encrypted by https when sending the request? I assume yes, but don't know how to check to be sure. I don't see how wireshark could capture packets generated by the router from my pc.

Constructive criticism is appreciated; obvious problems and solutions to them are more than welcome.


  • openvpn-event.txt
    884 bytes · Views: 28
  • ddns-start.txt
    12.8 KB · Views: 17

Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!