この記事は TUT CDSL Advent Calendar 2019 - Adventar の1日目です.
正式名称はCloud and Distributed Systems Laboratory(クラウド・分散処理)です.2019年に発足したばかりの研究室です.細かなことは今後の記事にまかせます.
この記事では,CDSLの内部にあるシステムを紹介します.今回はDDNSまわりを紹介します.
DDNSとは
DDNSは動的(Dynamic)に割り当てを行うDNSです.例えば,ホスト名が hoge
の場合は hoge.exampe.com
が自動で割り当てられることです.CDSLではこの技術を使って,ネットワーク内の端末へFQDNでアクセスできる仕組みを用意しています.
アーキテクチャ
DNSサーバは,権威サーバとキャッシュサーバのどちらもPowerDNSを使っています.DHCPサーバーにはISC DHCPDを使っています.Fluentdは後述のSlack通知に使っています.
PowerDNSの設定例:
config-dir=/etc/powerdns
local-address=192.168.100.6
local-port=53
allow-from=127.0.0.0/8,192.168.100.0/24
forward-zones=a910.tak-cslab.org=127.0.0.1
forward-zones-recurse=.=8.8.8.8,.=1.1.1.1
hint-file=/usr/share/dns/root.hints
setgid=pdns
setuid=pdns
max-cache-ttl=300
max-negative-ttl=300
ISC DHCPDの設定例:
option domain-name "a910.tak-cslab.org";
option domain-name-servers 192.168.100.6, 8.8.8.8;
# 12h
default-lease-time 43200;
# 24h
max-lease-time 86400;
ddns-updates on;
ddns-update-style standard;
ignore client-updates;
log-facility local7;
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.100.10 192.168.100.254;
option routers 192.168.0.1;
ddns-domainname "a910.tak-cslab.org";
ddns-ttl 3600;
zone a910.tak-cslab.org. {
primary 127.0.0.1;
}
# zone 100.168.192.in-addr.arpa. {
# primary 127.0.0.1;
# }
}
Slack通知
当初,DDNSの割り当てを確認するためにWeb UIの用意を考えていました.しかし,そのためにサーバーの管理や設定を行うことは負担になると考えました.そこで,Slackのチャンネルを作成し,そこへ通知を送ることにしました.
ISC DHCPDにはIPリース時にコマンドを実行する機能があります.しかし,この機能を使おうと設定を行ったところ権限エラーで動作しないため諦めました.
ISC DHCP serverでIPアドレスのリース時に外部コマンドを実行する - yunazuno.log
方針を転換して,Fluentdのtailプラグインでログの監視を行い,条件に一致した文字列が見つかった場合にSlackへ通知を行うことにしました.
fluentdでログ監視して特定の文字列をgrepで検知したらSlackに通知する(バースト抑止付き) - Qiita
Fluentdの設定例:
## File input
<source>
@type tail
@id input_tail
@label @raw
path /var/log/syslog
pos_file /var/lib/td-agent/syslog.pos
format syslog
tag raw.syslog
</source>
<label @raw>
## Filtering DHCPD
<filter>
@type grep
<and>
<regexp>
key ident
pattern /^dhcpd$/
</regexp>
<regexp>
key message
pattern /^Added new forward map from/
</regexp>
</and>
</filter>
## Remove prefix
<filter>
@type record_transformer
enable_ruby true
<record>
message ${record["message"].gsub("Added new forward map from ","").gsub(" to ", ",")}
tag ${tag}
</record>
</filter>
## CSV Parse
<filter>
@type parser
key_name message
<parse>
@type csv
keys fqdn,ip_addr
</parse>
</filter>
## Remove prefix
<filter>
@type record_transformer
enable_ruby true
<record>
message ${record["fqdn"]} is binded new client. (ip_addr: `${record["ip_addr"]}` )
tag ${tag}
</record>
</filter>
## Debug
# <match>
# @type stdout
# @id output_stdout
# # <format>
# # @type json
# # </format>
# </match>
<match>
@type slack
webhook_url https://hooks.slack.com/services/XXXX/YYYY/ZZZZZZZ
channel _ddns-notice
username ddns-notice
icon_emoji :ghost:
flush_interval 60s
</match>
</label>