-
Notifications
You must be signed in to change notification settings - Fork 2
/
thdns.py
229 lines (193 loc) · 7 KB
/
thdns.py
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#!/usr/bin/python
"""DNS dinamico con TopHost.
Lancia thdns -h per informazioni sull'uso.
Daniele Paganelli @ 2007
Guido del Puente @ 2018 fix
Emanuele Magrin @ 2021 more fixes and code cleaning
CreativeCommons Attribution-ShareAlike"""
########################
# CONFIGURAZIONE
########################
# Nome utente e password per il pannello di controllo TopHost:
userid = "username"
passwd = "password"
# Nomi (domini di terzo livello) dei quali si desidera aggiornare l'ip: (devono gia' essere presenti come record di tipo A.)
dyn=['@','www']
# File dove memorizzare l'ip dell'ultimo aggiornamento:
logip='/tmp/thdns.ip'
# FINE CONFIGURAZIONE
#-------------------------
#######################
#######################
# COSTANTI
#######################
version='0.3'
storedip=None
test=True
ip=''
help="""#################################
thdns %s - Gestione DNS per TopHost
#################################
Utilizzo: thdns [<opzioni> <ip>]
ARGOMENTI:
[<ip>]: Aggiorna i nomi all'ip dato in argomento (equivalente al flag -i <ip>, o --ip=<ip>).
OPZIONI:
-f [<ip>], --forza[=<ip] : Forza l'aggiornamento (nota: non abusare di questa opzione per non sovraccaricare i server)
-g [<ip>],--gentile[=<ip]: Controlla se l'aggiornamento e' necessario, paragonando l'ip attuale (in argomento o ottenuto dalla rete) all'ip dell'ultima chiamata al programma, memorizzato in %s. Questo e' il comportamento predefinito.
-h, --help : stampa questo messaggio di aiuto
-n <dom>, --nome=<dom>: Aggiorna questo/i sottodominio/i, ignorando quelli configurati. <dom> e' una lista di sottodomini separati da virgole.
Tutte le opzioni e gli argomenti sono facoltativi. Nel caso non venga specificato un ip ne' in argomento ne' tra le opzioni, verra' ottenuto in rete tramite il servizio checkip.dyndns.org (non funziona con i proxy).
Esempi:
thdns -f 192.168.1.1 -> forza l'aggiornamento all'ip
thdns 192.168.1.1 / thdns -g 192.168.1.1 -> se %s non corrisponde a 192.168.1.1, aggiorna
thdns -> ottiene l'indirizzo dalla rete; se non corrisponde a %s, aggiorna (equivalente a thdns -g)
"""
#######################
# FUNZIONI
#######################
from httplib import HTTPSConnection,HTTPS
from urllib2 import urlopen
from urllib import urlencode
from base64 import encodestring
from string import strip
from sys import argv,exit
from os.path import exists
from getopt import getopt
import ssl
import json
import httplib, urllib
from collections import OrderedDict
def getip():
"""Ottieni l'ip da checkip.dyndns.org"""
si='Address: '
r=urlopen('http://checkip.dyndns.org').read()
i=r.find(si)+len(si)
e=r.find('<',i)
return r[i:e]
def getsid():
"""Connetti al cpanel per ottenere l'id di sessione"""
# La procedura e' necessaria per ottenere i cookie,
# che chiameremo PSI e SID
# PSI corrisponde al PHPSESSID= , presente nella risposta di /x-login,
# mentre SID corrisponde al cookie che viene rilasciato nel body della pagina /godns
global sid,psi
# Prepara l'header ed effettua una POST a cp.tophost.it/x-login,
# fornisci le credenziali e ottieni PHPSESSID= dall'header,
# che verra' inserito su "psi"
headersauth = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
auth = urllib.urlencode([('user',''+userid),('pass',''+passwd)])
conn = HTTPSConnection('cp.tophost.it')
conn.request('POST', '/x-login', auth, headersauth)
r=conn.getresponse()
psi=r.getheader('Set-Cookie').split(';')[0].replace('PHPSESSID=','')
conn.close
# Prepara l'header ed effettua una GET a /x-httpsstatus,
# necessaria per determinare il cookie "nodo"
# che si trovera' nell'header
headers_httpstatus = {'Cookie': 'PHPSESSID='+psi+'; logged_cp='+userid}
conn = HTTPSConnection('cp.tophost.it')
conn.request('GET', '/x-httpsstatus', headers=headers_httpstatus)
x_httpsstatus=conn.getresponse()
node=x_httpsstatus.getheader('set-cookie').split(';')[0]
conn.close()
# Prepara l'header ed effettua una GET a /godns,
# necessaria per determinare il cookie "sid"
# che sara' presente nella pagina come dato hidden
headers_godns = {'Cookie': 'PHPSESSID='+psi+'; logged_cp='+userid+'; '+node}
conn = HTTPSConnection('cp.tophost.it')
conn.request('GET', '/godns', headers=headers_godns)
godns=conn.getresponse()
page=godns.read()
bound='<input type=hidden name=sid value='
s=page.find(bound); e=page.find('>',s)
sid=page[s+len(bound):e].replace('"','')
conn.close()
return sid,psi
def dnscp(act,params):
"""Effettua l'azione richiesta sul pannello dns"""
myheaders = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain", "Cookie":"seeweb="+psi,"Content-length":"%d" % len(params)}
conn = HTTPSConnection("ns1.th.seeweb.it", timeout=100, context=ssl._create_unverified_context())
conn.request("POST", act, params, myheaders)
response = conn.getresponse()
hdrs = response.getheaders()
msg = response.msg
reply = response.status
page = response.read()
conn.close()
return reply,msg,hdrs,page
def dnsinfo(name):
"""Controlla quale indirizzo ip era presente nel pannello dns di tophost.
Questa funzione fa il parsing della pagina per individuare
l'ip associato al nome richiesto."""
b1='<input type="hidden" name="name" value="%s">' % name
i=data.find(b1)+len(b1)
b2='<input type="hidden" name="value" value="'
i=data.find(b2,i)+len(b2)
e=data.find('">',i)
return data[i:e]
def update(name):
"""Aggiorna il valore per il nome richiesto, se necessario"""
global ip
old=dnsinfo(name) # L'ip del DNS
if ip==old:
# Esci dalla funzione se l'ip del DNS era corretto
print '[%10s]\t mantengo %s' % (name,old)
return False
# Modifica il nome
params = urlencode({'name':name,
'old_value':old,
'new_value':ip,
'type':'A',
'action':'Modifica'})
reply,msg,hdrs,page=dnscp('/dnscp/index.php?page=edit_record',params)
# Quando l'aggiornamento riesce, viene proposto un redirect.
# Non ci interessa, quindi consideriamolo riuscito.
if msg!='OK' and reply!=302:
print 'Errore di connessione per %s: %s, %s.' % (name,str(reply),msg)
return False
print '[%10s]\t era %s, aggiorno a %s' % (name,old,ip)
return True
#######################
# SCRIPT
#######################
# Lettura parametri
if len(argv)>1:
opts, args=getopt(argv[1:],'fghin:',['forza','help','gentile','nome='])
for o,a in opts:
if o in ['-h','--help']:
print help
exit(0)
if o in ['-f','--forza']:
test=False
ip=a
if o in ['-g','--gentile']:
test=True
ip=a
if o in ['-n','--nome']:
dyn=a.replace(' ','').split(',')
if len(args)==1:
ip=args[0]
if ip=='':
ip=getip()
if test==True:
# Compara con l'ip memorizzato
if exists(logip):
storedip=open(logip,'r').read()
if storedip==ip:
print "L'IP corrente corrisponde gia' a quello memorizzato ("+storedip+")"
noedit = 'Non modifico '
for key in dyn:
noedit=noedit+key+', '
print (noedit[:-2])
exit(0)
else:
open(logip,'w').write(ip)
else:
open(logip,'w').write(ip)
# Inizio la sessione con il cpanel:
getsid()
params = urlencode({'sid': sid, 'b1': 'Vai al pannello del DNS'})
data=dnscp('/dnscp/',params)[-1]
# Aggiorna tutti i nomi richiesti sul pannello dns:
for n in dyn:
update(n)