Cloudflare DDNSをAPIトークン+systemd timerで自動更新する方法

IT

モグラ先生:こんにちは!今日は、Cloudflare DDNS を最新の方法でラクに運用するトンネルを掘るよ。昔ながらの「グローバルAPIキー方式」はもう古い!今はAPIトークンsystemd timerでスマート管理する時代だね✨


はじめに|Cloudflare DDNSを最新仕様で運用しよう

今まで「グローバルAPIキー+cron」で更新していた人、多いですよね?
でもそれ、もう時代遅れかも知れません。

  • Cloudflare公式推奨は最小権限の「APIトークン」!
  • Linux界隈ではcronよりsystemd timerが推され中!
  • PythonもPEP 668対応が必要になってきました!

モグラ先生:つまり、「今風」に掘り直すと運用が安全・快適になるってことだね🐾


CloudflareでAPIトークンを作成しよう 🔑

必須キーワード:「Edit zone DNS」のトークン

  1. Cloudflareダッシュボードへログイン
  2. My Profile → API Tokens → Create Token
  3. テンプレートから「Edit zone DNS」を選ぶ
  4. 対象ゾーン(ドメイン)を限定して発行!

モグラ先生:昔のグローバルAPIキーは、落としたら全権喪失。怖いよね💦トークンなら安心!


Zone IDとRecord IDをAPIでゲットする🧭

bashスクリプト例:

CF_API="https://api.cloudflare.com/client/v4"
TOKEN="YOUR_BEARER"
DOMAIN="example.com"
FQDN="home.example.com"

ZONE_ID=$(curl -s -H "Authorization: Bearer $TOKEN" "$CF_API/zones?name=$DOMAIN" | jq -r '.result[0].id')
REC_ID=$(curl -s -H "Authorization: Bearer $TOKEN" "$CF_API/zones/$ZONE_ID/dns_records?type=A&name=$FQDN" | jq -r '.result[0].id')

モグラ先生:「手動で探す」とかもう卒業しよう。API叩いてサクッと掘り出そう!⛏️


PythonスクリプトでDNSを更新しよう 🐍

Pythonコード例:(update_dns.py)

import os
import requests
import re
from datetime import datetime
import configparser

# 現在のスクリプトのディレクトリを取得
current_directory = os.path.dirname(os.path.abspath(__file__))

# 設定ファイルを読み込む
config = configparser.ConfigParser()
config_file = os.path.join(current_directory, 'config.ini')
config.read(config_file)

# 設定値の取得
MY_DOMAIN = config['DEFAULT']['MY_DOMAIN']
ZONE_ID = config['DEFAULT']['ZONE_ID']
RECORD_ID = config['DEFAULT']['RECORD_ID']
AUTH_EMAIL = config['DEFAULT']['AUTH_EMAIL']
API_TOKEN = config['DEFAULT']['API_TOKEN']

# IPアドレス取得サービスのリスト
services = [
    "https://api.ipify.org/",
    "https://checkip.amazonaws.com/",
    "https://ipv4.icanhazip.com/",
    "https://4.icanhazip.com/"
]

def get_ip_address(url):
    """
    指定されたURLからIPアドレスを取得します。
    """
    try:
        response = requests.get(url)
        response.raise_for_status()
        return response.text.strip()
    except requests.RequestException:
        return None

def is_valid_ip(ip_address):
    """
    IPアドレスが正しい形式かどうかをチェックします。
    """
    pattern = r"^([0-9]{1,3}\.){3}[0-9]{1,3}$"
    return re.match(pattern, ip_address) is not None

# IPアドレスを取得するループ
ip_address = None
for service in services:
    ip_address = get_ip_address(service)
    if ip_address and is_valid_ip(ip_address):
        break

if ip_address is None:
    raise Exception("有効なIPアドレスを取得できませんでした。")

# 今日の日付を取得
current_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# CloudFlare APIによるAレコードの更新
update_url = f"https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records/{RECORD_ID}"
headers = {
    'Content-Type': 'application/json',
    'X-Auth-Email': AUTH_EMAIL,
    'Authorization': f'Bearer {API_TOKEN}'
}
data = {
    "content": ip_address,
    "name": MY_DOMAIN,
    "proxied": False,
    "type": "A",
    "comment": f"DDNS record updated on {current_datetime}"
}

response = requests.put(update_url, headers=headers, json=data)
response.raise_for_status()  # エラーが発生した場合、例外を発生させます

print("IPアドレスが更新されました。")
print('response',response)

設定ファイルの例:(config.ini)

[DEFAULT]
MY_DOMAIN=XXXXX
ZONE_ID=YYYYY
RECORD_ID=ZZZZZ
[email protected]
API_TOKEN=AABBCCDD

5️⃣ Python仮想環境(venv)で安全に運用 🐚

python3 -m venv ~/cf-ddns
~/cf-ddns/bin/pip install requests

PEP 668対応で、グローバルpip汚染を防ぎましょう。

モグラ先生:今どきsudo pip installは時限爆弾だから絶対やめようね💣


6️⃣ systemd-timerで自動更新!⏰

.serviceファイル

[Unit]
Description=Update Cloudflare DDNS
After=network-online.target

[Service]
Type=oneshot
ExecStart=/home/pi/cf-ddns/bin/python /home/pi/update_ddns.py

.timerファイル

[Unit]
Description=Run Cloudflare DDNS every 5min

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
AccuracySec=30s
Persistent=true
Unit=cf-ddns.service

[Install]
WantedBy=timers.target

ポイント!

  • Persistent=trueにすると、シャットダウン中の実行漏れもリカバー!
  • systemctl list-timersで次回予定も確認できる!
sudo systemctl daemon-reload
sudo systemctl enable --now cf-ddns.timer
systemctl list-timers | grep cf-ddns

モグラ先生:「cronと違って、再起動後も自動で走る」のがsystemd-timer最大のメリットだよ!


7️⃣ 代替案:ddclient 3.11以上を使う手もある🚏

もし「Pythonスクリプトめんどい!」なら、ddclientでもいけます。

以下でインストール。初期設定ウィザードは適当でOK。

apt install ddclient

ddclient設定例:

#================= 一般設定 =================
daemon=300
syslog=yes
pid=/var/run/ddclient.pid
ssl=yes

#================= IP 取得設定 ==============
usev4=webv4, webv4=ipify-ipv4
usev6=webv6, webv6=ident-me-ipv6

#================= Cloudflare 本体 ==========
protocol=cloudflare, \
zone=hoge.com, \
ttl=1, \
login=token, \
password=<API_TOKEN> \
XXX.hoge.com
  • loginには「token」と明示!
  • passwordにAPIトークン直書き!

【まとめ】Cloudflare DDNSを最新運用にアップグレードしよう⛏️✨

  • APIトークン+systemd-timerで安全・スマートなDDNS運用が可能!
  • グローバルAPIキーやcronは卒業して、今風のやり方へ!
  • Python仮想環境(venv)運用で依存管理もバッチリ!

これでCloudflare DDNS運用は一段とラクに!
次回はこの仕組みをDocker化してさらに掘り進める予定だよ〜🐾

モグラ先生:最後まで読んでくれてありがと〜!他の記事もぜひ掘りに来てね🪹✨

タイトルとURLをコピーしました