-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathddns-updater.lua
123 lines (92 loc) · 2.82 KB
/
ddns-updater.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
local https = require 'ssl.https'
local http = require 'socket.http'
-- config. following must be URL-encoded
local USERNAME = "username"
local PASSWORD = "password"
local HOSTNAME = "dnsname.net"
local RESPONSE_911 = "911"
local RETRY_SECONDS_911 = 30 * 60 -- wait at least 30 mins before retrying after receiving 911 from noip.com
local LAST_UPDATE_FILE_PATH = "last-update"
local EXTERNAL_IP_SERVER = "http://icanhazip.com/s"
http.USERAGENT="ddns-updater/0.1 [email protected]"
local function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
local function read_whole_file(path)
local f = io.open(path, "r")
if not f then
return nil
end
local contents = f:read("*all")
f:close()
return contents
end
local function write_last_update(last_update)
local str = last_update.time .. " " .. last_update.ip ..
" " .. last_update.response
local f = io.open(LAST_UPDATE_FILE_PATH, "w")
f:write(str)
f:close()
end
local function read_last_update()
local last_update = {}
local str = read_whole_file(LAST_UPDATE_FILE_PATH)
if not str then
last_update.time = 0
last_update.ip = ""
last_update.response = ""
return last_update
end
-- time
local start_index = 1
local space_index = string.find(str, " ")
last_update.time = tonumber(string.sub(str, start_index, space_index - 1))
-- ip
start_index = space_index + 1
space_index = string.find(str, " ", start_index)
last_update.ip = string.sub(str, start_index, space_index - 1)
-- response
last_update.response = string.sub(str, space_index + 1)
return last_update
end
local function get_ip()
local response, code = http.request(EXTERNAL_IP_SERVER)
if tonumber(code) ~= 200 then
return nil
end
return trim(response:gsub("\r", ""):gsub("\n", ""))
end
---- main ----
-- read last_update table (time, ip, response)
local last_update = read_last_update()
local current_ip = get_ip()
if last_update.ip == current_ip then
return
end
local current_time = os.time()
if last_update.response == RESPONSE_911 and
(current_time - last_update.time < RETRY_SECONDS_911) then
return
end
-- if here then either we've waited long enough after receiving a 911
-- or we didn't need to wait. update ip in both cases
-- values plugged in the URL below must be URL-encoded
local update_url = "https://" .. USERNAME .. ":" .. PASSWORD ..
"@dynupdate.no-ip.com/nic/update?hostname=" .. HOSTNAME .. "&myip=" ..
current_ip
local response, code, headers, status = https.request(update_url)
if tonumber(code) ~= 200 then
return
end
response = trim(response)
local current_update = {}
if response == RESPONSE_911 then
current_update.time = current_time
current_update.ip = last_update.ip
current_update.reponse = response
else
current_update.time = current_time
current_update.ip = current_ip
current_update.response = response
end
write_last_update(current_update)