-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
138 lines (118 loc) · 3.28 KB
/
index.js
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request))
})
const API = 'https://api.cloudflare.com/client/v4'
function response(obj, status = 200) {
return new Response(JSON.stringify(obj), {
headers: {
'content-type': 'application/json',
},
status,
})
}
async function dnsRecords(url, method, body = null) {
return await fetch(`${API}/zones/${CF_ZONE}/${url}`, {
method,
headers: {
authorization: 'Bearer ' + CF_TOKEN,
'content-type': 'application/json',
},
body: body === null ? null : JSON.stringify(body),
})
}
async function handleUpdate(type, ip, existingRecord) {
let cfResponse = null
if (ip && existingRecord) {
if (existingRecord.content === ip) {
return
}
// UPDATE
console.log(`updating record from ${existingRecord.content} to ${ip}`)
cfResponse = await dnsRecords(`dns_records/${existingRecord.id}`, 'PATCH', {
content: ip,
})
} else if (ip && !existingRecord) {
// CREATE
console.log(`creating record with ${ip}`)
cfResponse = await dnsRecords(`dns_records`, 'POST', {
type,
name: DOMAIN,
content: ip,
ttl: 1,
proxied: true,
})
} else if (!ip && existingRecord) {
// DELETE
console.log(`deleting record`)
cfResponse = await dnsRecords(`dns_records/${existingRecord.id}`, 'DELETE')
} else {
console.log('doing nothing', ip, existingRecord, DOMAIN)
}
if (!cfResponse) {
return
}
const cfResponseObject = await cfResponse.json()
console.log(cfResponseObject)
if (cfResponseObject.success !== true) {
return cfResponseObject.errors
}
}
async function handleRequest(request) {
const requestUrl = new URL(request.url)
if (requestUrl.pathname === '/current-ip') {
return response({
ip: request.headers.get('cf-connecting-ip'),
})
}
if (requestUrl.pathname !== '/dyndns') {
return response(
{
success: false,
},
404,
)
}
const params = requestUrl.searchParams
// https://<url>?ipv4=<ipaddr>&ipv6=<ip6addr>&password=<pass>
const ipv4 = params.get('ipv4')
const ipv6 = params.get('ipv6')
const password = params.get('password')
if (password !== PASSWORD) {
return response({ success: false, errors: ['invalid password'] }, 401)
}
const cfResponse = await fetch(`${API}/zones/${CF_ZONE}/dns_records`, {
headers: {
authorization: 'Bearer ' + CF_TOKEN,
},
})
const cfResponseObject = await cfResponse.json()
if (cfResponseObject.success !== true) {
return response({ success: false, errors: cfResponseObject.errors })
}
let existing4Record = null
let existing6Record = null
for (const record of cfResponseObject.result) {
if (record.name !== DOMAIN) {
continue
}
if (record.type === 'A') {
existing4Record = record
} else if (record.type === 'AAAA') {
existing6Record = record
}
}
console.log(cfResponseObject)
const v4Errors = await handleUpdate('A', ipv4, existing4Record)
const v6Errors = await handleUpdate('AAAA', ipv6, existing6Record)
const errors = {}
let success = true
if (v4Errors) {
success = false
errors.ipv4 = v4Errors
}
if (v6Errors) {
success = false
errors.ipv6 = v6Errors
}
return response({ success, errors })
}