Ostatnio jeden z „komentatorów” zainspirował mnie do nakręcenia wideo do wpisu dotyczącego zmiany duetu Apache2 + MOD-PHP na Apache2 + PHP-FPM. Tym razem jego „boje z no-ip.com” skłoniły mnie do przygotowania tego wpisu – czyli jak wykorzystać Cloudflare jako klienta DDNS (DNS dla dynamicznego IP).

Spis treści w artykule

Cloudflare jako Dynamic DNS (DDNS)

Wprawdzie na co dzień Cloudflare wykorzystuje jako „frontend” dla stron internetowych, to tym razem użyjemy tego serwisu w formie dynamicznego DNSa – korzystając z faktu, że właściwie każda zmiana w DNSach w ramach Cloudflare odbywa się w czasie rzeczywistym.

Dynamiczny adres IP, DDNS i własna domena

Gdy mamy publiczny i stały adres IP – sprawa jest prosta, w kilka(naście) minut możemy postawić u siebie serwer dostępny „z internetu”. Sytuacja trochę się komplikuje gdy wprawdzie mamy publiczny adres IP, ale jest on zmienny – jak np. w przypadku Neostrady.

W takiej sytuacji nadal możemy uzyskać „z internetu” dostęp do swojego serwera pod stałym adresem (domena/subdomena) korzystając z popularnych serwisów oferujących usługi pozwalające pod konkretną domenę/subdomenę podstawiać dynamicznie aktualny adres IP.

Własna domena

Często są to usługi bezpłatne, choć w takim wariancie nie możemy np. podpiąć własnej domeny – co dla niektórych z Was może być sporym minusem/problemem. W takim przypadku możecie przejść na konto „premium”, lub skorzystać z metody którą za chwilę przedstawię…

Cloudflare jako DNS z dynamicznie aktualizowanym adresem IP

Wykorzystanie Cloudflare w formie DDNS ma sporo zalet, m.in.:

  • Usługa w pełni bezpłatna (choć są pakiety płatne)
  • CDN (sieć serwerów serwujących kontent)
  • Dodatkowa ochrona (adresu IP, jak i serwera)
  • Dowolna ilość własnych domen (kierujących na serwer, nawet z dynamicznym IP)
  • Pełne wykorzystanie możliwości domeny (obsługa nie tylko rekordu A, ale i pozostałych)

To rozwiązanie ma też jedną – potencjalną – wadę, bo o ile:

  • Na komputerze domowym (jeśli ma robić jako serwer) możecie zainstalować klienta DDNS
  • Większość routerów posiada obsługę kilku serwisów DDNS

To w przypadku rozwiązania opartego na Cloudflare trzeba będzie skorzystać z dedykowanego skryptu – ale w końcu jest to przykład oparty na serwerze działającym na Raspberry Pi, więc i wymienione minusy są nam nie straszne. Nas nie dotyczą… ;-)

Aby przedstawione tu rozwiązanie działało domena musi być zarejestrowana, dodana do usługi Cloudflare i odpowiednio skonfigurowana (ustawione adresy serwerów DNS na podane przez Cloudflare podczas dodawania domeny).

W przypadku świeżo zarejestrowanych domen czasem trzeba poczekać 10-15 minut, aż odświeżą/zaktualizują się dane w rejestrze operatora danej domeny zanim będzie można dodać domenę do konta (komunikat o niezarejestrowanej domenie).

Należy też pamiętać, że zależnie m.in. od rejestratora domeny, czy ISP (dostawca internetu, u którego często znajdują się przypisane do łącza internetowego DNSy) zmiana adresów serwerów DNSów dla domeny na te od Cloudflare może zająć nawet 24-48 godzin.

Cloudflare API

By móc płynnie zmieniać IP dla rekordu A domeny skorzystamy z API Cloudflare, czyli będzie potrzebny klucza API – znajdziecie go w ustawieniach swojego konta:

cloudflare_account_api

Oprócz tego potrzebny będzie adres e-mail przypisany do konta – ale ten na pewno znacie… ;-)

CRON + cURL

Wykorzystamy tu też systemowe harmonogram zadań (CRON) i cURL – najprawdopodobniej macie w systemie, ale na wszelki wypadek:

sudo apt-get install cron
sudo apt-get install curl

Jeszcze tylko…

Zakładam, że serwer WWW lub np. VPN z którego chcecie korzystać za pośrednictwem domeny już jest gotowy do pracy. Oczywiście potrzebne będzie konto na Cloudflare i podpięta do niego domena – ale to chyba oczywiste… ;-)

Tyle teorii czy przygotowań, bierzemy się za „mięcho”, czyli skrypt:

Skrypt Cloudflare DDNS

Skrypt który przygotowałem może wydawać się rozbudowany, ale dzięki temu cała obsługa sprowadza się do modyfikacji kilku parametrów – a „zainteresowani” zawsze mogą wyciągnąć z niego odpowiednie fragmenty…


#!/bin/bash

# --------------------------------------------------
#
# ----- ---- --- Cloudflare DDNS --- ---- -----
#
# Code from: https://Webinsider.pl/cloudflare-ddns
#
# Cloudflare API DOC:
# https://www.cloudflare.com/docs/client-api.html
#
# --------------------------------------------------

IP_CONTROL_LAST=0 # 1 - check the latest IP (file $IP_LOG), 0 - always sends the new IP

# Use Your fav IP chceck URL:
IP_CHECK_URL=
# e.g.:
# https://cdn.pryc.eu/add/myip.php

if [ -z "$IP_CHECK_URL" ]
then
	echo "IP_CHECK_URL is empty!"
	exit 0
else
	IP_NOW=`wget -O - -q $IP_CHECK_URL` # Get current IP, if IP_CONTROL_LAST=1
fi

IP_LOG=/boot/last-ip.txt # Last IP LOG file

if [ ! -f $IP_LOG ] && [ "$IP_CONTROL_LAST" = "1" ]
then
    sudo touch $IP_LOG
fi

if [ $IP_LOG ] && [ "$IP_CONTROL_LAST" = "1" ]
then
    IP_LAST=$(cat $IP_LOG)
fi

CF_API_KEY= #insert here Your API key
CF_EMAIL= #insert here Your e-mail

DOMAIN= #insert here domain name
DOMAIN_RECORD_NAME= #insert here domain or subdomain name
CF_DOMAIN_REC_ID= #insert here record ID # First time read it - see below

CF_DOMAIN_READ_REC_ID=1 # 1 - ONLY read domain REC_ID, 0 - controls (changing) IP

CF_PROXY4RECORD=1 # Status of Cloudflare Proxy, 1 = orange cloud, 0 = grey cloud. 

if [ -z "$CF_API_KEY" ] || [ -z "$CF_EMAIL" ] || [ -z "$DOMAIN" ] || [ -z "$DOMAIN_RECORD_NAME" ]
then
	echo "Check script config!"
	exit 0
fi

if [ "CF_DOMAIN_READ_REC_ID" = "0" ] && [ -z "$CF_DOMAIN_REC_ID" ]
then
	echo "Check CF_DOMAIN_REC_ID"
	exit 0
fi

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

function f_cf_api_rec_load_all() {
	curl https://www.cloudflare.com/api_json.html \
		-d 'a=rec_load_all' \
		-d 'tkn='$CF_API_KEY \
		-d 'email='$CF_EMAIL \
		-d 'z='$DOMAIN
}

function f_cf_api_rec_edit() {
	curl https://www.cloudflare.com/api_json.html \
		-d 'a=rec_edit' \
		-d 'tkn='$CF_API_KEY \
		-d 'email'=$CF_EMAIL \
		-d 'z='$DOMAIN \
		-d 'id='$CF_DOMAIN_REC_ID \
		-d 'type=A' \
		-d 'name='$DOMAIN_RECORD_NAME \
		-d 'content='$IP_NOW \
		-d 'service_mode='$CF_PROXY4RECORD \
		-d 'ttl=1'
}

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

if [ "$CF_DOMAIN_READ_REC_ID" = "1" ]
then
	echo "Read CF DOMAIN REC_ID..."
	f_cf_api_rec_load_all
	exit 0
fi

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

if [ "$IP_CONTROL_LAST" = "1" ]
then
	if [ "$IP_NOW" != "$IP_LAST" ]
	then
		echo "New IP - changing..."
		echo $IP_NOW | sudo tee $IP_LOG > /dev/null
		f_cf_api_rec_edit
	else
		echo "IP is OK"
	fi
else
	echo "Changing IP..."
	echo $IP_NOW | sudo tee $IP_LOG > /dev/null
	f_cf_api_rec_edit
fi

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

exit 0

Skrypt możecie skopiować z „listingu” powyżej, lub – chyba bezpieczniej – pobrać z tego adresu. Ew możecie pobrać do bezpośrednio na serwer za pomocą komendy:

wget https://webinsider.pl/add/download/?link=cloudflare_ddns -O /ścieżka/do/zapisania/cloudflare_ddns

Konfiguracja skryptu

Konfiguracja skryptu sprowadza się do zmiany wartości kilku zmiennych:

  • IP_CONTROL_LAST – Gdy zmienna ma wartość „1” to po uruchomieniu skryptu następuje połączenie z serwerem w celu sprawdzenia aktualnego adresu IP (IP_NOW), po czym następuje jego porównanie z wcześniej zapisanym (IP_LAST) i dopiero jeśli te 2 wartości są różne – następuje wysłanie nowego adresu (IP_NOW) do Cloudflare. Gdy zmienna ma wartość „0” – adres IP jest wysyłany do Cloudflare przy każdym uruchomieniu skryptu, niezależnie od tego czy od ostatniego uruchomienia został zmieniony.
  • IP_CHECK_URL – Tu należy podać adres skryptu/strony wyświetlającej adres IP. W skrypcie są podane przykładowe, ale jeśli macie taką możliwość, to warto użyć własnego pliku. Więcej na ten temat za chwilę…
  • IP_NOW – Pobranie „z internetu” aktualnego adresu IP. W skrypcie są podane 2 przykładowe strony z których można pobrać adres IP w „czystej postaci” – możecie też podstawić tu własny adres…
  • IP_LOG – Adres (ścieżka) pliku służącego do zapisywania ostatniego adresu IP. Ma szczególne znaczenia gdy zmienna IP_CONTROL_LAST  ma wartość „1”.
  • IP_LAST – Adres IP pobierany z pliku IP_LOG
  • CF_API_KEY – Klucz API Waszego konta w Cloudflare
  • CF_EMAIL – E-mail przypisany do Waszego konta w Cloudflare
  • DOMAIN – Domena na której skrypt będzie pracował. W przypadku korzystania z subdomen w tym miejscu wpisujecie domenę, nie subdomenę.
  • DOMAIN_RECORD_NAME – Nazwa rekordu. W przypadku modyfikacji rekordu A dla domeny będzie to nazwa domeny, w przypadku modyfikowania rekordu A dla subdomeny będzie to nazwa subdomeny.
  • CF_DOMAIN_REC_ID – Jedna z ważniejszych zmiennych, dzięki której skrypt i Cloudflare wiedzą który rekord chcemy zmodyfikować. Więcej na ten temat za chwilę…
  • CF_DOMAIN_READ_REC_ID – Ustawiamy wartość na „1” gdy chcemy uzyskać CF_DOMAIN_REC_ID. W każdym innym przypadku wartość ustawiamy na „0”. Więcej na ten temat za chwilę…
  • CF_PROXY4RECORD – Włączenie (1) lub wyłączenie (0) usługi Cloudflare dla rekordu.

Sprawdzanie aktualnego IP

Wprawdzie możecie skorzystać z adresu podanego w skrypcie:

https://cdn.pryc.eu/add/myip.php

To jeśli macie taką możliwość – warto rozważyć skorzystanie z własnego plik/adresu… Bo zawsze „adres niezależny” może przestać istnieć, czy… A wystarczy na serwerze WWW – oczywiście nie tym z dynamicznym IP na którym działa skrypt – stworzyć plik PHP o takiej zawartości:

<?php
 echo $_SERVER['REMOTE_ADDR'];
?>

I jego adres ustawić dla zmiennej IP_CHECK_URL.

Odczyt ID wybranego rekordu

By odczytać ID rekordu uzupełniamy wszystkie niezbędne dane – oczywiście poza CF_DOMAIN_REC_ID którego jeszcze nie znamy – i ustawiamy wartość „CF_DOMAIN_READ_REC_ID” na „1”.

Następnie zapisujemy i uruchamiamy skrypt.

Jak konfiguracja nie zawiera żadnych błędów zobaczycie wynik podobny do tego:

cloudflare_ddns_api_skrypt01

To wynik dla domeny z tylko 3 rekordami, więc przy bardziej rozbudowanych konfiguracjach DNS będzie tego więcej – ale tylko wygląda to strasznie… ;-)

To co nas interesuje to pozycja „rec_id” występująca tuż przed „rec_hash” i „zone_name” interesującego nas rekordu.

Wartość z „rec_id” wpisujemy jako wartość zmiennej CF_DOMAIN_REC_ID i ustawiamy „CF_DOMAIN_READ_REC_ID” na „0”.

Kilka regułek „kontrolnych”

W skrypcie znalazło się kilka regułek kontrolnych, którym zadaniem jest sprawdzanie, czy wszystkie niezbędne pola zostały odpowiednio wypełnione/skonfigurowane.

Jeśli coś będzie nie tak – dostaniecie stosowną informację…

Działanie skryptu

Oczywiście skrypt trzeba gdzieś zapisać, ja w przypadku Raspberry Pi wszystkie skrypty trzymam w katalogu:

/boot/bin

który jest „podlinkowany” jako „bin” w katalogu każdego użytkownika, dzięki czemu skrypt można wywołać bez potrzeby wpisywania całej ścieżki.

Dodatkową zaletą trzymania skryptów na partycji „boot” jest to, że jest ona w formacie FAT32, a więc można odczytać i modyfikować znajdujące się na niej pliki właściwie na każdym komputerze, a nawet smartfonie (OTG).

Po wywołaniu skonfigurowanego skryptu – zależnie od konfiguracji – sprawdza on (lub nie) adres IP, i gdy trzeba przesyła odpowiednią komendę do Cloudflare w celu jego aktualizacji:

cloudflare_ddns_api_skrypt02

Może się zdarzyć, że system nie będzie chciał uruchomić pliku – w tym celu należy skorzystać z polecenia:

sudo chmod +x /ścieżka/do/pliku/cloudflare_ddns

Harmonogram (CRON)

Oczywiście naszym celem jest automatyzacja całego procesu, dlatego warto skonfigurować systemowy harmonogram (CRON) do wywoływania skryptu o określonej godzinie, czy co określony przedział czasu.

Z racji tego, że już kiedyś pisałem artykuł poświęcony temu tematowi – odsyłam do niego…

(!) Zgłoś błąd na stronie
Potrzebujesz profesjonalnej pomocy? Skontaktuj się z nami!