test/lib/dns.sh

241 lines
7.6 KiB
Bash

#!/bin/bash
#
# DNS Service
PATH=$HOME/.docker/cli-plugins:/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
config_dns() {
echo -ne "\n* Configuring /federated/apps/dns container.."
spin &
SPINPID=$!
EXTERNAL_IP_LASTDIGIT=`echo $EXTERNALIP | awk -F . '{ print $4 }'`
EXTERNALIP_INADDR=`echo $EXTERNALIP | awk -F . '{ print $3"."$2"."$1".in-addr.arpa"}'`
EXTERNALIP_INADDR_CAPS=`echo $EXTERNALIP | awk -F . '{ print $3"."$2"."$1".IN-ADDR.ARPA"}'`
mkdir -p /federated/apps/dns/data/root
mkdir -p /federated/apps/dns/data/etc/bind/zones
mkdir -p /federated/apps/dns/data/var/log/letsencrypt
cat > /federated/apps/dns/docker-compose.yml <<EOF
services:
dns:
image: alpine:\${IMAGE_VERSION}
container_name: dns
hostname: dns
restart: always
working_dir: /root
networks:
core:
ipv4_address: 192.168.0.10
volumes:
- ./data/etc/bind:/etc/bind
- ./data/etc/letsencrypt:/etc/letsencrypt
- ./data/var/log/letsencrypt:/var/log/letsencrypt
- ./data/root:/root
ports:
- "53:53/udp"
- "53:53/tcp"
command: [ "/root/dns-cert.sh" ]
networks:
core:
external: true
EOF
cat > /federated/apps/dns/data/root/dns-cert.sh <<'EOF'
#!/bin/sh -x
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
if [ ! -e /etc/bind/.firstdone ]; then
# Install bind and certbot packages
apk add --no-cache bind
apk add --no-cache certbot
# Install ACME DNS script
if [ ! -e /root/acme-dns-auth.py ]; then
wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py
chmod +x acme-dns-auth.py
fi
[ ! -e /usr/bin/python ] && ln -s /usr/bin/python3 /usr/bin/python
# Run rndc to create bind keys for rndc to run
rndc-confgen -a
cat /etc/bind/rndc.key >> /etc/bind/named.conf
# Run Certbot and insert CNAME record into bind configuration
DOMAIN=`ls /etc/bind/zones | head -1`
echo "Trying to certbot for DOMAIN $DOMAIN"
CNAME_RECORD=`certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n 2>1 | grep acme-dns | awk '{ print $3 }'`
echo "Got CNAME record: $CNAME_RECORD"
echo "$CNAME_RECORD" > /etc/bind/.cnamerecord
echo -e "_acme-challenge.customer2\tIN\tCNAME\t$CNAME_RECORD" >> /etc/bind/zones/$DOMAIN
# Reload Bind configuration without restarting the container or process
named -f -g &
crond &
# rndc reload $DOMAIN
# rndc reload
sleep 7
# Run Certbot again to generate the certificate
certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n &> /dev/null
if [ $? -eq 0 ]; then
echo "[federated]: SUCCESS generating certificates for $DOMAIN!"
echo "[federated]: Certificates are at /etc/letsencrypt/live/$DOMAIN"
echo -ne "#!/bin/sh\n\n/usr/bin/certbot renew -q" > /etc/periodic/15min/certbot-renew.sh
chmod +x /etc/periodic/15min/certbot-renew.sh
else
touch /etc/bind/.failedcert
touch /etc/bind/.firstdone
echo "[federated]: FAILED generating certificates for $DOMAIN"
echo "[federated]: Check that you have DNS setup properly"
wait -n
exit 2;
fi
touch /etc/bind/.firstdone
wait -n
elif [ -e /etc/bind/.firstdone ] && [ -e /etc/bind/.failedcert ]; then
# Install bind and certbot packages
apk add --no-cache bind
apk add --no-cache certbot
DOMAIN=`ls /etc/bind/zones | head -1`
named -f -g &
crond &
sleep 7
# Run Certbot again to generate the certificate
certbot certonly --manual --manual-auth-hook /root/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d \*.$DOMAIN -d $DOMAIN --agree-tos --email hostmaster@$DOMAIN -n &> /dev/null
if [ $? -eq 0 ]; then
rm /etc/bind/.failedcert
echo "[federated]: SUCCESS generating certificates for $DOMAIN!"
echo "[federated]: Certificates are at /etc/letsencrypt/live/$DOMAIN"
else
touch /etc/bind/.failedcert
echo "[federated]: FAILED generating certificates for $DOMAIN"
echo "[federated]: Check that you have DNS setup properly"
wait -n
exit 2;
fi
wait -n
else
# Install bind and certbot packages
apk add --no-cache bind
apk add --no-cache certbot
[ ! `pgrep -x named` ] && named -f -g && crond
fi
EOF
chmod +x /federated/apps/dns/data/root/dns-cert.sh
cat > /federated/apps/dns/.env <<EOF
IMAGE_VERSION="3.17.1"
EOF
chmod 600 /federated/apps/dns/.env
cat > /federated/apps/dns/data/etc/bind/named.conf <<EOF
options {
directory "/var/bind";
listen-on { any; };
listen-on-v6 { none; };
allow-transfer { none; };
allow-recursion { none; };
recursion no;
dnssec-validation auto;
};
zone "$DOMAIN" {
type master;
file "/etc/bind/zones/$DOMAIN";
};
zone "$EXTERNALIP_INADDR" {
type master;
file "/etc/bind/zones/$DOMAIN.rev";
};
controls {
inet 127.0.0.1 port 953
allow { 127.0.0.1; } keys { "rndc-key"; };
};
EOF
cat > /federated/apps/dns/data/etc/bind/zones/$DOMAIN <<EOF
\$TTL 2d
\$ORIGIN $DOMAIN.
$DOMAIN. IN SOA ns1.$DOMAIN. hostmaster.$DOMAIN. (
18 ; Serial
12h ; Refresh
15m ; Retry
3w ; Expire
3h ; Negative Cache TTL
)
IN NS ns1.$DOMAIN.
IN NS ns2.$DOMAIN.
MX 10 mail.$DOMAIN.
IN TXT "v=spf1 mx a:mail.$DOMAIN ~all"
ns1 IN A $EXTERNALIP
ns2 IN A $EXTERNALIP
mail IN A $EXTERNALIP
www IN A $EXTERNALIP
EOF
cat > /federated/apps/dns/data/etc/bind/zones/$DOMAIN.rev <<EOF
\$TTL 2d
\$ORIGIN $EXTERNALIP_INADDR_CAPS.
@ IN SOA ns1.$DOMAIN. hostmaster.$DOMAIN. (
12 ; Serial
12h ; Refresh
15m ; Retry
3w ; Expire
3h ; Negative Cache TTL
)
IN NS ns1.$DOMAIN.
IN NS ns2.$DOMAIN.
$EXTERNAL_IP_LASTDIGIT IN PTR computer.$DOMAIN.
EOF
echo -ne "done."
kill $SPINPID &> /dev/null
}
start_dns() {
echo -ne "\n* Starting /federated/apps/dns service.."
spin &
SPINPID=$!
if [ $DEBUG ]; then
# Start /federated/apps/dns with output to console for debug
docker compose -f /federated/apps/dns/docker-compose.yml -p dns up
[ $? -eq 0 ] && echo -ne "done.\n" || fail "There was a problem starting service /federated/apps/dns"
else
# Start /federated/apps/dns with output to /dev/null
docker compose -f /federated/apps/dns/docker-compose.yml -p dns up -d &> /dev/null
# Keep trying to see that certificates are generated
RETRY="18"
while [ $RETRY -gt 0 ]; do
# Check if we have hit limit for requesting certificate too many times / limits
docker exec -it dns grep "too many certificates" /var/log/letsencrypt/letsencrypt.log &> /dev/null
if [ $? -eq 0 ]; then
fail "There was a problem starting /federated/apps/dns\nYou have requested this certificate too many times.\nWait 24 hours before requesting it again.\n"
fi
# Check if certs are generated
ls /federated/apps/dns/data/etc/letsencrypt/live/$DOMAIN/*.pem &> /dev/null
if [ $? -eq 0 ]; then
kill -9 $SPINPID &> /dev/null
echo -ne "done."
# echo -ne "* Certificates at /federated/apps/dns/data/etc/letsencrypt/live/$DOMAIN\n"
break
else
if [ "$RETRY" == 1 ]; then
docker compose -f /federated/apps/dns/docker-compose.yml -p dns down &> /dev/null
fail "There was a problem starting service /federated/apps/dns\nCheck the output of 'docker logs dns' or turn on\ndebug with -d"
fi
((RETRY--))
sleep 9
fi
done
fi
}