読者です 読者をやめる 読者になる 読者になる

みかづきメモ

学習したことのメモとか、日記とか、備忘録。

Raspberry Pi 2 で cron を使って IPアドレスを監視する

前回、Raspberry Pi でサーバーを建てたのはいいのだけれども、
うちはグローバルIPアドレスがちょくちょく変わるので、 cron でなんとかしてみる。


前回の記事 mikazuki.hatenablog.jp

このままでもいいけども、IPアドレスが変わってアクセスできなくなるのは困るので、
cron とかを使って、 IPアドレスを監視し、変わっていたら変更を適用させます。

とりあえず、cron で10分おきくらいでタスクを実行させてみます。

crontab -e

できたら、これは使わないほうがいい*1(タイプミスしたら悲しいことになる)らしいけど、
これ1回だけなので。

nanoが開くので、以下の項目を追加

*/10 * * * * /home/mikazuki/task/hoge.sh

これで、10分おきに hoge.sh を実行してくれます。


次に、IPアドレスの監視部分。
ほしいのは、グローバルIPアドレスなので、 http://httpbin.org/ip を使うことにしました。
下のようなものが帰ってきます。

{
    "origin": "111.111.111.111"
}

これで、グローバルIPアドレスが入手出来ました。


次は、これをDNSのレコードに適用させます。
私は、ConoHaのDNSを使っているので、APIを使ってやってみることにしました。   Designate とか言うやつらしいですね。便利な時代です。

それで、上までの作業をまとめたのが↓

#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import pycurl
from StringIO import StringIO

# ConoHa APIユーザー
API_USER = "hoge"

# ConoHa APIパスワード
API_PASSWD = "fuga"

# ConoHa テナントID
TENANT_ID = "foobar"

# 更新対象のドメイン
DOMAINS = ["example.com", "www.example.com"]

# 更新対象のレコード
RECORDS = ["A"]

# 以下定数
CONOHA_DNS_SERVICE = 'https://dns-service.tyo1.conoha.io'

token = ""
ipaddress = ""

#
# ネットワークまわり
#
# method
#  0 : GET
#  1 : POST
#  3 : PUT
#
def network(endpoint, method = 0, headers = [], contents = []):
    buffer = StringIO()
    
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, endpoint)
    curl.setopt(pycurl.HTTPHEADER, headers)
    if method == 1:
        curl.setopt(pycurl.POST, 1)
        curl.setopt(pycurl.POSTFIELDS, json.dumps(contents))
    if method == 3:
        curl.setopt(pycurl.CUSTOMREQUEST, 'PUT')
        curl.setopt(pycurl.POSTFIELDS, json.dumps(contents))
    curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
    curl.perform()
    curl.close()

    return buffer.getvalue()
# --------------------------------------------------------


#
# 初期化
#
def initialize():
    global token
    
    options = {"auth": {"passwordCredentials": {"username": API_USER, "password": API_PASSWD}, "tenantId": TENANT_ID}}
    response = json.loads(network('https://identity.tyo1.conoha.io/v2.0/tokens', 1, ['Accept: application/json'], options))

    token = response["access"]["token"]["id"]
# --------------------------------------------------------


#
# グローバルIPアドレスを拾ってくる
#
def get_global_ip():
    global ipaddress
    
    response = json.loads(network('http://httpbin.org/ip'))
    ipaddress = response['origin']
# --------------------------------------------------------

#
# レコードの更新
#
def update_record(record):
    if record['data'] == ipaddress:
        return

    options = {"name": record["name"], "type": record["type"], "data": ipaddress}
    response = json.loads(network(CONOHA_DNS_SERVICE + '/v1/domains/' + str(record['domain_id']) + '/records/' + str(record['id']), 3, ['Accept: application/json', 'X-Auth-Token: ' + str(token), 'Content-Type: application/json'], options))
    if response['data'] == ipaddress:
        print "ok"
# --------------------------------------------------------

#
# ConoHa の DNS に登録されているものを列挙したり
#
def select_domains():
    response = json.loads(network(CONOHA_DNS_SERVICE + '/v1/domains', 0, ['Accept: application/json', 'X-Auth-Token: ' + str(token)]))
    for domain in response["domains"]:
        records = json.loads(network(CONOHA_DNS_SERVICE + '/v1/domains/' + str(domain['id']) + '/records', 0, ['Accept: application/json', 'X-Auth-Token: ' + str(token)]))
        for record in records["records"]:
            if not record['type'] in RECORDS:
                continue

            if record['name'][:-1] in DOMAINS:
                update_record(record)
# --------------------------------------------------------

#
# Main
#
def main():
    initialize()
    get_global_ip()
    select_domains()
main()

あまり時間がなかったので、あれだけども(;・∀・)
前のIPアドレスとかは保存してないので、すごく無駄な処理がある気がするけど、
多分そのうち直すと思います。

ちなみに、はじめから pycurl ははいってないので、 pip で入れる必要があります。

# pip の導入
sudo apt-get install python-pip

# pycurl の導入
sudo apt-get install libcurl4-openssl-dev
pip install pycurl

とりあえず、これで目的を達成することはできました。

ではでは。


宣伝 www.conoha.jp