返回 登录
0

通过AWS创建无服务器的动态DNS系统

作者: Sean Greathouse
原文: Building a Serverless Dynamic DNS System with AWS
译者: 孙薇

现代人具有移动与互联属性,人们希望从任何地方都能访问自己的工具。而通过互联网访问网络中的系统,就需要了解网络的公共IP地址。初创公司、小型企业还有家庭网络经常会使用动态的公共IP地址,这些地址在变更时不会另行作出通知。由于地址是变更的,人们无法以可靠地方式从外部访问这些系统。动态DNS系统通过在网络中运行软件代理,保持DNS记录与公共IP地址同步更新,来解决这一问题。只要保证DNS记录是最新的,就能找到相应的网络。

在本文中,我们讲述了如何通过一个小脚本与一些AWS服务来构建自己的动态DNS系统。也有其他系统能提供类似的解决方案,然而只用AWS服务与几行代码来构建无服务器系统确实简单合算;下面是在AWS上如何构建自己的无服务器解决方案的案例。

我们用在动态DNS系统中的AWS服务

在下文中,我们会展示如何使用下面的AWS服务来构建动态DNS微服务:

  • AWS Lambda可用于运行Python、Java或Node.js的代码,而无需管理底层服务器。代码随时可以运行,不过只有每次执行时才会加载,以100毫秒增量。Lambda可以通过AWS SDK管理其他AWS服务。Lambda的功能可以通过Amazon API Gateway或者其他AWS服务所发送的event,按预定计划触发。
  • Amazon API Gateway是一种托管服务,可以为运行在Amazon EC2、Lambda或者其他网络应用之上的后端服务建立公共API前端。
  • Amazon Route 53是一种托管的DNS服务,提供服务允许用户自全球DNS服务器对域名与DNS 区域进行注册与管理。与所有AWS服务一样,Route 53也是通过API来管理的。
  • Amazon S3是一个具有高可用性、高耐久度的对象存储服务。通常用于存储图片之类的静态资源,不过用来存储配置信息、或者其他无服务器/无状态系统的信息也是很好的选择。

动态DNS系统的逻辑流程

下面的图片展示了客户端是怎样向API Gateway和Lambda服务包发起API请求,以获得IP地址的。
图片描述

客户端知道自己的公共IP后,向我们的服务发送了另一个请求,设置DNS记录。Lambda通过咨询S3中的一个配置文件,来确认请求是否有效。如果核实有效,Lambda就会通过API调用,在Route 53中设置DNS条目。现在,网络当前的IP是公共DNS,可以通过标准的DNS查询来获取。
图片描述

使用AWS Lambda与Amazon Route 53获取动态DNS的好处

当然还有其他可用的动态DNS系统,下面列举了我们系统的一些优势。

  • 容易设置:样例客户端中包含了所有代码、设置与设置自己AWS账户的指南。
  • 架构单薄:更新API只需三个命令。支持大多语言,可以自行编写客户端,并能运行在Windows、Linux、OS X、Raspberry Pi、Chrome OS与DD-WRT/ Tomato USB 路由固件之上。
  • 支持任意数量的客户端、主机名与域名。
  • 价格低廉,1-2美元/mo。Route 53 每个区域成本为0.5美元/月,DNS查询花费为0.01美元/25万个,而更新DNS所需的Lambda请求为0.01美元/万次。
  • 无服务器微服务。因为代码在Lambda上运行,因此运行自己的Linux主机不需耗费成本或维护费用。
  • 安全。权限划分细致:只有获得授权的客户端才能更新自己的主机名。只有通过加入到DNS中的地址,客户端才能更新系统。
  • 调整当前DNS,只需简单的修改。可以在当前的DNS供应商处保留原本的example.com区域,并在AWS中使用第二个dynamic.example.com区域。
  • 代码开源,架构可扩展。想要向系统增加自己的功能,或请关注后续文章。我们打算演示该如何借助加强版系统,从网络或漫游的笔记本对Amazon EC2实例进行公开存取。

前提条件

  • AWS(Amazon Web Services)帐号。新账号有资格享受AWS Free Tier免费服务。
  • 自己的域:由Amazon Route 53或其他供应商托管。通过Route 53,只需每年10美元便可注册一个域

在自己的AWS帐号上构建动态DNS系统

读到这里,信息量已经足够,你可以开始构建自己的系统副本了。如果想要了解更多相关信息,请往下看。如果想要开始构建,请访问Git repository下载图例说明,与所有必要的代码及配置信息。

系统运作的详细描述

首先,客户端需要知道分配给自己网络的公共IP。如果从自己的网络向互联网服务发送请求,则该服务会看到从你的外部IP地址发出请求。

在我们的系统中,以Get mode调用API,就会返回相应的公共IP地址:

https://….amazonaws.com/prod?mode=get
{“return_message”: “176.32.100.36”, “return_status”: “success”}

在后端,API Gateway将请求转化为JSON,并将请求发送方的IP地址发给了Python Lambda的函数。然后,Lambda会通过API Gateway将JSON回应与IP返回给客户端。

下图演示了获得公共IP的请求。
图片描述

现在,客户端通过将Get请求返回的公共IP地址、DNS主机名与共享secret密匙串联在一起,构建了请求token。举个例子,如果IP地址是176.32.100.36,域名为host1.dyn.example.com,共享secret密匙是shared_secret_1,则串联的字符串如下:

176.32.100.36host1.dyn.example.comshared_secret_1

下一步通过该字符串,客户端生成SHA-256哈希

echo -n 176.32.100.36host1.dyn.example.comshared_secret_1 | shasum -a 256
96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535

以明文主机名和该哈希为密匙,客户端发出更新DNS的请求。

https://MY_API_ID.execute-api.us-west-2.amazonaws.com/prod?mode=set&hostname=host1.dyn.example.com&hash=96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535

API Gateway再次将请求返回给Lambda函数。从Amazon S3,Lambda函数用AWS SDK for Python(Boto 3)复制自己的JSON配置文件。所有的AWS服务都可以用SDK来查询与修改。在该系统中,Lambda、S3与Route 53使用Boto 3的交互,在Lambda中是本地可用的。一旦我们的Lambda函数从S3载入配置,就会用主机名作为密匙来获得共享secret密匙与其他相关配置:

{
“host1.dyn.example.com.”: {
“aws_region”: “us-west-2”,
“route_53_zone_id”: “MY_ZONE_ID”,
“route_53_record_ttl”: 60,
“route_53_record_type”: “A”,
“shared_secret”: “SHARED_SECRET_1”
},
“host2.dyn.example.com.”: {…..

客户端将host1.dyn.example.com作为密匙发送,因此Lambda从配置中读取SHARED_SECRET_1,并使用主机名、请求发送方的IP地址与共享secret密匙来重构哈希令牌。如果该哈希由Lambda得出,并通过客户端匹配获得,则该请求被认为是有效的。

一旦请求确认有效,Lambda会使用来自配置的信息,对Route 53进行API调用,以观察DNS主机名是否已经设置好客户端IP。如果无需更变,则Lambda会向客户端发回响应并退出:

{“return_message”: “Your IP address matches the current Route53 DNS record.”, “return_status”: “success”}

如果没有记录,或者现有记录与客户端IP不匹配,则Lambda会向Route 53发出API调用来设置记录,并向客户端发回响应,然后退出:

{“return_message”: “Your hostname record host1.dyn.example.com. has been set to 176.32.100.36”, “return_status”: “success”}

下图展示了设置主机名的请求。
图片描述

该系统的安全功能

  • 所有通过API Gateway的通讯都是加密的。
  • 共享secret密匙不会在互联网上传播。
  • 由于客户端需要提供共享的secret密匙(“持有的东西”)与自身公共IP地址(“自身”),这种身份验证机制是具有多重性的。
  • 这样就将凭据泄漏的可能性降到最低。如果有人想要采取不利的活动,并获得了主机名与共享secret密匙副本,他唯一能做的就是将与单独DNS记录所关联的IP地址变更为自己当前的公共IP。
  • 通过S3服务器端加密,可以对配置文件进行加密。
  • 由于并未用到AWS凭据,因此根本不会被泄漏。

结论

我们在本文中所描述的动态DNS系统展示了如何在AWS上构建自己的微服务,以解决实际问题。我们希望这个系统对你有用,或是帮助你在AWS上运行自己的动态DNS,或是作为案例,协助你研究如何运用我们的服务,来创建自己任意规模的解决方案。

你可以通过访问Git repository来获取完整代码、配置与指南。


(责编/钱曙光,关注架构和算法领域,寻求报道或者投稿请发邮件qianshg@csdn.net,交流探讨可加微信qshuguang2008,备注姓名+公司+职位)

「CSDN 高级架构师群」,内有诸多知名互联网公司的大牛架构师,欢迎架构师加微信qshuguang2008入群,备注姓名+公司+职位。

评论