forked from gdelpuente/thdns
/
thdns.py
196 lines (165 loc) · 5.73 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
#!/usr/bin/python
"""DNS dinamico con TopHost.
Lancia thdns -h per informazioni sull'uso.
Daniele Paganelli @ 2007
Guido del Puente @ 2018 fix
CreativeCommons Attribution-ShareAlike"""
########################
# CONFIGURAZIONE
########################
# Nome utente e password per il pannello di controllo TopHost:
userid = "userid"
passwd = "passwd"
# 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.2'
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)
""" % (version,logip,logip,logip)
ua='User-Agent','thdns/%s (+https://github.com/gdelpuente/thdns)' % version
#######################
# 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
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"""
# "Basic" authentication encodes userid:password in base64. Note
# that base64.encodestring adds some extra newlines/carriage-returns
# to the end of the result. string.strip is a simple way to remove
# these characters.
global sid,psi
auth = 'Basic ' + strip(encodestring(userid + ':' + passwd))
conn = HTTPSConnection('cp.tophost.it')
conn.putrequest('GET', '/dnsjump.php')
conn.putheader('Authorization', auth )
conn.putheader(ua[0],ua[1])
conn.endheaders()
r=conn.getresponse()
psi=r.getheader('Set-Cookie').replace('PHPSESSID=','').replace('; path=/','')
page=r.read()
bound='<input type="hidden" name="sid" value="'
s=page.find(bound); e=page.find('">',s)
sid=page[s+len(bound):e]
conn.close()
return sid,psi
def dnscp(act,params):
"""Effettua l'azione richiesta sul pannello dns"""
headers = {"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, headers)
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)
if msg!='OK':
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:
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)