{"id":71,"date":"2024-12-12T22:52:40","date_gmt":"2024-12-12T21:52:40","guid":{"rendered":"https:\/\/martflom.com\/?p=71"},"modified":"2025-03-14T09:12:19","modified_gmt":"2025-03-14T08:12:19","slug":"ip-publica-fija-sin-coste","status":"publish","type":"post","link":"https:\/\/martflom.com\/index.php\/2024\/12\/12\/ip-publica-fija-sin-coste\/","title":{"rendered":"IP publica fija sin coste"},"content":{"rendered":"\n<p>Buenos d\u00edas,<\/p>\n\n\n\n<p style=\"margin-right:0;margin-left:0\">Hoy traigo una iniciativa inteligente para ahorrar costes a la hora de contratar una IP fija, muchos de los ISL&#8217;s ni si quiera disponen del servicio para facilitarla. Lo cual, puede ser un inconveniente si tenemos un servidos en casa con varios servicios corriendo, ya que al reiniciarse el router se cambiara la ip por otra y tendremos que modificar el DNS a mano.<\/p>\n\n\n\n<p>Para este proyecto trabajare con el proveedor de dominios Ionos, donde aprenderemos a gestionar las API para consultar y modificar los registros. Como entorno de desarrollo utilizare Ubuntu Server, donde instalaremos Python3 y las librer\u00edas necesarias.<\/p>\n\n\n\n<p style=\"margin-top:0;margin-right:0;margin-bottom:0;margin-left:0\"><strong>Instalaci\u00f3n de los paquetes necesarios<\/strong><\/p>\n\n\n\n<p>Empezaremos por instalar Python en nuestro sistema:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>sudo apt update &amp;&amp; apt upgrade -y<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-2 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>sudo apt install python3<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Para poder descargarnos las librer\u00edas necesarias necesitaremos instalar tambi\u00e9n PIP:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-3 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>sudo apt install python3-pip<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Una vez instalado todo comprobamos que la instalaci\u00f3n se hizo correctamente:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-4 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>python3 --version<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-5 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>pip3 --version<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Para no afectar a nuestro sistema, python te da la facilidad de crear un entorno donde poder entrar e instalar todo lo necesario sin riesgo alguno, se crea de la siguiente manera:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-6 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>python -m venv nombre_entorno<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Y, para iniciar el entorno, debemos de poner este comando:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>source nombre_entorno\/bin\/activate<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Una vez dentro del entorno, pasamos a instalar las dependencias necesarias para nuestro c\u00f3digo, en este caso son requests, json, time, os:<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\">\n<pre class=\"wp-block-code\"><code>pip install requests json time os<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:50%\"><\/div>\n<\/div>\n\n\n\n<p>Con esto ya tendr\u00edamos lo necesario.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import requests\nimport json\nimport time\nimport os\n\n# Configuraci\u00f3n\nAPI_KEY = \"tu_prefijo+clave_api\"\nZONE_ID = \"Tu_id_zona\"\nBASE_URL = \"https:\/\/api.hosting.ionos.com\/dns\/v1\/zones\"\nIP_FILE = \"registro_ip_nombredominio.txt\"\nCHECK_INTERVAL = 300  # Intervalo de tiempo para verificar la IP (en segundos)\n\ndef get_public_ip():\n    \"\"\"Obtiene la IP p\u00fablica actual.\"\"\"\n    response = requests.get(\"https:\/\/api.ipify.org?format=json\")\n    response.raise_for_status()\n    return response.json()&#91;\"ip\"]\n\ndef get_dns_records(zone_id, api_key):\n    \"\"\"Consulta los registros de la zona DNS.\"\"\"\n    url = f\"{BASE_URL}\/{zone_id}\"\n    headers = {\"X-API-Key\": api_key}\n    response = requests.get(url, headers=headers)\n    response.raise_for_status()\n    return response.json()&#91;\"records\"]\n\ndef update_dns_record(zone_id, record_id, api_key, new_ip, domain_name):\n    \"\"\"Actualiza un registro A con la nueva IP.\"\"\"\n    url = f\"{BASE_URL}\/{zone_id}\/records\/{record_id}\"\n    headers = {\n        \"X-API-Key\": api_key,\n        \"Content-Type\": \"application\/json\",\n    }\n    data = {\n        \"name\": domain_name,\n        \"type\": \"A\",\n        \"content\": new_ip,\n        \"ttl\": 3600,\n        \"prio\": 0,\n        \"disabled\": False\n    }\n    response = requests.put(url, headers=headers, data=json.dumps(data))\n    response.raise_for_status()\n    return response.json()\n\ndef load_last_ip():\n    \"\"\"Carga la \u00faltima IP registrada desde un archivo.\"\"\"\n    if os.path.exists(IP_FILE):\n        with open(IP_FILE, \"r\") as file:\n            return file.read().strip()\n    return None\n\ndef save_current_ip(ip):\n    \"\"\"Guarda la IP actual en un archivo.\"\"\"\n    with open(IP_FILE, \"w\") as file:\n        file.write(ip)\n\ndef main():\n    while True:\n        try:\n            # Obt\u00e9n la IP p\u00fablica actual\n            new_ip = get_public_ip()\n            print(f\"IP p\u00fablica actual: {new_ip}\")\n\n            # Carga la \u00faltima IP registrada\n            last_ip = load_last_ip()\n            print(f\"\u00daltima IP registrada: {last_ip}\")\n\n            if new_ip != last_ip:\n                print(\"Cambio de IP detectado. Actualizando registros DNS...\")\n\n                # Consulta los registros DNS\n                records = get_dns_records(ZONE_ID, API_KEY)\n                a_records = &#91;record for record in records if record&#91;\"type\"] == \"A\"]\n\n                # Actualiza los registros A con la nueva IP\n                for record in a_records:\n                    record_id = record&#91;\"id\"]\n                    domain_name = record&#91;\"name\"]\n                    print(f\"Actualizando registro {domain_name} (ID: {record_id}) con la IP {new_ip}...\")\n                    result = update_dns_record(ZONE_ID, record_id, API_KEY, new_ip, domain_name)\n                    print(f\"Registro actualizado: {result}\")\n\n                # Guarda la nueva IP en el archivo\n                save_current_ip(new_ip)\n                print(\"Registros DNS actualizados y nueva IP guardada.\")\n            else:\n                print(\"No hay cambios en la IP. Verificando nuevamente en el pr\u00f3ximo intervalo.\")\n\n        except requests.exceptions.RequestException as e:\n            print(f\"Error al realizar la solicitud: {e}\")\n        except Exception as e:\n            print(f\"Error inesperado: {e}\")\n\n        # Espera antes de la pr\u00f3xima verificaci\u00f3n\n        time.sleep(CHECK_INTERVAL)\n\nif __name__ == \"__main__\":\n    main()<\/code><\/pre>\n\n\n\n<p><strong>Creaci\u00f3n de API en ionos<\/strong><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Buenos d\u00edas, Hoy traigo una iniciativa inteligente para ahorrar costes a la hora de contratar una IP fija, muchos de los ISL&#8217;s ni si quiera disponen del servicio para facilitarla. Lo cual, puede ser un inconveniente si tenemos un servidos en casa con varios servicios corriendo, ya que al reiniciarse el router se cambiara la [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":50,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[12,11],"tags":[],"class_list":["post-71","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-novedad","category-proyectos"],"_links":{"self":[{"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/posts\/71","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/comments?post=71"}],"version-history":[{"count":5,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/posts\/71\/revisions"}],"predecessor-version":[{"id":176,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/posts\/71\/revisions\/176"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/media\/50"}],"wp:attachment":[{"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/media?parent=71"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/categories?post=71"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/martflom.com\/index.php\/wp-json\/wp\/v2\/tags?post=71"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}