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