Browse Source

New repo

master
rune 1 year ago
commit
2fe2aaf350
6 changed files with 288 additions and 0 deletions
  1. 63
    0
      .gitignore
  2. 0
    0
      .npmignore
  3. 14
    0
      config.json
  4. 157
    0
      index.js
  5. 18
    0
      package.json
  6. 36
    0
      readme.md

+ 63
- 0
.gitignore View File

@@ -0,0 +1,63 @@
1
+# Logs
2
+logs
3
+*.log
4
+npm-debug.log*
5
+yarn-debug.log*
6
+yarn-error.log*
7
+# Runtime data
8
+pids
9
+*.pid
10
+*.seed
11
+*.pid.lock
12
+.DS_Store
13
+
14
+# Directory for instrumented libs generated by jscoverage/JSCover
15
+lib-cov
16
+
17
+# Coverage directory used by tools like istanbul
18
+coverage
19
+
20
+# nyc test coverage
21
+.nyc_output
22
+
23
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24
+.grunt
25
+
26
+# Bower dependency directory (https://bower.io/)
27
+bower_components
28
+
29
+# node-waf configuration
30
+.lock-wscript
31
+
32
+# Compiled binary addons (http://nodejs.org/api/addons.html)
33
+build/Release
34
+
35
+# Dependency directories
36
+node_modules/
37
+jspm_packages/
38
+
39
+# Typescript v1 declaration files
40
+typings/
41
+
42
+# Optional npm cache directory
43
+.npm
44
+
45
+# Optional eslint cache
46
+.eslintcache
47
+
48
+# Optional REPL history
49
+.node_repl_history
50
+
51
+# Output of 'npm pack'
52
+*.tgz
53
+
54
+# Yarn Integrity file
55
+.yarn-integrity
56
+
57
+# dotenv environment variables file
58
+.env
59
+.idea/dyndns.iml
60
+.idea/workspace.xml
61
+.idea/vcs.xml
62
+.idea/dyndns.iml
63
+.idea/modules.xml

+ 0
- 0
.npmignore View File


+ 14
- 0
config.json View File

@@ -0,0 +1,14 @@
1
+{
2
+  "api_key": "AN#EXAMPLE!API$KEY",
3
+  "domains":
4
+  	[
5
+		  {
6
+		  	"id": 00000,
7
+		  	"name": "example.com"
8
+		  },
9
+		  {
10
+		  	"id": 000000,
11
+		  	"name": "example.com"
12
+		  }
13
+  	]
14
+}

+ 157
- 0
index.js View File

@@ -0,0 +1,157 @@
1
+#!/usr/bin/env node
2
+var request = require('request');
3
+var fs = require('fs');
4
+var args = process.argv;
5
+var includeIP6 = false;
6
+var IP6;
7
+var updated = false;
8
+try{
9
+    var configFileId = process.argv.indexOf('--config');
10
+    var config = JSON.parse(fs.readFileSync(process.argv[configFileId+1], 'utf8'));
11
+} catch(error){
12
+     console.log(new Date()+' Error reading cofig file. File either missing or malformed.'); 
13
+     process.exit();
14
+};
15
+
16
+if(process.argv.indexOf('--list') !== -1 || process.argv.indexOf('-l') !== -1){
17
+   var domainInfo = JSON.parse(getDomainInfo());
18
+   console.dir(domainInfo, {depth: null, colors: true});
19
+   process.exit();
20
+};
21
+
22
+function getIPv4() {
23
+    var source;
24
+    request({
25
+    url: 'http://ip4.iurl.no' ,   
26
+    method: 'GET',
27
+    headers: {
28
+        'Content-Type': 'application/text'
29
+    }
30
+}, function(error, response, body){
31
+    if(error){
32
+        console.log(new Date()+' Error getting IP '+error.code+' ('+error.host+')'); 
33
+        process.exit();
34
+    }
35
+    source = body;
36
+    });
37
+    while(source === undefined) {
38
+      require('deasync').runLoopOnce();
39
+    }
40
+    return source;
41
+
42
+};
43
+
44
+function getIPv6() {
45
+    var source;
46
+    request({
47
+    url: 'http://ip6.iurl.no' ,   
48
+    method: 'GET',
49
+    headers: {
50
+        'Content-Type': 'application/text'
51
+    }
52
+}, function(error, response, body){
53
+    if(error){
54
+        console.log(new Date()+' Error getting IP '+error.code+' ('+error.host+')'); 
55
+        process.exit();
56
+    }
57
+    source = body;
58
+    });
59
+    while(source === undefined) {
60
+      require('deasync').runLoopOnce();
61
+    }
62
+    return source;
63
+
64
+};
65
+
66
+function updateIP(newIP,domain,API_KEY,domainid) {
67
+    request({
68
+    url: 'https://api.digitalocean.com/v2/domains/'+domain+'/records/' + domainid ,
69
+    qs: {"data": newIP},
70
+    method: 'PUT',
71
+    headers: {
72
+        'Content-Type': 'application/json',
73
+        'Authorization': 'Bearer '+API_KEY
74
+    }
75
+}, function(error, response, body){
76
+    if(error){
77
+        console.log(new Date()+' Error uppdating IP '+error.code); 
78
+        process.exit();
79
+    }
80
+});
81
+}
82
+
83
+function getServerIP(i){
84
+    var remoteIP;
85
+    request({
86
+    url: 'https://api.digitalocean.com/v2/domains/'+config.domains[i].name+'/records/' + config.domains[i].id ,
87
+    method: 'GET',
88
+    headers: {
89
+        'Content-Type': 'application/json',
90
+        'Authorization': 'Bearer '+config.api_key
91
+    }
92
+}, function(error, response, body){
93
+    try{
94
+    var data = (JSON.parse(body));
95
+    remoteIP = [data.domain_record.type, data.domain_record.data];
96
+} catch(error){
97
+        console.log(new Date()+' Error getting remote IP '+error.code); 
98
+        process.exit();
99
+}
100
+});
101
+    while(remoteIP === undefined) {
102
+      require('deasync').runLoopOnce();
103
+    }
104
+    return remoteIP;
105
+}
106
+function getDomainInfo(){
107
+    var domainInfo;
108
+    request({
109
+    url: 'https://api.digitalocean.com/v2/domains/'+config.domains[0].name+'/records/',
110
+    method: 'GET',
111
+    headers: {
112
+        'Content-Type': 'application/json',
113
+        'Authorization': 'Bearer '+config.api_key
114
+    }
115
+}, function(error, response, body){
116
+    try{
117
+    domainInfo = body;
118
+} catch(error){
119
+    console.log(new Date()+' Error getting domaininfo '+error.code); 
120
+    process.exit();
121
+}
122
+});
123
+    while(domainInfo === undefined) {
124
+      require('deasync').runLoopOnce();
125
+    }
126
+    return domainInfo;
127
+}
128
+if(process.argv.indexOf('--list') !== -1 || process.argv.indexOf('-l') !== -1){
129
+   var domainInfo = JSON.parse(getDomainInfo());
130
+   console.dir(domainInfo, {depth: null, colors: true});
131
+   process.exit();
132
+};
133
+
134
+if(process.argv.indexOf('-ip6') !== -1){
135
+    IP6 = getIPv6();
136
+    console.log('IP6');
137
+    includeIP6 = true
138
+};
139
+
140
+var IP4 = getIPv4();
141
+
142
+
143
+   for (var i = 0; i < config.domains.length; i++) {
144
+        var dnsIP = getServerIP(i);
145
+        if(dnsIP[0] === 'A' && IP4.localeCompare(dnsIP[1]) != 0){
146
+            updateIP(IP4,config.domains[i].name,config.api_key,config.domains[i].id);
147
+	    updated = true;
148
+	    console.log(new Date()+' Updated IP to '+IP4);           
149
+        
150
+        if(includeIP6 && dnsIP[0] === 'AAAA' && IP6.localeCompare(dnsIP[1]) != 0){
151
+            updateIP(IP6,config.domains[i].name,config.api_key,config.domains[i].id);
152
+	    console.log(new Date()+' Updated IP to '+IP6);
153
+        };
154
+};
155
+    };
156
+if(!updated) console.log('['+new Date()+'] IP not updated.');
157
+    process.exit();

+ 18
- 0
package.json View File

@@ -0,0 +1,18 @@
1
+{
2
+  "name": "dyndns",
3
+  "version": "1.0.5",
4
+  "description": "Dynamic DNS and DigitalOcean",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "test": "echo \"Error: no test specified\" && exit 1"
8
+  },
9
+  "author": "Rune G",
10
+  "license": "ISC",
11
+  "bin": {
12
+    "dyndns": "./index.js"
13
+  },
14
+  "dependencies": {
15
+    "deasync": "^0.1.10",
16
+    "request": "^2.81.0"
17
+  }
18
+}

+ 36
- 0
readme.md View File

@@ -0,0 +1,36 @@
1
+# DYNDNS
2
+DYNDNS is a small Node CLI (command line) app that updates DNS records on you Digital Ocean account.
3
+
4
+### Installation
5
+Clone this repo with `git clone https://gitlab.no/rune/dyndns.git` edit the `config.json` file with your information. To get your API key, log in to your Digital Ocean account and click the API link at the top of the page. Follow the instructions!
6
+
7
+If you don't know your subdomains ID, just fill in the parts with `api_key` and `name` and install as described below. The `name` parameter is the top level domain name, eg. `example.com`.
8
+
9
+Then run the app `dyndns --config "/path/to/your/config.json" --list`
10
+
11
+You will get a JSON looking something like this:
12
+
13
+    
14
+       { id: 000000, <-- The ID
15
+       type: 'A',
16
+       name: 'YOU SUB DOMAIN',
17
+       data: '127.0.0.1', <-- Current IP
18
+       priority: null,
19
+       port: null,
20
+       ttl: 1800,
21
+       weight: null,
22
+       flags: null,
23
+       tag: null },
24
+
25
+Place the value of `id` in the correct place(s) in your `config.json` file.
26
+
27
+### Use
28
+As describe above, you use the app by runnig it with parameters. You _HAVE_ to include `--config "/path/to/your/config.json"`. The file can be anywhere on the system, but the user running the app should be able to read the file! You can name the file what you like as well.
29
+
30
+To include IPv6 add `-ip6` to the command. eg. `dyndns --config "/path/to/your/config.json" -ip6`
31
+
32
+I use it with Cron. My crontab contains the line `0 * * * * dyndns --config "/path/to/your/config.json" -ip6 >/dev/null 2>&1`. This runs the command once an hour with no logging. If you want a log, you can use `0 * * * * dyndns --config "/path/to/your/config.json" -ip6 >> /var/log/dyndns.log`in your crontab. This logs all events and errors to a log file (`dyndns.log`). You can of course name your log file as you wish!  Digital Ocean has a rate limit on 5000 requests per hour.
33
+
34
+### Development
35
+
36
+

Loading…
Cancel
Save