【老李瞎折腾】001、折腾一下DDNS

去年就申请了电信的公网IP,现在终于可以用起来了,当时是通过电信的官方公众号申请的,直接就给开通了,也没有人上门核对,但是现在申请好像要上门核对了~

端口映射

想要把树莓派的上的服务开放到公网,首先要做的就是端口映射,把本地服务的端口映射到公网,方法很简单,登录电信网关后台,找到高级设置 > 端口映射

【老李瞎折腾】001、折腾一下DDNS

如上所示,我的源码托管平台就可以通过电信分配公网IP访问了~

DDNS

虽然是公网IP,但不是静态的,每隔一段时间或者重启网关后都会更改,每次更改了都要去查一下新的IP,关键是不在家还查询不了,所以为了更好的稳定的连接家里的服务器,我们需要使用DDNS技术。

所谓DDNS,就是动态域名解析,流程上就是定时查询公网IP,如果发现变更了,则调用域名所在服务商的域名解析API,来更新域名的解析IP。

下面是我用C#做的,使用阿里云做的DDNS代码示例,该示例是使用开源.Net模块化快速开发框架 NetModular 中的任务调度模块开发的,仅供参考:

using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Aliyun.Acs.Alidns.Model.V20150109;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using NetModular.Lib.Config.Abstractions;
using NetModular.Lib.Quartz.Abstractions;
using NetModular.Module.MyJob.Infrastructure;
using Newtonsoft.Json;

namespace NetModular.Module.MyJob.Quartz
{
    [Description("DDNS任务")]
    public class DdnsTask : TaskAbstract
    {
        private readonly IConfigProvider _configProvider;

        public DdnsTask(ITaskLogger logger, IConfigProvider configProvider) : base(logger)
        {
            _configProvider = configProvider;
        }

        public override async Task Execute(ITaskExecutionContext context)
        {
            var config = _configProvider.Get<MyJobConfig>().Ddns;

            var profile = DefaultProfile.GetProfile(config.RegionId, config.AccessKeyId, config.Secret);
            var client = new DefaultAcsClient(profile);
            var request = new DescribeDomainRecordsRequest
            {
                DomainName = config.Domain,
                PageNumber = 1,
                PageSize = 50,
                AcceptFormat = Aliyun.Acs.Core.Http.FormatType.JSON
            };
            try
            {
                var response = client.GetAcsResponse(request);
                var json = System.Text.Encoding.Default.GetString(response.HttpResponse.Content);
                var model = JsonConvert.DeserializeAnonymousType(json, new
                {
                    DomainRecords = new
                    {
                        Record = new[] { new { RecordId = "", RR = "", Value = "" } }
                    }
                });

                var record = model.DomainRecords.Record.FirstOrDefault(m => m.RR.EqualsIgnoreCase(config.RR));
                if (record != null)
                {
                    await Update(profile, client, record.RecordId, record.Value, config);
                }
                else
                {
                    await Add(profile, client, config);
                }
            }
            catch
            {
                //
            }
        }

        /// <summary>
        /// 获取公网IP
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetIP()
        {
            string url = "https://202020.ip138.com/";
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("User-Agent", "abcdefg");
            var html = await client.GetStringAsync(url);
            return Regex.Match(html, "<title>[^:]+:([^<]+)</title>").Groups[1].Value;
        }

        /// <summary>
        /// 添加
        /// </summary>
        private async Task Add(IClientProfile profile, IAcsClient client, DdnsConfig config)
        {
            var ip = await GetIP();
            var request = new AddDomainRecordRequest
            {
                DomainName = config.Domain,
                RR = config.RR,
                Type = "A",
                Value = await GetIP()
            };

            var response = client.GetAcsResponse(request);
            await Logger.Info($"新增解析记录:{response.RecordId},IP:{request.Value}");
        }

        //修改
        private async Task Update(IClientProfile profile, IAcsClient client, string recordId, string value, DdnsConfig config)
        {
            var ip = await GetIP();
            if (ip == value)
                return;

            var request = new UpdateDomainRecordRequest
            {
                RecordId = recordId,
                RR = config.RR,
                Type = "A",
                Value = await GetIP()
            };

            var response = client.GetAcsResponse(request);

            await Logger.Info($"修改解析记录:{response.RecordId},IP:{request.Value}");
        }
    }
}

这样就可以安心连接自己的树莓派了,比如老李的代码世界

上一篇:通过阿里云实现动态域名解析DDNS


下一篇:kaliDHCP配置失败解决(纯兴趣)