Skip to content

Instantly share code, notes, and snippets.

@grepwood
Created December 2, 2014 08:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grepwood/0cf3286d6491f57a7a1f to your computer and use it in GitHub Desktop.
Save grepwood/0cf3286d6491f57a7a1f to your computer and use it in GitHub Desktop.
Sets up PowerDNS on a host in slave or master mode
#!/bin/bash
# Before running this script
RUNLEVELS="235"
HAVE_PASS=0
FEEDED_KEY=""
ROLE=""
JOB_PID=$$
NAN=1
NUMREGEX='^[0-9]+$'
DEPS=""
DEBUG=0
# Before you begin, you have to set these variables:
NS1_INET="0"
SOLUS_MANAGER="0"
# If there are any commented out lines, that means they are for MySQL 5.1
# The script has been refactored to work with MariaDB 5.5, which is a non-Oracle implementation of MySQL 5.5
if [ "$NS1_INET" == "0" ] || [ "$SOLUS_MANAGER" == "0" ]; then
echo "Before you begin to set up your host, you must edit the following variables:"
echo "NS1_INET located at line 14"
echo "SOLUS_MANAGER located at line 15"
echo "They need to be IPv4 addresses of your nameserver 1 and your VM manager"
exit
fi
if [ "$#" -gt "0" ]; then
if [ "$#" -eq "1" ] || [ "$#" -eq "2" ]; then
if [[ $1 =~ ^([mM][aA][sS][tT][eE][rR])$ ]]; then
ROLE="Master"
elif [[ $1 =~ ^([sS][lL][aA][vV][eE])$ ]]; then
ROLE="Slave"
else
echo "First argument is either slave or master."
exit
fi
fi
if [ "$#" -eq "2" ]; then
FEEDED_KEY="$2"
HAVE_PASS=1
fi
if [ "$#" -gt "3" ]; then
echo "This program accepts only 2 argument"
exit
fi
else
echo "Usage: setup_pdns.sh role (pass)"
echo "role is either master or slave"
echo "pass is optional"
exit
fi
CONFLICT=`netstat -lnpu | tail -n+3 | awk '{print $4}' | sed 's/.*://' | grep ^53$ | wc -l`
if [ "$CONFLICT" -eq "1" ]; then
COLUMNS=`netstat -lnpu | tail -n+3 | awk 'BEGIN {FS=" "} ; END{print NF}'`
CONFLICT_NAME=`netstat -lnpu | tail -n+3 | awk '{print $"$COLUMNS"}'`
echo "$CONFLICT_NAME is hogging port 53. Kill it."
exit
elif [ "$CONFLICT" -gt "1" ]; then
echo "There are programs fighting for port 53! Kill them before continuing."
exit
fi
mkdir -p /var/lib/mysql
HAVE_EPEL=`rpm -qa epel-release | wc -l`
if [ "$HAVE_EPEL" -eq "0" ]; then
rpm -U http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 2>/dev/null
fi
if [ ! -f "/etc/yum.repos.d/mariadb.repo" ] || [ `md5sum /etc/yum.repos.d/mariadb.repo 2>/dev/null | awk '{print $1}'` != "02fdd192719bcc8bf621db927a1c3de4" ]; then
printf "Adding MariaDB repo... "
echo "[mariadb]" > /etc/yum.repos.d/mariadb.repo
echo "name = MariaDB" >> /etc/yum.repos.d/mariadb.repo
echo "baseurl = http://yum.mariadb.org/5.5/centos6-amd64" >> /etc/yum.repos.d/mariadb.repo
echo "gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB" >> /etc/yum.repos.d/mariadb.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/mariadb.repo
rpm --import https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
echo "done!"
fi
printf "Installing MariaDB and PDNS... "
if [ "`rpm -qa pdns pdns-backend-mysql MariaDB-server | wc -l`" -lt "3" ]; then
HAVE_PDNS=`rpm -qa pdns | wc -l`
HAVE_BACKEND=`rpm -qa pdns-backend-mysql | wc -l`
HAVE_MARIA=`rpm -qa MariaDB-server | wc -l`
if [ "$HAVE_PDNS" -eq "0" ]; then
DEPS="$DEPS pdns"
fi
if [ "$HAVE_BACKEND" -eq "0" ]; then
DEPS="$DEPS pdns-backend-mysql"
fi
if [ "$HAVE_MARIA" -eq "0" ]; then
DEPS="$DEPS MariaDB-server"
fi
yum install $DEPS --enablerepo=epel,mariadb -y -q 2>/dev/null 1>/dev/null
echo "done!"
else
echo "it wasn't necessary"
fi
printf "Adding MySQLd and PDNS to runlevels: $RUNLEVELS... "
chkconfig --levels $RUNLEVELS mysql on
chkconfig --levels $RUNLEVELS pdns on
echo "done!"
service mysql start
INTERJECT=`cat -n /etc/my.cnf.d/server.cnf | grep "\[mysqld\]" | awk '{print $1}'`
if [ "$HAVE_PASS" -eq "1" ]; then
mysqladmin -u root password $FEEDED_KEY
else
read -r -s -p "What should be the root MySQL pass? " FEEDED_KEY
echo ""
HAVE_PASS=1
mysqladmin -u root password $FEEDED_KEY
fi
printf "Fetching PDNS SQL database... "
curl http://files.soluslabs.com/solusvm/pdns/pdns.sql 2>/dev/null > pdns.sql.$JOB_PID
sed 's/type=InnoDB;/ENGINE\ =\ InnoDB;/' pdns.sql.$JOB_PID > pdns.sql
rm -f pdns.sql.$JOB_PID
echo "done!"
printf "Merging PDNS database into our MySQL... "
mysql -u root --password=$FEEDED_KEY < pdns.sql
rm -f pdns.sql
echo "done!"
printf "Altering PDNS config... "
sed 's/^launch=bind$/launch=gmysql/' /etc/pdns/pdns.conf > pdns.conf.$JOB_PID
mv pdns.conf.$JOB_PID /etc/pdns/pdns.conf
echo "gmysql-host=127.0.0.1" >> /etc/pdns/pdns.conf
echo "gmysql-user=root" >> /etc/pdns/pdns.conf
echo "gmysql-password=$FEEDED_KEY" >> /etc/pdns/pdns.conf
echo "gmysql-dbname=powerdns" >> /etc/pdns/pdns.conf
echo "done!"
service pdns start
printf "Altering iptables rules... "
IPT_RULE_NO=`iptables -L INPUT --line-number | tail -n+3 | tail -n-1 | awk '{print $1}'`
for ((IPT_COUNTER=IPT_RULE_NO; IPT_COUNTER > 0; IPT_COUNTER--)); do
IPT_RULE=`iptables -L INPUT | tail -n+3 | head -n$IPT_RULE_NO | tail -n1`
echo $IPT_RULE > ipt.$JOB_PID
IPT_RULE=`cat ipt.$JOB_PID`
rm -f ipt.$JOB_PID
if [ "$IPT_RULE" == "REJECT all -- anywhere anywhere reject-with icmp-host-prohibited" ]; then
iptables -D INPUT $IPT_COUNTER
fi
done
SSH_DUPES=`iptables -L INPUT | grep -E '22|ssh' | grep -v SSH | wc -l`
if [ "$SSH_DUPES" -ne "0" ]; then
for ((SSH_COUNTER=1; SSH_COUNTER <= $SSH_DUPES; SSH_COUNTER++)); do
iptables -D INPUT `iptables -L INPUT --line-number | grep -E '22|ssh' | grep -v SSH | head -n$SSH_COUNTER | tail -n1 | awk '{print $1}'`
done
fi
if ! iptables -L INPUT | grep -qE '53|domain'; then
iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
fi
if [ `iptables -L INPUT --line-number | grep SSH | wc -l` -eq "0" ]; then
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 30 --hitcount 4 --rttl --name SSH --rsource -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 30 --hitcount 3 --rttl --name SSH --rsource -j LOG --log-prefix "SSH brute force "
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --update --seconds 30 --hitcount 3 --rttl --name SSH --rsource -j REJECT --reject-with tcp-reset
fi
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
if [ "$ROLE" == "Master" ]; then
if ! iptables -L INPUT | grep -qE '3306|mysql'; then
iptables -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
fi
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
echo "done!"
printf "Granting permission to users to connect to master... "
echo "GRANT ALL ON powerdns.* TO 'root'@'$NS1_INET' IDENTIFIED BY '$FEEDED_KEY';" > mysql.cmd.$JOB_PID
printf "grant all privileges on *.* to 'root'@'$SOLUS_MANAGER' identified by '$FEEDED_KEY';" >> mysql.cmd.$JOB_PID
mysql -u root --password=$FEEDED_KEY < mysql.cmd.$JOB_PID
rm -f mysql.cmd.$JOB_PID
echo "done!"
printf "Editing /etc/my.cnf.d/server.cnf... "
head -n$INTERJECT /etc/my.cnf.d/server.cnf > server.cnf.$JOB_PID
echo "server-id=1" >> server.cnf.$JOB_PID
echo "log-bin=mariadb-bin" >> server.cnf.$JOB_PID
echo "log-bin-index=mariadb-bin.index" >> server.cnf.$JOB_PID
echo "expire-logs-days=10" >> server.cnf.$JOB_PID
echo "max-binlog-size=100M" >> server.cnf.$JOB_PID
echo "binlog-do-db=powerdns" >> server.cnf.$JOB_PID
tail -n+`expr $INTERJECT + 1` /etc/my.cnf.d/server.cnf >> server.cnf.$JOB_PID
mv server.cnf.$JOB_PID /etc/my.cnf.d/server.cnf
echo "done!"
read -r -s -p "Enter slave password: " USER_PASS
echo ""
printf "Preparing MySQL master setup command... "
echo "create user pdnsslave;" > mysql.cmd.$JOB_PID
echo "create user 'pdnsslave'@'*';" >> mysql.cmd.$JOB_PID
echo "grant replication slave on *.* to pdnsslave identified by '$USER_PASS';" >> mysql.cmd.$JOB_PID
printf "flush privileges;" >> mysql.cmd.$JOB_PID
echo "done!"
printf "Executing said command... "
mysql -u root --password=$FEEDED_KEY < mysql.cmd.$JOB_PID
echo "done!"
service pdns stop
service mysql stop
service mysql start
service pdns start
printf "Altering iptables rules... "
IPT_RULE_NO=`iptables -L INPUT --line-number | tail -n+3 | tail -n-1 | awk '{print $1}'`
for ((IPT_COUNTER=$IPT_RULE_NO; IPT_COUNTER > 0; IPT_COUNTER--)); do
IPT_RULE=`iptables -L INPUT | tail -n+3 | head -n$IPT_RULE_NO | tail -n1`
echo $IPT_RULE > ipt.$JOB_PID
IPT_RULE=`cat ipt.$JOB_PID`
rm -f ipt.$JOB_PID
if [ "$IPT_RULE" == "REJECT all -- anywhere anywhere reject-with icmp-host-prohibited" ]; then
iptables -D INPUT $IPT_COUNTER
fi
done
SSH_DUPES=`iptables -L INPUT | grep -E '22|ssh' | grep -v SSH | wc -l`
if [ "$SSH_DUPES" -ne "0" ]; then
for ((SSH_COUNTER=1; SSH_COUNTER <= $SSH_DUPES; SSH_COUNTER++)); do
iptables -D INPUT `iptables -L INPUT --line-number | grep -E '22|ssh' | grep -v SSH | head -n$SSH_COUNTER | tail -n1 | awk '{print $1}'`
done
fi
if ! iptables -L INPUT | grep -qE '3306|mysql'; then
iptables -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
fi
if ! iptables -L INPUT | grep -qE '53|domain'; then
iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
fi
if [ `iptables -L INPUT --line-number | grep SSH | wc -l` -eq "0" ]; then
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 30 --hitcount 4 --rttl --name SSH --rsource -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --rcheck --seconds 30 --hitcount 3 --rttl --name SSH --rsource -j LOG --log-prefix "SSH brute force "
iptables -A INPUT -p tcp -m tcp --dport 22 -m recent --update --seconds 30 --hitcount 3 --rttl --name SSH --rsource -j REJECT --reject-with tcp-reset
fi
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
echo "done!"
service iptables save
mysql -u root --password=$FEEDED_KEY -e "show master status \G"
elif [ "$ROLE" == "Slave" ]; then
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
echo "done!"
while [ "$NAN" -eq "1" ]; do
read -r -p "What server ID should this host have? [2 or greater] " SLAVE_ID
if [[ $SLAVE_ID =~ $NUMREGEX ]] && [ $SLAVE_ID -gt 1 ]; then
NAN=0
printf "Thanks! Now, configuring my.cnf for slave... "
else
echo "This is not a valid number greater than 2"
fi
done
head -n$INTERJECT /etc/my.cnf.d/server.cnf > server.cnf.$JOB_PID
echo "server-id=$SLAVE_ID" >> server.cnf.$JOB_PID
echo "relay-log=slave-relay-bin" >> server.cnf.$JOB_PID
echo "relay-log-index=slave-relay-bin.index" >> server.cnf.$JOB_PID
echo "replicate-do-db=powerdns" >> server.cnf.$JOB_PID
tail -n+`expr $INTERJECT + 1` /etc/my.cnf.d/server.cnf >> server.cnf.$JOB_PID
mv server.cnf.$JOB_PID /etc/my.cnf.d/server.cnf
echo "done!"
service mysql restart
echo "Continue only if you have configured your master PDNS correctly!"
read -r -p "What was the file number? mariadb-bin." INDEX
read -r -p "And what was the position? " POSITION
read -r -s -p "Enter slave password: " USER_PASS
echo ""
echo "change master to master_host='$NS1_INET', master_user='pdnsslave', master_password='$USER_PASS', master_log_file='mariadb-bin.$INDEX', master_log_pos=$POSITION, master_connect_retry=60;" > mysql.cmd.$JOB_PID
printf "Preparing SQL command... "
echo "change master to master_host='$NS1_INET', master_user='pdnsslave', master_password='$USER_PASS', master_log_file='mariadb-bin.$INDEX', master_log_pos=$POSITION, master_connect_retry=60;" > mysql.cmd.$JOB_PID
printf "start slave;" >> mysql.cmd.$JOB_PID
echo "done!"
mysql -u root --password=$FEEDED_KEY < mysql.cmd.$JOB_PID
mysql -u root --password=$FEEDED_KEY -e "show slave status \G"
rm -f mysql.cmd.$JOB_PID
else
echo "Congratulations. You somehow tricked bash."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment