DNS のゾーンファイルを編集する

「ネットワークに新規のサーバーを追加した」や、「サーバーの入れ替えをした」など、DNS の設定を変更する場合があります。追加・変更する際には bind のゾーンファイルを書き換えることになりますが、これは運用上、最も気を使う作業の一つです。本稿では、Kompira Enterprise を利用して DNS の登録情報の変更を行ってみましょう。

※ named の設定と Python に関する簡単な知識が前提となります。


環境情報

本稿は、以下の環境で検証しています。

ソフトウェア バージョン
Kompira Enterprise 1.5.5.post11
OS CentOS 7.8.2003
dnspython 1.16.0

または

ソフトウェア バージョン
Kompira Enterprise 1.6.2.post4
OS CentOS 7.8.2003
dnspython 2.1.0

事前準備

単純にサーバーの追加であれば、ゾーンファイルに A レコードを追加するのみですが、今回のような既存登録の変更となると単純ではありません。
本稿では Python の “dnspython” を利用し、ゾーンファイルにおける既存登録の変更を行っていきます。

流れとしては以下のようになります。

1. DNS サーバーから、ゾーンファイルを Kompira Enterprise サーバーに転送
2. Kompira Enterprise サーバーで、dnspython の機能を使って編集
3. 編集したファイルを DNS サーバーに再転送

dnspython のインストール

Kompira Enterprise サーバーにシェルログインを行った後、管理者権限のアカウントで以下のようにインストールしてください。

Kompira Enterprise 1.6系の場合

$ /opt/kompira/bin/pip install dnspython=2.1.0

Kompira Enterprise 1.5系の場合

$ /opt/kompira/bin/pip install dnspython=1.16.0

※ Kompira Enterprise 1.4系では /opt/kompira/bin/pip install の代わりに easy_install を用います。

ライブラリの作成

Kompira Enterprise から dnspython を利用するためのラッパーライブラリを作成していきます。ここでは「DNSレコード編集」という名前の「ライブラリ型」のオブジェクトを作成します。

ライブラリ「DNSレコード編集」

import dns.rdata
import dns.rdataset
import dns.zone
from dns.exception import DNSException
from dns.rdataclass import *
from dns.rdatatype import *

def change_A_record(oldzone, newzone, domain, key, new_IP):
    """
    oldzone: 変更前のゾーンファイル
    newzone: 変更後のゾーンファイル
    domain: ドメイン名
    key: キー (www 、mail 、ftp など)
    new_IP: 変更後の IP アドレス
    """
    
    try:
        zone = dns.zone.from_file(oldzone, domain)
        print("Zone origin: {}".format(zone.origin))
    except DNSException as e:
        print(e.__class__, e)

    print("Changing A record for {} to {}".format(key, new_IP))
    rdataset = zone.find_rdataset(key, rdtype=A)
    
    # 対象となる A レコードがなければ終了
    if not rdataset:
        return()
    
    # zone を置き換えるための新規 Rdataset を作成
    rdclass, rdtype = rdataset[0].rdclass, rdataset[0].rdtype
    new_rdataset = dns.rdataset.Rdataset(rdclass, rdtype)
    
    # IP Address を変更した新規 Rdata オブジェクトを作成
    for rdata in rdataset:
        new_rdata = dns.rdata.from_text(rdclass, rdtype, new_IP)
        new_rdataset.add(new_rdata)

    # zone の更新
    zone.replace_rdataset(zone.origin, new_rdataset)
    print("Writing modified zone to file {}".format(newzone))
    zone.to_file(newzone)

これで指定したドメイン名、キーに該当するレコードの IP アドレスを変更して、新しいゾーンファイルに保存する “change_A_record” というメソッドが利用できるようになりました。

ジョブフローの作成

次にライブラリを利用するジョブフローを作成します。

| oldzone = "/var/named/mykompira.com.db" | # DNS上のゾーンファイル
| domain = "mykompira.com" |                # ドメイン名
| key = "mail" |                            # キー
| ip = "192.168.99.99" |                   # 変更後のIPアドレス
| tmpzone = "/tmp/tmpzone" |               # 作業用の一時ファイル(変更前)
| newzone = "/tmp/mykompira.com.db.new" |   # 作業用一時ファイル(変更後)
  
[
    __host__ = "<DNS サーバー>",
    __user__ = "<ユーザー名>",
    __password__ = "<パスワード>",
    __sudo__ = true
] ->

get(oldzone, tmpzone) ->
["cat $tmpzone"] ->
print($RESULT) -> # 変更前のゾーン

[./DNSレコード編集.change_A_record: tmpzone, newzone, domain, key, ip] ->
put(newzone, oldzone) ->
["cat $newzone"] ->
print($RESULT) -> # 変更後のゾーン

["rndc reload"]

上記のジョブフローの流れは以下の通りです。

1. get() を利用し、DNS サーバーからゾーンファイルを Kompira Enterprise サーバーにダウンロード
2. change_A_record() を呼び出し、ゾーン情報内のレコードの更新
3. 変更後のゾーンファイル /tmp/mykompira.com.db.new を DNS サーバーに再アップロード

(必要に応じて rndc コマンドでゾーン情報の再読み込みを行わせるなどの対応が必要です。)

本稿では dnspython を利用して既存のゾーン情報内のレコードの更新を行いましたが、他にも TTL の変更、ドメインの追加、ホストの追加・削除などを行うことができます。上記と同様にライブラリにメソッドを追加してジョブフローから利用することができますので、詳細に関しては「dnspython」を参照してください。

今回の例では Kompira Enterprise サーバー上に dnspython をインストールしました。しかし、dnspython を DNS サーバー上にインストールすることができれば、Kompira Enterprise からはコマンド発行のみでゾーン情報の変更が出来るため、get/put のようなファイル転送は不要になります。また、DNS サーバーの認証情報についても「ノード情報」型オブジェクトを使用しても結構です。

TOP