Skip to content

Instantly share code, notes, and snippets.

@hlissner
Last active July 29, 2022 14:44
Show Gist options
  • Save hlissner/1b9e900b50a75fd568d73d41fd6aef6f to your computer and use it in GitHub Desktop.
Save hlissner/1b9e900b50a75fd568d73d41fd6aef6f to your computer and use it in GitHub Desktop.
A DDNS service provider script for Synology NAS (based off https://github.com/cpascal/syno-ddns-linode/blob/master/linode.php)
#!/usr/bin/php -d open_basedir=/usr/syno/bin/ddns
<?php
if ($argc !== 5) {
echo 'badparam';
exit();
}
// Entered into DSM (Control Panel > External Access > DDNS)
$username = (string) $argv[1]; // Resource ID
$password = (string) $argv[2]; // API Key
$hostname = (string) $argv[3]; // DomainID.domain (e.g. 1234567.henrik.io)
$ip = (string) $argv[4]; // External address
$token = $password;
$domainId = explode('.', $hostname)[0];
$resourceId = $username;
// only for IPv4 format
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
echo "badparam";
exit();
}
function linode_request($curl, $token, $uri, $fields = [], $type = 'GET')
{
$BASE_URL = 'https://api.linode.com/v4';
$HEADERS = [
'Authorization: Bearer '.$token,
'Content-type: application/json',
];
curl_setopt($curl, CURLOPT_URL, $BASE_URL.$uri);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $type);
curl_setopt($curl, CURLOPT_HTTPHEADER, $HEADERS);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
if (count($fields) > 0) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
array_push($HEADERS, 'Accept: application/json');
} else {
curl_setopt($curl, CURLOPT_POST, false);
}
$res = curl_exec($curl);
$http_status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$error = null;
switch ($http_status) {
case 200: break;
case 401: $error = 'badauth'; break;
default : $error = '911'; break;
}
if ($error !== null) {
echo $error;
curl_close($curl):
exit(-1);
}
return json_decode($res, true);
}
$req = curl_init();
//
$json = linode_request($req, $token, 'GET', "/domains/$domainId/records");
if ($json['results'] < 1) {
echo 'nohost';
curl_close($req);
exit();
}
$record = null;
foreach($json['data'] as $row) {
if ($row['type'] == 'A' && (string) $row['id'] == $resourceId) {
$record = $row['target'];
}
}
if ($record === null) {
echo 'nohost';
curl_close($req);
exit();
}
if ($record == $ip) {
echo 'nochg';
curl_close($req);
exit();
}
//
linode_request($req, $token, 'PUT', "/domains/$domainId/records/$resourceId", [ 'target' => $ip ]);
curl_close($req);
echo 'good';
@hlissner
Copy link
Author

Acquiring domain/resource IDs via Linode's API

  • Acquiring the domain ID:

    APIKEY=...
    curl -H "Authorization: Bearer $APIKEY" \
         -H "Accept: application/json" \
         https://api.linode.com/v4/domains | jq
  • Acquiring the resource ID

    APIKEY=...
    DOMAIN=1234567
    curl -H "Authorization: Bearer $APIKEY" \
         -H "Accept: application/json" \
         "https://api.linode.com/v4/domains/$DOMAIN/records" | jq
  • Updating a resource's DNS record

    APIKEY=...
    DOMAIN=1234567
    RECORD=12345678
    IP=123.123.123.123
    curl -H "Authorization: Bearer $APIKEY" \
         -H "Accept: application/json" \
         -H "Content-Type: application/json" \
         -X PUT \
         -d "{\"target\":\"$IP\"}" \
         "https://api.linode.com/v4/domains/$DOMAIN/records/$RECORD"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment