MikroTik и CloudFlare: Динамический IP для домена

MikroTik и CloudFlare: Динамический IP для домена

Нашёл скрипт реализации динамической смены IP адреса из #RouterOS напрямую в панели управления #CloudFlare при помощи API. Где нашёл скрипт уже не помню, вроде бы на страницах официального форума #MikroTik.

Скрипт я немного переделал, удалил лишние переменные, некоторые переопределил, подправил области видимости переменных, обновил метод авторизации скрипта на серверах #CloudFlare. Вроде работает.

Сам скрипт нужно настроить под себя, прописав в нём значения переменных. Некоторые значений можно узнать из панели управления доменом в #CloudFlare, но для получения значения переменной cfDnsID необходимо выполнит немного телодвижений. Об этом ниже.

Работа CloudFlare API

Без токена - никак.

Создание токена

Для того, чтобы начать работать с #CloudFlare API, нам нужно создать специальный токен:

  1. Зайти в панель управления токенами.
  2. Нажать кнопку Create Token.
  3. На странице выбора шаблонов - выбрать шаблон Edit zone DNS.
  4. В разделе Zone Resources можно выбрать область доступа токена к зонам (доменам). Можно указать конкретную зону (Specific zone) или выбрать все зоны (All zones).
  5. Всё, нажимаем кнопку Continue to summary и перемещаемся на следующую станицу…

Проверка токена

По окончании создания токена, #CloudFlare переместит нас на страницу проверки токена. На этой странице будут наш созданный токен (его необходимо сохранить) и команда, которой при помощи утилиты curl можно проверить корректность токена:

1
2
3
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type:application/json" | python3 -mjson.tool

При выполнении, команда вернёт следующий результат:

Терминал
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" -H "Authorization: Bearer <...>" -H "Content-Type: application/json" | python3 -mjson.tool

{
    "result": {
        "id": "<...>",
        "status": "active"
    },
    "success": true,
    "errors": [],
    "messages": [
        {
            "code": 10000,
            "message": "This API Token is valid and active",
            "type": null
        }
    ]
}

По сообщению “This API Token is valid and active” понятно, что токен корректный и работает.

Получение ID ресурсной записи домена

Когда у нас есть токен, можно полноценно работать с #CloudFlare API. Нам нужно получить ID ресурсной записи домена. Получать будем следующей командой:

1
2
3
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" | python3 -mjson.tool

Обратите внимание на следующие заглушки в команде:

  • ZONE_ID - ID домена. Находится в панели оправления доменом на главной странице в поле Zone ID.
  • TOKEN - токен для доступа к #CloudFlare API.

Сформировав правильную команду с корректными данными и выполнив её, команда вернёт результат в формате #JSON. Результат будет содержать набор всех ресурсных записей конкретного домена. У меня это выглядит так:

Терминал
 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
curl -X GET "https://api.cloudflare.com/client/v4/zones/<...>/dns_records" -H "Authorization: Bearer <...>" -H "Content-Type: application/json" | python3 -mjson.tool

{
    "result": [
        {
            "id": "gJDSG5la4IWNOEVn6K2PHyope8Q9YhzC",
            "zone_id": "<...>",
            "zone_name": "example.com",
            "name": "example.com",
            "type": "A",
            "content": "192.168.10.232",
            "proxiable": true,
            "proxied": true,
            "ttl": 1,
            "locked": false,
            "meta": {
                "auto_added": false,
                "managed_by_apps": false,
                "managed_by_argo_tunnel": false,
                "source": "primary"
            },
            "created_on": "2020-02-23T21:26:27.56227Z",
            "modified_on": "2020-02-23T21:26:27.56227Z"
        }
    ],
    "success": true,
    "errors": [],
    "messages": [],
    "result_info": {
        "page": 1,
        "per_page": 20,
        "count": 7,
        "total_count": 7,
        "total_pages": 1
    }
}

Как видим, команда вернула нам результат с массивом result. В этом массиве находятся все ресурсные записи нашего домена. Каждая ресурсная запись содержит поля id и content:

  • id - ID ресурсной записи. Очень важное поле, как раз его значение необходимо записать в переменную cfDnsID скрипта.
  • content - содержимое ресурсной записи.

Нам необходимы только записи с типом A. Обычно в записях с типом A хранятся IP адреса серверов, к которым привязан домен. У записей с типом A в поле content находится IP адрес, который должен изменить наш #MikroTik при обращении к #CloudFlare API.

Скрипт

cf.ddns.rsc
 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
# Mikrotik RouterOS script for CloudFlare DDNS
#
# @package    RouterOS
# @author     Kai Kimera <mail@kai.kim>
# @copyright  2023 Library Online
# @license    MIT
# @version    0.0.1
# @link       https://lib.onl
# -------------------------------------------------------------------------------------------------------------------- #

# RouterOS: WAN interface name.
:local rosWanInterface "ether1"

# RouterOS: Enables trust chain validation from local certificate store.
# 'no'  | Disable certificate check.
# 'yes' | Enable certificate check.
:local rosCheckCert "no"

# CloudFlare: API token.
:local cfToken ""

# CloudFlare: Domain.
:local cfDomain "example.com"

# CloudFlare: Zone ID.
:local cfZoneID ""

# CloudFlare: DNS ID.
:local cfDnsID ""

# CloudFlare: Domain record type.
:local cfRecordType "A"

# CloudFlare: Debug mode.
# 0 | Disable debug mode.
# 1 | Enable debug mode.
:local cfDebug 0

# -------------------------------------------------------------------------------------------------------------------- #

# IP on WAN interface.
:local srcIP

# IP on CloudFlare domain.
:local dstIP

# Get RouterOS WAN IP.
:set srcIP [/ip address get [/ip address find interface=$rosWanInterface ] address]
:set srcIP [:pick $srcIP 0 [:find $srcIP "/"]]

# Get CloudFlare domain IP.
:set dstIP [:resolve $cfDomain]

# Build CloudFlare API (v4).
:local cfAPI "https://api.cloudflare.com/client/v4/zones/"
:set cfAPI ($cfAPI . "$cfZoneID/dns_records/$cfDnsID")
:local cfAPIHeader "Authorization: Bearer $cfToken, Content-Type: application/json"
:local cfAPIData "{\"type\":\"$cfRecordType\",\"name\":\"$cfDomain\",\"content\":\"$srcIP\"}"

# Write debug info to log.
:if ($cfDebug) do={
  :log info ("CloudFlare: Domain = $cfDomain")
  :log info ("CloudFlare: Domain IP (dstIP) = $dstIP")
  :log info ("CloudFlare: WAN IP (srcIP) = $srcIP")
  :log info ("CloudFlare: CloudFlare API (cfAPI) = $cfAPI&content=$srcIP")
}

# Compare and update CF if necessary.
:if ($dstIP != $srcIP) do={
  :log info ("CloudFlare: Updating $cfDomain, setting $srcIP = $cfDomain")
  /tool fetch \
    mode=https \
    http-method=put \
    http-header-field="$cfAPIHeader" \
    http-data="$cfAPIData" url="$cfAPI" \
    check-certificate=$rosCheckCert \
    output=user as-value
  /ip dns cache flush
}

Настройка

Алгоритм настройки довольно прост:

  1. Получаем токен для работы с #CloudFlare API.
  2. При помощи специальной команды узнаём значение поля id ресурсной записи с типом A.
  3. Это значение вписываем в переменную cfDnsID скрипта.
  4. Остальные требуемые значения для переменных уже доступны без каких-либо телодвижений.

Переменные

Опишу переменные и что они из себя представляют:

  • rosWanInterface - имя интерфейса WAN в #RouterOS.
  • rosCheckCert - включение / отключение проверки цепочки сертификации при запросе к #CloudFlare API. Для корректной работы этой функции необходимо, чтобы в репозитории сертификатов #RouterOS присутствовали корневые сертификаты центров сертификации. Про импортирование сертификатов написано в заметке MikroTik: Добавление корневых сертификатов в RouterOS.
  • cfToken - токен, полученный в панели управления токенами.
  • cfDomain - название домена, для которого необходимо динамически менять IP адрес.
  • cfZoneID - ID домена. Находится в панели управления доменом на главной странице в поле Zone ID.
  • cfDnsID - ID ресурсной записи домена. Для получения значения переменной, необходимо выполнить запрос к #CloudFlare API.
  • cfRecordType - тип ресурсной записи домена. Обычно это A. Менять нет необходимости.
  • cfDebug - включение / отключение отображения технической информации в логе #RouterOS.

Рекомендую настраивать скрипт в редакторе с подсветкой синтаксиса, чтобы не ошибиться и не задеть какую-либо кавычку.

Установка

После настройки скрипта, его нужно добавить в репозиторий скриптов #RouterOS. Находится репозиторий в System / Scripts. При добавлении скрипта, необходимо выбрать политики read, write, test, policy.

Планировщик

Скрипт должен переодически запускаться для проверки и синхронизации IP адресов сервера и домена. В этом поможет планировщик #RouterOS. Заходим в System / Scheduler и создаём задачу с политиками read, write, test, policy. В поле On Event вписываем точное название скрипта, ранее добавленного в репозиторий #RouterOS.

Проверка

Проверить работу скрипта можно в репозитории по адресу System / Scripts. Выделив скрипт и нажав на кнопку Run, смотрим изменился ли IP адрес у домена в панели управления #CloudFlare.

2023-10-19

  • Статья переписана под новые реалии работы с CloudFlare API.
  • В статью добавлен код скрипта.
  • Скрипт немного переделан, в частности, изменён процесс авторизации CloudFlare API.
Категории
Авторы
Смотрите также
Мета
Лицензия
ID файла
UUID
Системный путь
Тип
Статистика
Количество слов
Время чтения
мин.