bind运维——docker bind-9.20.16配置dnssec

Dockerfile的代码:

FROM alpine:latest as builder
RUN sed -i 's|http.*/alpine/|https://mirrors.nju.edu.cn/alpine/|g' /etc/apk/repositories && \
    apk add --no-cache build-base openssl-dev libuv-dev libcap-dev userspace-rcu-dev jemalloc-dev readline-dev json-c-dev nghttp2-dev zlib-dev perl
WORKDIR /usr/local/src
COPY ./bind-9.20.16.tar.xz /usr/local/src
RUN tar -xJf bind-9.20.16.tar.xz && \
    cd bind-9.20.16 && \
    ./configure --prefix=/usr/local/bind9 \
    --sysconfdir=/etc/bind \
    --localstatedir=/var/bind \
    --enable-largefile \
    --enable-dnsrps \
    --with-openssl=yes \
    --with-readline=yes \
    --with-jemalloc \
    --with-json-c \
    --with-zlib && \
    make -j$(nproc) && \
    make install
FROM alpine:latest
RUN sed -i 's|http.*/alpine/|https://mirrors.nju.edu.cn/alpine/|g' /etc/apk/repositories && \
    apk add --no-cache openssl-dev libuv-dev libcap-dev userspace-rcu-dev jemalloc-dev readline-dev json-c-dev nghttp2-dev zlib-dev perl
RUN addgroup named && adduser -G named -S -D -H -h /var/bind -s /sbin/nologin named && \
    mkdir -p /etc/bind /var/bind && \
    chown -R named:named /etc/bind /var/bind
COPY --from=builder /usr/local/bind9 /usr/local/bind9
WORKDIR /etc/bind
COPY ./rndc.conf .
COPY ./named.ca .
ENV PATH="/usr/local/bind9/sbin:/usr/local/bind9/bin:$PATH"
EXPOSE 53/udp 53/tcp
CMD ["named", "-g", "-u", "named", "-c", "/etc/bind/named.conf"]

生成named.ca:

dig -t ns @a.root-servers.net. . >named.ca

rndc.conf的代码:

key "rndc-key" {
	algorithm hmac-sha256;
	secret "9we6RB9xNmgiC3Y16uS6fUjgpDIXWHHvRwKMY6AJmoM=";
};
options {
	default-key "rndc-key";
	default-server 127.0.0.1;
	default-port 953;
};

构建alpine-bind:9.20.16的镜像:

docker build --no-cache -t alpine-bind:9.20.16 .

named.conf的代码:

options {
    directory "/var/bind";
    pid-file "/var/run/named/named.pid";
    listen-on port 53 { any; };
    allow-query { any; };
    allow-recursion { none; };
    recursion no;
};
zone "." IN {
    type hint;
    file "/etc/bind/named.ca";
};
zone "example.com" {
    type primary;
    file "/etc/bind/zones/example.com.db";
    dnssec-policy default;
};
key "rndc-key" {
	algorithm hmac-sha256;
	secret "9we6RB9xNmgiC3Y16uS6fUjgpDIXWHHvRwKMY6AJmoM=";
};
controls {
	inet 127.0.0.1 port 953
		allow { 127.0.0.1; } keys { "rndc-key"; };
};

zones/example.com.db的代码:

$TTL 86400
@ IN SOA ns1.example.com. yunhaoz000@gmail.com. (
 1764126658
 7200
 3600
 1209600
 3600 )
  IN NS ns1.example.com.
  IN NS ns2.example.com.
ns1 1440 IN A 167.88.177.215
ns2 1440 IN A 167.88.177.215
ifconfig 205 IN A 222.94.76.5
zyc 205 IN A 114.221.74.194
kms.v0v 205 IN A 167.88.177.215
kms.v3v IN CNAME ifconfig.example.com.
cnta IN CNAME ifconfig.example.com.
gofile IN CNAME ifconfig.example.com.
svn IN CNAME ifconfig.example.com.
relay-acting IN CNAME ifconfig.example.com.
time IN CNAME ifconfig.example.com.
ntp IN CNAME ifconfig.example.com.
kms.v6v IN CNAME zyc.example.com.
tun IN CNAME zyc.example.com.

docker-compose.yml的代码:

services:
  memcached:
    image: memcached:latest
    container_name: memcached
    ports:
      - "11211:11211"
    restart: always
    command: memcached -m 64 -p 11211 -u memcache -l 0.0.0.0
  bind9:
    image: alpine-bind:9.20.16
    container_name: bind9
    ports:
      - "53:53/udp"
    restart: always
    volumes:
      - ./named.conf:/etc/bind/named.conf:rw
      - ./zones:/etc/bind/zones:rw

导入镜像:

docker load -i alpine-bind_9.20.16.img.gz
docker load -i memcached_latest.img.gz

启动容器:

docker-compose up -d

获取DS记录:

docker exec -it bind9 dnssec-dsfromkey /var/bind/Kexample.com.+013+52282.private
example.com. IN DS 52282 13 2 81D26780574037294C3A38FBFE563FD234D10B00297BCD7877851AC963634FFC

阿里云控制台-域名与网站-域名列表-<域名>-管理-DNS管理-DNSSEC设置-添加DS记录:

密钥标签:52282

加密算法:13 >

摘要类型:2 >

摘要:

81D26780574037294C3A38FBFE563FD234D10B00297BCD7877851AC963634FFC

阿里云控制台-域名与网站-域名列表-<域名>-管理-DNS管理-自定义DNS Host-创建DNS服务器:

ns1.<域名> IP地址

ns2.<域名> IP地址

阿里云控制台-域名与网站-域名列表-<域名>-管理-DNS管理-DNS修改:

修改为自定义DNS服务器:ns1.<域名> ns2.<域名>

DDNS联动机制:

客户端脚本storeipaddrtomemcache.sh的代码:

#!/bin/bash
mem__key="ifconfig"
mem__ipaddr="167.88.177.215"
mem__port="11211"
ipaddr="$(curl -4sLk -m 5 --retry 2 ip.sb/ip 2>/dev/null | grep -Eo "([0-9]{1,3}.){3}[0-9]{1,3}")"
if [[ "${#ipaddr}" -gt "0" ]]; then
	echo "Your IP Address is: ${ipaddr}"
	echo "Reading from Memcached ..."
	ipaddr__stored="$(printf "get ${mem__key}\r\n" | nc -w 1 ${mem__ipaddr} ${mem__port} | grep -Eo "([0-9]{1,3}.){3}[0-9]{1,3}")"
	if [[ "$ipaddr__stored" != "$ipaddr" ]]; then
		echo "Sending to Memcached..."
		printf "set ${mem__key} 0 900 ${#ipaddr}\r\n${ipaddr}\r\n" | nc -w 2 ${mem__ipaddr} ${mem__port}
		echo "Done"
	else
		echo "Already stored"
	fi
else
	echo "Failed to get your IP Address"
	exit 1
fi

服务端脚本readipaddrfrommemcache.sh的代码:

#!/bin/bash
mem__keys=(ifconfig zyc)
mem__ipaddr="167.88.177.215"
mem__port="11211"
zone__file="/data/bind9/zones/example.com.db"
if [[ ! -s "$zone__file" ]]; then
	echo "Zone file not found"
	exit 1
fi
updated__tag=0
for ((i = 0; i < ${#mem__keys[@]}; i++)); do
	mem__key="${mem__keys[$i]}"
	ipaddr__stored="$(printf "get ${mem__key}\r\n" | nc -w 1 ${mem__ipaddr} ${mem__port} 2>/dev/null | grep -Eo "([0-9]{1,3}.){3}[0-9]{1,3}")"
	if [[ "${#ipaddr__stored}" -gt "0" ]]; then
		ipaddr__setted="$(awk '{if($1==K){print $0}}' K=$mem__key $zone__file | grep -Eo "([0-9]{1,3}.){3}[0-9]{1,3}")"
		if [[ "${#ipaddr__setted}" -eq "0" ]]; then
			echo "Adding $mem__key ... ($ipaddr__stored)"
			echo "${mem__key} 205 IN A ${ipaddr__stored}" >>$zone__file
			let updated__tag++
			continue
		fi
		if [[ "$ipaddr__stored" != "$ipaddr__setted" ]]; then
			echo "Updating $mem__key ... ($ipaddr__setted -> $ipaddr__stored)"
			sed -i "/^${mem__key}/s/([0-9]{1,3}.){3}[0-9]{1,3}/${ipaddr__stored}/g" $zone__file
			let updated__tag++
		else
			echo "$mem__key Already updated ($ipaddr__stored)"
		fi
	fi
done
if [[ "$updated__tag" -gt "0" ]]; then
	echo "Updating zone file..."
	/bin/cp -f $zone__file $zone__file.bak
	serial__num="$(date +%s)"
	sed -i "3s/[0-9]+/${serial__num}/g" $zone__file
	docker exec -i bind9 named-checkzone example.com /etc/bind/zones/example.com.db &&
		docker exec -i bind9 rndc reload
fi

客户端脚本设置为1分钟自动运行一次,当IP变化后,将当前的IP更新到服务端的memcached的相关键的值暂存900秒。

服务端脚本设置为1分钟自动运行一次,当IP需要更新的时候,自动进行DNS记录的修改(无则添加)并重载最新的区域配置。

Categories: docker与kubernetes