Created
December 2, 2014 08:38
-
-
Save grepwood/0cf3286d6491f57a7a1f to your computer and use it in GitHub Desktop.
Sets up PowerDNS on a host in slave or master mode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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