很多摄影爱好者/IT从业者都会购买NAS产品或着拥有性能强悍的工作站及服务器,比如笔者家里就购买了NAS存储,同时家里也有一台工作站,出门在外可以随时将手机拍摄的图片传到家里的NAS上或者通过笔记本远程连接到家里的服务器上进行某些特定的操作。 但是鉴于现在的家用网络状况,家用PPPOE网络会在光猫/路由器重启后,发生IP变更,一旦IP变更,如果我们不知道新的IP,就无法连接到家庭的网络中了,针对这种状况,有一些DDNS服务商提供了动态IP和域名绑定的服务,比如典型的花生壳,公云,还有国外的一些服务。但这些服务大部分都会收取一定的流量或带宽费用,笔者的上行带宽为50Mbps,使用这些服务会导致额外很高昂的费用,因此,笔者决定自行配置一套简易的DDNS。

在之前的内容中,我们曾分享过Azure DNS这款产品( 请参见《Azure DNS-每一个请求,都值得托付》),其实Azure DNS是有对应API的,我们在本例中,使用API的方式动态的修改A记录,即可实现DDNS的效果。

先看下如下示意图:

 

步骤解释:

1. IP检测程序 定时,例如每10分钟调用一次公开的公网IP获取API,一旦两次结果不一样,则表示本地的公网IP发生了变更;

2. IP检测程序通过 调用Azure DNS的 API,修改A记录的IP为 上一步得到的新IP地址;

3. 随时随地在任何地方通过域名的方式访问家庭网络的服务。

 

当然根据实际情况,IP检测程序可以以如下形式存在:

1. 真实的 程序,部署在家庭网络里的虚拟机,服务器里;

2. 主流的NAS都提供了检测外网IP的功能,并且具备调用自定义DDNS API的功能( 笔者的威联通 NAS,就使用了此方式);

3. 主流的国产NAS(群晖,威联通等都支持容器),可以将该程序以容器方式部署在NAS里。

 

在本例中,笔者通过NAS自带的外网IP检测和自定义DDNS功能进行了设置,NAS每10分钟检测一次IP是否发生变更,一旦变更,则调用自定义的API修改A记录,笔者把自定义的API 发布到了Azure的一台VM里,当然,为了省钱,你可以使用Azure Function, 免费层级在这个场景中最适合了。

 

 

当然在这个过程中,有如下前置条件:

1. 你的宽带运营商提供的了公网IP地址(某些小型运营商其实目前已经不提供公网IP了);

2. 你的光猫/路由器有端口转发的功能;

3. 合法使用DDNS;

 

本例中 如何检测公网IP可通过如下API:

http://pv.sohu.com/cityjson

例如笔者的IP地址如下图(该IP会在路由器重启后发生变更):

 端口转发如下图所示(该步骤在你家用路由器中调试):

 

 

接下来,可以在任何时候,任何地点,访问家里的存储/服务器了:

 

 

本例中,修改Azure DNS A记录的代码如下:

 

 #region Update A Record
            // **********************************************************************************************************
            // Update A Record
            // **********************************************************************************************************

            Console.Write("Updating DNS 'A' record set with name '{0}'...", recordSetName);
            try
            {
                var recordSet = dnsClient.RecordSets.Get(resourceGroupName, zoneName, recordSetName, RecordType.A);

                // Add a new record to the local object.  Note that records in a record set must be unique/distinct
                recordSet.ARecords.Add(new ARecord("5.6.7.8"));

                // Update the record set in Azure DNS
                // Note: ETAG check specified, update will be rejected if the record set has changed in the meantime
                recordSet = await dnsClient.RecordSets.CreateOrUpdateAsync(resourceGroupName, zoneName, recordSetName, RecordType.A, recordSet, recordSet.Etag);

                Console.WriteLine("success");
            }
            catch (System.Exception e)
            {
                Console.WriteLine("failed: {0}", e.Message);
            }
            #endregion

 

更多Azure DNS示例代码,请下载官方案例:

https://download.microsoft.com/download/2/A/C/2AC64449-1747-49E9-B875-C71827890126/AzureDNSSample1_2016-09-14.zip