marmottin PostĂ©(e) le 19 octobre 2019 PostĂ©(e) le 19 octobre 2019 (modifiĂ©)  Disposer dâun nom de domaine dont lâadresse IP est laissĂ©e au bon vouloir de votre Fournisseur dâAccĂšs Internet peut rapidement devenir trĂšs pĂ©nible. AprĂšs quelques recherches, jâai mis la main sur un script en Python (merci Ă son auteur : Arnaud Levaufre) qui permet dâactualiser les champs DNS toutes les « x » minutes et donc de palier aux changements dâIP alĂ©atoires imposĂ©s par votre FAI. Nota : Ce script sâappuie sur la derniĂšre version de lâAPI (LiveDNS API / V5). Plus dâinformations ici : https://doc.livedns.gandi.net/ PrĂ©requis: Disposer dâun Nom de Domaine enregistrĂ© chez Gandi.net (ex: dudule.fr) Avoir rĂ©cupĂ©rĂ© le '"Gandi API Token" (API Key) correspondant Ă ce nom de domaine (via https://account.gandi.net/fr/ -> sĂ©curitĂ©) Avoir installĂ© lâinterprĂ©teur Python 3 (derniĂšre version : 3.5.1-0108) sur votre NAS. Disposer de PuTTY sur le terminal dâaccĂšs au NAS et avoir activĂ© SSH dans le Panneau de configuration NAS -> Terminal & SNMP -> Terminal =========================================================================================================================== Mise en place du script "gandip.py": Copier le script dans un rĂ©pertoire utilisateur du NAS. Personnellement, jâutilise WinSCP. Lancer PuTTY et indiquer lâadresse IP local du NAS, le Port = 22 et le type de connexion (SSH). Se connecter (Open). Saisir le Login et le Password du NAS A la rĂ©ponse admin@Diskstation:/$, saisir sudo -i . A la rĂ©ponse Password : saisir de nouveau le Password du NAS. Vous ĂȘtes dĂ©sormais au niveau « Racine » root@Disktation:~# ATTENTION : A partir de maintenant, vous ĂȘtes connectĂ© en ROOT ; une mauvaise manipulation peut entrainer une perte de donnĂ©es ou une inaccessibilité totale Ă votre NAS. CrĂ©er un rĂ©pertoire "dyndns" dans lâarborescence /var/services : cd /var/services/ mkdir dyndns ls Le nouveau rĂ©pertoire "dyndns" devrait apparaitre. Imaginons que le script gandip.py ait Ă©tĂ© placĂ© dans le volume1 utilisateur, la copie va avoir la forme suivante : cp /volume1/gandip.py /var/services/dyndns/ cd /var/services/dyndns/ ls Le fichier script "gandip.py" devrait apparaitre. Saisir deux fois la commande « exit » pour sortir de PuTTY. Nota : Pour des raisons de sĂ©curitĂ©, pensez Ă dĂ©sactiver SSH dans le Panneau de configuration NAS -> Terminal & SNMP -> Terminal =========================================================================================================================== Le script:  (code source original: https://github.com/ArnaudLevaufre/GandIP/blob/69973607bf0ce2836c45eeee4f4494344ddea57d/gandip.py )  Jâai procĂ©dĂ© Ă quelques modifications du script original : lignes 50 et 65: request = urllib.request.Request(f"{self.url}/domains/{fqdn}/records/{name}/{rtype}/" devient: request = urllib.request.Request("{}/domains/{}/records/{}/{}".format(self.url,fqdn,name,rtype)) pour ĂȘtre utilisable sous Python 3.5 ligne 30, ajout de: import time ligne 96, ajout de: time.sleep(120) pour introduire un dĂ©calage de temps du planificateur de tĂąches DSM et Ă©viter des "HTTP Error 504: Gateway Timeout" chez Gandi.net. Le script nĂ©cessite de lui fournir trois arguments lors de l'appel (voir capture n°3 ci-dessous): gandip.py Gandi API Token Nom de Domaine "@" Gandi API Token (API Key) permettant d'autoriser la requĂȘte, Nom de Domaine, le domaine intĂ©ressĂ©, "@" permettant de pointer l'enregistrement DNS. Le code: """ Copyright (c) 2017 Arnaud Levaufre <arnaud@levaufre.name> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import argparse import json import logging import os import urllib.request import time IPV4_PROVIDER_URL = "https://api.ipify.org" IPV6_PROVIDER_URL = "https://api6.ipify.org" GANDI_API_URL = "https://dns.api.gandi.net/api/v5" LOG_FORMAT = "[%(asctime)s][%(name)s][%(levelname)s] %(message)s" logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) logger = logging.getLogger(__name__) class GandiAPI: def __init__(self, url, key): self.url = url self.key = key def get_domain_record_by_name(self, fqdn, name, rtype="A"): try: request = urllib.request.Request("{}/domains/{}/records/{}/{}".format(self.url,fqdn,name,rtype)) request.add_header("X-Api-Key", self.key) with urllib.request.urlopen(request) as response: return json.loads(response.read().decode()) except urllib.error.HTTPError: return None def update_records(self, fqdn, record_names, current_ip, ttl=10800, rtype="A"): for name in record_names: record = self.get_domain_record_by_name(fqdn, name, rtype=rtype) if record is not None and current_ip in record['rrset_values']: logger.info("Record %s for %s.%s is up to date.",rtype, name, fqdn) else: request = urllib.request.Request( "{}/domains/{}/records/{}/{}".format(self.url,fqdn,name,rtype), method="POST" if record is None else "PUT", headers={"Content-Type": "application/json", "X-Api-Key": self.key}, data=json.dumps({"rrset_ttl": ttl,"rrset_values": [current_ip],}).encode() ) with urllib.request.urlopen(request) as response: logger.debug(json.loads(response.read().decode())) logger.info("Record %s for %s.%s is set to %s.",rtype, name, fqdn, current_ip) def get_current_ip(provider_url): with urllib.request.urlopen(provider_url) as response: return response.read().decode() def main(): parser = argparse.ArgumentParser( description= """" Keep your gandi DNS records up to date with your current IP """ ) parser.add_argument('key', type=str, help="Gandi API key or path to a file containing the key.") parser.add_argument('zone', type=str, help="Zone to update") parser.add_argument('record', type=str, nargs='+', help="Records to update") parser.add_argument("--ttl", type=int, default=10800, help="Set a custom ttl (in second)") parser.add_argument("--noipv4", action="store_true", help="Do not set 'A' records to current ipv4") parser.add_argument("--noipv6", action="store_true", help="Do not set 'AAAA' records to current ipv6") args = parser.parse_args() time.sleep(120) logger.info('Gandi record update started.') if os.path.isfile(args.key): with open(args.key) as fle: gandi_api_key = fle.read().strip() else: gandi_api_key = args.key api = GandiAPI(GANDI_API_URL, gandi_api_key) if not args.noipv4: current_ipv4 = get_current_ip(IPV4_PROVIDER_URL) api.update_records(args.zone, args.record, current_ipv4, ttl=args.ttl) if not args.noipv6: current_ipv6 = get_current_ip(IPV6_PROVIDER_URL) api.update_records(args.zone, args.record, current_ipv6, ttl=args.ttl, rtype="AAAA") if __name__ == "__main__": main()  =========================================================================================================================== Activation du script: L' activation est obtenue en crĂ©ant une nouvelle tĂąche dans le Planificateur de TĂąches de DSM -> "Script dĂ©fini par l'utilisateur" (voir les diffĂ©rentes captures dâĂ©cran ci-dessous). Capture n°1  Les appels du script se font toutes les cinq minutes. Capture n°2  Le champ "script dĂ©fini par l'utilisateur" prĂ©cise la localisation de Python 3 au sein des paquets DSM (/usr/local/bin/...) ainsi que celle du script "gandip.py" (/var/services/dyndns/...) suivi de ses arguments (Attention de bien laisser un espace entre chaque). Capture n°3  Dans un premier temps, je vous invite Ă surveiller la bonne exĂ©cution de ce script en indiquant une adresse mail qui vous permettra de rĂ©cupĂ©rer d'Ă©ventuelles erreurs. Pour ma part, je l'active en permanence. Ce script fonctionne sur mon DS718+ depuis plus de deux mois sans le moindre problĂšme. Les enregistrements DNS sont automatiquement actualisĂ©s Ă chaque changement de l'adresse IP de mon FAI (orange). gandip.py ModifiĂ© le 11 novembre 2019 par marmottin 0 Citer
pews PostĂ©(e) le 21 octobre 2019 PostĂ©(e) le 21 octobre 2019 Bonjour Marmottin, Je viens de tester ton script et j'obtiens ce mail :  Cher utilisateur, Le planificateur de tĂąches Ă terminĂ© une tĂąche planifiĂ©e. TĂąche : Dyndns Gandi V5 Heure de dĂ©but : Mon, 21 Oct 2019 21:05:02 GMT Heure dâarrĂȘt : Mon, 21 Oct 2019 21:07:05 GMT Ătat actuel : 1 (Interrompu) Sortie standard/erreur : [2019-10-21 21:07:02,929][__main__][INFO] Gandi record update started. [2019-10-21 21:07:03,663][__main__][INFO] Record A for @.toto.fr is up to date. Traceback (most recent call last):  File "/var/services/dyndns/gandip.py", line 117, in <module>   main()  File "/var/services/dyndns/gandip.py", line 113, in main   api.update_records(args.zone, args.record, current_ipv6, ttl=args.ttl, rtype="AAAA")  File "/var/services/dyndns/gandip.py", line 70, in update_records   with urllib.request.urlopen(request) as response:  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 162, in urlopen   return opener.open(url, data, timeout)  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 471, in open   response = meth(req, response)  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 581, in http_response   'http', request, response, code, msg, hdrs)  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 509, in error   return self._call_chain(*args)  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 443, in _call_chain   result = func(*args)  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 589, in http_error_default   raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 400: Bad Request  Comment dois je lâinterprĂ©ter ? car je vois une erreur sur la fin. Merci de ton aide. 0 Citer
marmottin PostĂ©(e) le 22 octobre 2019 Auteur PostĂ©(e) le 22 octobre 2019 (modifiĂ©) Bonjours pews, La rĂ©ponse est dans la derniĂšre ligne: HTTP 400 Bad Request qui indique que le serveur ne comprend pas la requĂȘte en raison d'une syntaxe invalide. Je pense qu'un (ou plusieurs) argument(s) fourni(s) sont erronĂ©(s) (toto.fr ?). Le script exige trois arguments lors de l'appel : Gandi API Token Nom de Domaine "@" 1- Gandi API Token (ou API key) correspondant au Nom de domaine (Ă rĂ©cupĂ©rer chez Gandi.net via ce lien: https://account.gandi.net/fr/ -> sĂ©curitĂ©) 2- Nom de Domaine, le domaine dĂ©clarĂ© et enregistrĂ© chez Gandi.net. 3- "@" permettant de pointer l'enregistrement DNS (guillemets obligatoires). Les trois arguments doivent ĂȘtre dĂ©clarĂ©s dans l'ordre indiquĂ©, separĂ©s d'un espace. ModifiĂ© le 22 octobre 2019 par marmottin 0 Citer
pews PostĂ©(e) le 22 octobre 2019 PostĂ©(e) le 22 octobre 2019 Bonjour Marmottin, Je ne pense pas m'ĂȘtre trompĂ© car je passe en argument ma API key et le nom de domaine que j'ai remplacĂ© par toto.fr đ /usr/local/bin/python3 /var/services/dyndns/gandip.py xxxxxxxxxxxxxxxxxxxxxx toto.fr "@" Je vais essayer de regĂ©nĂ©rer une clĂ© API.  Bon sans succĂšs avec ma nouvelle API key... Pourtant mon enregistrement @ dans le DNS existe bien. Je dois louper quelque chose... 0 Citer
marmottin Posté(e) le 22 octobre 2019 Auteur Posté(e) le 22 octobre 2019 (modifié) Vos enregistrement DNS chez Gandi se présentent-ils sous cette forme?: et en particulier le champ "AAAA" correspondant à l'IP v6?  Modifié le 22 octobre 2019 par marmottin 0 Citer
pews Posté(e) le 22 octobre 2019 Posté(e) le 22 octobre 2019 Je n'ai pas l'enregistrement AAAA 0 Citer
marmottin PostĂ©(e) le 22 octobre 2019 Auteur PostĂ©(e) le 22 octobre 2019 Il faut alors l'ajouter (mĂȘme s'il ne sert pas dans l'immĂ©diat) via le bouton "AJOUTER" Dans votre message d'erreur, le champ "A" est indiquĂ© comme "mis Ă jour" puis l'erreur est dĂ©clenchĂ©e. C'est peut-ĂȘtre cette absence de champ qui est Ă l'origine du problĂšme... 0 Citer
pews Posté(e) le 22 octobre 2019 Posté(e) le 22 octobre 2019 J'ai rajouté dans le DNS le champs AAAA avec une IP V6 au pif mais pas mieux :  File "/volume1/@appstore/py3k/usr/local/lib/python3.5/urllib/request.py", line 589, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 400: Bad Request 0 Citer
marmottin Posté(e) le 22 octobre 2019 Auteur Posté(e) le 22 octobre 2019 (modifié) Je vous propose d'ajouter un argument supplémentaire interdisant la mise à jour de l'IP v6: /var/services/dyndns/gandip.py xxxxxxxxxxxxxxxxxxxxxx toto.fr "@" "--noipv6" Au fait, votre FAI vous fournit-il une adresse en IP v6? Modifié le 22 octobre 2019 par marmottin 0 Citer
pews PostĂ©(e) le 22 octobre 2019 PostĂ©(e) le 22 octobre 2019 Aucune erreur en rajoutant le noipv6 ! Pour info, je n'ai pas activer l'option cotĂ© FAI pour fournir une IPV6. Merci beaucoup pour ton aide. Je n'aurais jamais trouvĂ© sans toi đ 0 Citer
marmottin PostĂ©(e) le 22 octobre 2019 Auteur PostĂ©(e) le 22 octobre 2019 Et un client de satisfait!!! đ€Łđ€Łđ€Ł Bonne soirĂ©e đ 1 Citer
pews PostĂ©(e) le 22 octobre 2019 PostĂ©(e) le 22 octobre 2019 Ah oui đ ca faisait un moment que je me penchais sur ce sujet et j'avais jusque la testĂ© plusieurs scripts trouvĂ©s sur Internet sans succĂšs. Bonne soirĂ©e ! 0 Citer
Deadbone Posté(e) le 29 octobre 2019 Posté(e) le 29 octobre 2019 Hello, Merci bcp pour ce script (perso, je l'ai fait sans passer par un shell, juste mis via l'interface le script avec mes autres scripts) J'avais bataillé pour configurer avec l'interface DDNS du syno, mais sans succÚs Bref, encore merci =) 0 Citer
marmottin PostĂ©(e) le 29 octobre 2019 Auteur PostĂ©(e) le 29 octobre 2019 Merci pour le retour đ 0 Citer
Jojo (BE) Posté(e) le 29 octobre 2019 Posté(e) le 29 octobre 2019 question qui peut paraitre innocente : Quel avantage y a-t-il d'avoir un nid chez Gandy plutÎt que chez OVH, qui gÚre automatiquement les changement d'IP de to n FAI (vu-ia ton NAS) ? 0 Citer
marmottin Posté(e) le 30 octobre 2019 Auteur Posté(e) le 30 octobre 2019 (modifié) Ma réponse sera courte: le support technique et commercial. J'ai eu une trÚs mauvaise expérience avec OVH il y a quelques années (HUBIC) et je me suis juré de ne plus jamais utiliser leurs services. Modifié le 30 octobre 2019 par marmottin 0 Citer
Jojo (BE) PostĂ©(e) le 30 octobre 2019 PostĂ©(e) le 30 octobre 2019 OK, merci pour l'info. Le jour oĂč j'ai un soucis, je saurai oĂč aller 0 Citer
PPJP Posté(e) le 4 novembre 2019 Posté(e) le 4 novembre 2019 Bonjour, Deux remarques mineures si vous le permettez. Dans le procédure main: Pourquoi utiliser le nom de variable zone au lieu de fqdn s'agissant du nom de domaine? L'API KEY étant une info "sensible" pourquoi ne pas utiliser l'option, prévue dans le script, de la stocker dans un fichier situé à un emplacement moins accessible, plutÎt que de l'indiquer en clair dans le planificateur de tùches? 0 Citer
marmottin PostĂ©(e) le 4 novembre 2019 Auteur PostĂ©(e) le 4 novembre 2019 (modifiĂ©) Bonsoir,       En prĂ©ambule, je tiens Ă prĂ©ciser que je ne suis pas le concepteur de ce script et que mes compĂ©tences en rĂ©seau sont limitĂ©es. Il est vrai quâil serait prĂ©fĂ©rable de passer lâargument « API Key » via un fichier plutĂŽt quâen clair comme indiquer dans le Tuto (et comme le permet le script). Jâai voulu faire simple afin de rendre la comprĂ©hension aisĂ©e et dâarriver facilement au rĂ©sultat attendu. Libre Ă chacun dâutiliser toutes les possibilitĂ©s de ce script. Concernant le FQDN (ou nom de domaine pleinement qualifiĂ©), je ne peux vous communiquer que ce que lâauteur du script mâavez indiquĂ© lors d'une prise de contact: « Dans le cas oĂč vous voulez faire pointer le nom de domaine exemple.com sur votre adresse vous devez utiliser la valeur "@" en valeur de record. Pour faire pointer tous les sous-domaines, vous pouvez utiliser la valeur "*" NB : (attention Ă bien entourer * et @ de guillemets) ». LĂ aussi, jâai fait une impasse afin de faciliter la mise en Ćuvre. ModifiĂ© le 4 novembre 2019 par marmottin 0 Citer
PPJP PostĂ©(e) le 6 novembre 2019 PostĂ©(e) le 6 novembre 2019 Bonjour, Il ne sâagissait que de remarques sur la forme. Il n'y a aucune consĂ©quence sur le dĂ©roulĂ© du script. Je n"ai pas abordĂ© le sujet des paramĂštres @ et * (d'ailleurs attention avec * ) C'Ă©tait juste que je mâĂ©tonnais que le nom de domaine soit contenu dans une variable fdqn dans la partie classe et zone dans la partie main. Si certains, en plus d'utiliser le script, veulent le comprendre, tout en ayant peu de connaissances des scripts, cela ne leur facilitera pas la tĂąche. JâarrĂȘte ici mon intrusion sur ce tutoriel. PS: Ce script n'a pas d"emplacement impĂ©ratif, il pouvait rester sur le volume 1. Pour faire simple, vous auriez ainsi pu Ă©viter la partie SSH, qui n'est pas apprĂ©ciĂ©e par tous. 0 Citer
marmottin PostĂ©(e) le 6 novembre 2019 Auteur PostĂ©(e) le 6 novembre 2019 (modifiĂ©) Merci pour ces remarques fort pertinentes. Sur un sujet aussi abscons, toute observation est apprĂ©ciĂ©e pour le « bĂ©otien » que je suis. Je vous invite mĂȘme Ă rĂ©diger un complĂ©ment dâinformations sur le sujet afin dâamĂ©liorer les connaissances des utilisateurs de ce Tuto đ. ModifiĂ© le 6 novembre 2019 par marmottin 0 Citer
RedAlan Posté(e) le 19 juin 2020 Posté(e) le 19 juin 2020 (modifié) Bonjour, Etant une buse en DNS, je sollicite votre aide, est-il possible en utilisant ce script de ne mettre a jour q'un sous domaine (cloud.xxxxxxxxx.com), tout en laissant le domaine principale pointer sur le serveur web xxxxxxxxx.com et www.xxxxxxxxx.com hébergé chez ovh? Merci de votre aide  Modifié le 19 juin 2020 par RedAlan 0 Citer
nithou PostĂ©(e) le 27 octobre 2022 PostĂ©(e) le 27 octobre 2022 Je suis un peu perdu, le script marchait Ă la perfection chez moi jusqu'Ă il y a un mois, mais depuis il met une erreur : "File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'api.ipify.org'. (_ssl.c:1131)" J'ai renouvelĂ© les certificats de mon cĂŽtĂ© mais rien n'y fait đ 0 Citer
Messages recommandés
Rejoindre la conversation
Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.