找回密码
 新建账号

腾讯云 DnsPod API 3.0 接口 Powershell 程序实现动态解析域名记录

[复制链接]
php 发表于 2024/12/12 19:10 | 显示全部楼层 |阅读模式
DnsPod 被腾讯收购以后进行了升级,原先的 API 相对简单,后续将会停止服务,应当尽早过渡到新的接口,DnsPod 3.0 分两种签名方法,分别是 V1 和 V3,V1 虽然比原 DnsPod 认证复杂,但比起 V3 仍然不算复杂,目前腾讯云推荐的是 V3 签名算法,安全性更高,但算法比较复杂,腾讯官方提供了 Python、Java、PHP、Go、NodeJS、.NET、C++、Ruby 的 SDK,可以直接下载配置使用,但这些 SDK 都依赖于指定的程序,需要额外安装软件,Powershell 是 Windows 内置组件,不需要安装,但腾讯云没有提供 DnsPod Powershell 程序 SDK 或示例,而普通人使用 Powershell 编程又会困难重重,并不是因为 Powershell 难学,而是设计 Powershell 的人不是正常人,Powershell 的坑太多,脑残的设计和莫名其妙的数据自动转换贯穿始终,一不小心就掉进坑里。
以下代码使用 Powershell DnsPod 3.0 接口实现了 Ddns 动态更新域名解析记录。支持 Powershell 5.1 - 7.4,其中 7.4 是编写代码时 Powershell 的最高版本。
代码有可能被编辑器改变,建议下载附件使用。
  1. <#
  2.     .Description Powershell DnsPod API 3.0 接口程序 动态更新域名解析 实现 Ddns
  3.     .Link wuxiancheng.cn
  4.     .Notes 本程序由吴先成编写
  5.     .Notes 请修改 Make-ApiRequest 中的 $SecretId $SecretKey 为自己的腾讯云 API 密钥信息
  6. #>
  7. <#
  8.     .Description 计算字符串的哈希值
  9.     .Link wuxiancheng.cn
  10.     .Notes 本程序由吴先成编写
  11.     .Parameter [String] $Algorithm 哈希算法 支持 SHA256
  12.     .Parameter [String] $Message 要计算哈希值的字符串
  13.     .Outputs [String] 返回计算得到的哈希值
  14. #>
  15. Function Compute-Hash{
  16.     [CmdletBinding(PositionalBinding=$False)]
  17.     Param(
  18.         [String][ValidateSet("SHA256")]$Algorithm="SHA256",
  19.         [String]$Message
  20.     )
  21.    $SHA256 = Invoke-Expression -Command "[System.Security.Cryptography.$Algorithm]::Create()"
  22.    $MessageBytes = [System.Text.Encoding]::UTF8.GetBytes($Message)
  23.    $HashBytes = $SHA256.ComputeHash($MessageBytes)
  24.    $Hash = [System.BitConverter]::ToString($HashBytes).Replace("-", "").ToLower()
  25.    Return $Hash
  26. }
  27. <#
  28.     .Description 计算 HMAC 哈希值
  29.     .Link wuxiancheng.cn
  30.     .Notes 本程序由吴先成编写
  31.     .Parameter [String] $Algorithm 哈希算法 支持 SHA256
  32.     .Parameter [String] $Message 要计算哈希值的字符串
  33.     .Parameter [String]|[Byte[]] $Key 密钥 字符串或字节数组
  34.     .Parameter [Switch] $Binary 是否返回原始二进制数据
  35.     .Outputs [String]|[Byte[]] 使用 $Binary 时返回字节数组 否则返回字符串
  36. #>
  37. Function Compute-HmacHash{
  38.     [CmdletBinding(PositionalBinding=$False)]
  39.     Param(
  40.         [String][ValidateSet("SHA256")]$Algorithm="SHA256",
  41.         [String]$Message,
  42.         [Object][ValidateScript({$_ -is [String] -or $_ -is [Byte]})]$Key,
  43.         [Switch]$Binary
  44.     )
  45.     $Utf8Encoding = [System.Text.Encoding]::UTF8
  46.     $MessageBytes = $Utf8Encoding.GetBytes($Message)
  47.     If($Key -is [String]){
  48.         $KeyBytes = $Utf8Encoding.GetBytes($Key)
  49.     }Else{
  50.         $KeyBytes = $Key
  51.     }
  52.     $HMAC = New-Object -TypeName "System.Security.Cryptography.HMAC$Algorithm"
  53.     $HMAC.Key = $KeyBytes
  54.     $HashBytes = $HMAC.ComputeHash($MessageBytes)
  55.     If($Binary){
  56.         $Hash = $HashBytes
  57.     }Else{
  58.         $Hash = [System.BitConverter]::ToString($HashBytes).Replace("-", "").ToLower()
  59.     }
  60.     Return $Hash
  61. }
  62. <#
  63.     .Description 将非 ASCII 字符转换为 JSON 安全字符
  64.     .Link wuxiancheng.cn
  65.     .Notes 本程序由吴先成编写
  66.     .Parameter [String] $String 原字符串
  67.     .Outputs [String] 转换后的字符串
  68. #>
  69. Function Escape-JsonString{
  70.     Param(
  71.         [String]$String
  72.     )
  73.     $EscapedString = $String.ToCharArray() | ForEach-Object{
  74.         If($_ -match "[^\x00-\x7F]"){
  75.             Return ("\u{0:x4}" -f [Int32][Char]$_)
  76.         }Else{
  77.             Return $_
  78.         }
  79.     }
  80.     Return $EscapedString -join ""
  81. }
  82. <#
  83.     .Description 向服务器发送接口请求 请求失败时输出错误信息
  84.     .Link wuxiancheng.cn
  85.     .Notes 本程序由吴先成编写   
  86.     .Parameter [String] $Action 需要请求的服务器接口名称
  87.     .Parameter [Hashtable] $Fields 向服务器发送的 POST 数据字段
  88.     .Outputs [Object] 返回请求响应对象 有 .Error 代表接口报错 .Error.Message 是接口提供的错误信息 .Error.Code 是接口提供的错误代码
  89. #>
  90. Function Make-ApiRequest{
  91.     [CmdletBinding(PositionalBinding=$False)]
  92.     Param(
  93.         [String]$Action,
  94.         [System.Collections.Hashtable]$Fields=@{}
  95.     )   
  96.     $ResponseObject = New-Object -TypeName System.Object
  97.     if("" -ne $Action){
  98.         $ActionLowerCase = $Action.ToLower()
  99.         $PsVersion = $PSVersionTable.PSVersion        
  100.         $SecretId  = "wuxiancheng"
  101.         $SecretKey = "wuxiancheng"
  102.         $Service   = "dnspod"
  103.         $HostName  = "dnspod.tencentcloudapi.com"
  104.         $Version   = "2021-03-23"
  105.         $Endpoint    = "https://$HostName"
  106.         $HashAlgorithm = "SHA256"
  107.         $SignatureAlgorithm   = "TC3-HMAC-SHA256"
  108.         $DateTime  = Get-Date
  109.         # Powershell 6.0 及更早版本 %s 返回值包含小数部分,并且有时区偏移量,需要修正。
  110.         If($PsVersion -lt [System.Version]"6.1"){
  111.             $Timestamp = [System.Math]::Round((Get-Date -Date $DateTime.ToUniversalTime() -UFormat "%s"))
  112.         }Else{
  113.             $Timestamp = Get-Date -Date $DateTime -UFormat "%s"
  114.         }
  115.         # Powershell 7.0 及更早版本不支持 Get-Date -AsUtc
  116.         If($PsVersion -lt [System.Version]"7.1"){
  117.             $UtcDate = [System.DateTime]::UtcNow.ToString("yyyy-MM-dd")
  118.         }Else{
  119.             $UtcDate = Get-Date -AsUtc -Date $DateTime -UFormat "%Y-%m-%d"
  120.         }
  121.         
  122.         $RequestMethod = "POST"
  123.         # Powershell 6.0 及更早版本不支持 JSON 非 ASCII 字符转码 会导致有汉字时接口请求出错
  124.         If($PsVersion -lt [System.Version]"6.1"){
  125.             $RequestPayload  = ConvertTo-Json -InputObject $Fields -Compress
  126.             $RequestPayload  = Escape-JsonString -String $RequestPayload
  127.         }Else{
  128.             $RequestPayload  = ConvertTo-Json -EscapeHandling "EscapeNonAscii" -InputObject $Fields -Compress
  129.         }
  130.         $CanonicalUri  = "/"
  131.         $CanonicalQueryString = ""
  132.         $ContentType = "application/json; charset=utf-8"
  133.         $CanonicalHeaders = "content-type:$ContentType`nhost:$HostName`nx-tc-action:$ActionLowerCase`n"
  134.         $SignedHeaders   = "content-type;host;x-tc-action"
  135.         $HashedRequestPayload = Compute-Hash -Algorithm $HashAlgorithm -Message $RequestPayload
  136.         $CanonicalRequest = "$RequestMethod`n$CanonicalUri`n$CanonicalQueryString`n$CanonicalHeaders`n$SignedHeaders`n$HashedRequestPayload"
  137.         
  138.         $CredentialScope = "$UtcDate/$Service/tc3_request"
  139.         $HashedCanonicalRequest = Compute-Hash -Algorithm $HashAlgorithm -Message $CanonicalRequest
  140.         $StringToSign = "$SignatureAlgorithm`n$Timestamp`n$CredentialScope`n$HashedCanonicalRequest"
  141.         
  142.         $SecretDate    = Compute-HmacHash -Algorithm $HashAlgorithm -Message $UtcDate -Key "TC3$SecretKey" -Binary
  143.         $SecretService = Compute-HmacHash -Algorithm $HashAlgorithm -Message $Service -Key $SecretDate -Binary
  144.         $SecretSigning = Compute-HmacHash -Algorithm $HashAlgorithm -Message "tc3_request" -Key $SecretService -Binary
  145.         $Signature     = Compute-HmacHash -Algorithm $HashAlgorithm -Message $StringToSign -Key $SecretSigning
  146.         
  147.         $Authorization = "$SignatureAlgorithm Credential=$SecretId/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$Signature"
  148.         
  149.         $Headers = @{
  150.             "Authorization" = $Authorization
  151.             "Content-Type" = $ContentType
  152.             "Host" = $HostName
  153.             "X-TC-Action" = $Action
  154.             "X-TC-Timestamp" = $Timestamp
  155.             "X-TC-Version" = $Version
  156.         }
  157.         
  158.         $InvokingArguments = @{
  159.             "Uri" = $Endpoint
  160.             "Method" = "POST"
  161.             "Headers" = $Headers
  162.             "Body" = $RequestPayload
  163.         }
  164.         # Powershell 6.0+ 支持 -SkipHeaderValidation 跳过请求头验证
  165.         If($PsVersion -ge [System.Version]"6.0"){
  166.             $InvokingArguments.SkipHeaderValidation = $True
  167.         }
  168.         $ResponseText = Invoke-WebRequest @InvokingArguments | Select-Object -ExpandProperty Content
  169.         $ResponseObject = ConvertFrom-Json -InputObject $ResponseText
  170.         If($ResponseObject -IsNot [System.Object]){
  171.             $ResponseObject = New-Object -TypeName System.Object
  172.         }ElseIf($ResponseObject.Response -Is [System.Object]){
  173.             $ResponseObject = $ResponseObject.Response
  174.         }
  175.         If($ResponseObject.Error -and $ResponseObject.Error.Message){
  176.             Write-Warning ($Action + ": " + $ResponseObject.Error.Message)
  177.         }
  178.     }
  179.     Return $ResponseObject
  180. }
  181. <#
  182.     .Description 调用接口更新域名解析记录值
  183.     .Link wuxiancheng.cn
  184.     .Notes 本程序由吴先成编写
  185.     .Parameter [String] $Domain 域名 如 wuxiancheng.cn
  186.     .Parameter [String] $Record 记录名 如 www
  187.     .Parameter [String] $Type 记录类型 如 A AAAA
  188.     .Parameter [String] $LineId 线路编号 0 代表默认线路
  189.     .Outputs [Boolean] 成功时返回 $True 失败时返回 $False
  190. #>
  191. Function Update-RecordValue{
  192.     [CmdletBinding(PositionalBinding=$False)]
  193.     Param(
  194.         [String]$Domain,
  195.         [String]$Record,
  196.         [String]$Type,
  197.         [String]$Value,
  198.         [String]$LineId="0"
  199.     )
  200.     $Response = Make-ApiRequest -Action DescribeRecordFilterList -Fields @{
  201.         "Domain" = $Domain
  202.         "SubDomain" = $Record
  203.         "IsExactSubDomain" = $True
  204.         "RecordType" = @($Type)
  205.         "RecordLine" = @($LineId)
  206.     }
  207.     If($Response.RecordList -is [System.Array]){
  208.         ForEach($RecordObject in $Response.RecordList){
  209.             If($RecordObject.Value -eq $Value){
  210.                 Return $True
  211.             }
  212.             $Response = Make-ApiRequest -Action ModifyRecordFields -Fields @{
  213.                 "Domain"    = $Domain
  214.                 "RecordId"  = $RecordObject.RecordId
  215.                 "FieldList" = @(@{
  216.                     "Key" = "value"
  217.                     "Value" = $Value
  218.                 })
  219.             }
  220.             Return $Null -eq $Response.Error
  221.         }
  222.     }
  223.     Return $False
  224. }

  225. Update-RecordValue -Domain "51-n.com" -Record "www" -Type A -Value "175.155.81.103"
  226. Update-RecordValue -Domain "51-n.com" -Record "www" -Type AAAA -Value "2408:8266:2b01:a6fd:54e2:d4af:3da6:184f"
复制代码
运行脚本前务必将 Make-ApiRequest 中的 $SecretId $SecretKey 修改为自己的密钥信息,如果没有腾讯云云 API 密钥,需要先申请。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?新建账号

×

手机版|轻松E站

GMT+8, 2024/12/21 23:51

快速回复 返回顶部 返回列表