diff --git a/README.md b/README.md index 7ab19178..2f25970b 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ Then launch a new instance. We're creating a m1.small instance --- it's the smal source ec2/start_instance.sh It will wait until the instance is available. + +You'll probably want to associate it with an Elastic IP. If you do, you'll need to update the INSTANCE_IP variable. Configure the server: diff --git a/ec2/start_instance.sh b/ec2/start_instance.sh index 93b39ab6..57ba57f5 100644 --- a/ec2/start_instance.sh +++ b/ec2/start_instance.sh @@ -7,7 +7,8 @@ UBUNTU_CONFIG="us-east-1 13.04 amd64 instance-store" export AMI=`curl -s http://cloud-images.ubuntu.com/locator/ec2/releasesTable | python3 tools/get_ubuntu_ami.py $UBUNTU_CONFIG` ec2-create-group -d "mailinabox" "mailinabox" -for PORT in 25 587 993; do ec2-authorize mailinabox -P tcp -p $PORT -s 0.0.0.0/0; done +for PORT in 25 53 587 993; do ec2-authorize mailinabox -P tcp -p $PORT -s 0.0.0.0/0; done +for PORT in 53; do ec2-authorize mailinabox -P udp -p $PORT -s 0.0.0.0/0; done ec2run $AMI -k $EC2_KEYPAIR_NAME -t m1.small -z $AWS_AZ -g mailinabox > instance.info export INSTANCE=`cat instance.info | grep INSTANCE | awk {'print $2'}` diff --git a/scripts/dkim.sh b/scripts/dkim.sh new file mode 100644 index 00000000..cd8fb81b --- /dev/null +++ b/scripts/dkim.sh @@ -0,0 +1,45 @@ +# Install OpenDKIM. +# +# After this, you'll still need to run dns_update to get the DKIM +# signature in the DNS zones. + +apt-get install -q -y opendkim opendkim-tools + +mkdir -p /etc/opendkim; +mkdir -p $STORAGE_ROOT/mail/dkim + +echo "127.0.0.1" > /etc/opendkim/TrustedHosts + +if grep -q "ExternalIgnoreList" /etc/opendkim.conf; then + true; # already done +else + cat >> /etc/opendkim.conf << EOF; +MinimumKeyBits 1024 +ExternalIgnoreList refile:/etc/opendkim/TrustedHosts +InternalHosts refile:/etc/opendkim/TrustedHosts +KeyTable refile:/etc/opendkim/KeyTable +SigningTable refile:/etc/opendkim/SigningTable +Socket inet:8891@localhost +RequireSafeKeys false +EOF +fi + +# Create a new DKIM key if we don't have one already. +if [ ! -z "$STORAGE_ROOT/mail/dkim/mail.private" ]; then + # Should we specify -h rsa-sha256? + opendkim-genkey -r -s mail -D $STORAGE_ROOT/mail/dkim +fi + +chown -R opendkim:opendkim $STORAGE_ROOT/mail/dkim +chmod go-rwx $STORAGE_ROOT/mail/dkim + +# add OpenDKIM as a milter to postfix. Be careful. If we add other milters +# later, it needs to be concatenated on the smtpd_milters line. +tools/editconf.py /etc/postfix/main.cf \ + smtpd_milters=inet:127.0.0.1:8891 \ + non_smtpd_milters=\$smtpd_milters \ + milter_default_action=accept + +service opendkim restart +service postfix restart + diff --git a/scripts/dns.sh b/scripts/dns.sh new file mode 100644 index 00000000..b7fa2a1c --- /dev/null +++ b/scripts/dns.sh @@ -0,0 +1,36 @@ +# Configures a DNS server using nsd. +# +# After running this script, you also must run scripts/dns_update.sh, +# and any time a zone file is added/changed/removed. It should be +# run after DKIM is configured, however. + +apt-get -qq -y install nsd3 + +if [ -z "$PUBLIC_HOSTNAME" ]; then + PUBLIC_HOSTNAME=example.org +fi + +if [ -z "$PUBLIC_IP" ]; then + # works on EC2 only... + PUBLIC_IP=`wget -q -O- http://instance-data/latest/meta-data/public-ipv4` +fi + +sudo mkdir -p /var/run/nsd3 +mkdir -p "$STORAGE_ROOT/dns"; + +# Store our desired IP address (to put in the zone files) for later. + +echo $PUBLIC_IP > $STORAGE_ROOT/dns/our_ip + +# Create the default zone if it doesn't exist. + +if [ ! -f "$STORAGE_ROOT/dns/$PUBLIC_HOSTNAME.txt" ]; then + # can be an empty file, defaults are applied elsewhere + cat > "$STORAGE_ROOT/dns/$PUBLIC_HOSTNAME.txt" << EOF; +EOF +fi + +chown -R ubuntu.ubuntu $STORAGE_ROOT/dns + +ufw allow domain + diff --git a/scripts/dns_update.sh b/scripts/dns_update.sh new file mode 100644 index 00000000..05091d53 --- /dev/null +++ b/scripts/dns_update.sh @@ -0,0 +1,89 @@ +# Create nsd.conf and zone files, and updates the OpenDKIM signing tables. + +PUBLIC_IP=`cat $STORAGE_ROOT/dns/our_ip` + +# Create the top of nsd.conf. + +cat > /etc/nsd3/nsd.conf << EOF; +server: + hide-version: yes + + # identify the server (CH TXT ID.SERVER entry). + identity: "" + + # The directory for zonefile: files. + zonesdir: "/etc/nsd3/zones" + +# ZONES +EOF + +# For every zone file in our dns directory, build a proper zone +# file and mention it in nsd.conf. And add information to the +# OpenDKIM signing tables. + +mkdir -p /etc/nsd3/zones; + +truncate --size 0 /etc/opendkim/KeyTable +truncate --size 0 /etc/opendkim/SigningTable + +for fn in $STORAGE_ROOT/dns/*.txt; do + fn2=`basename $fn` + zone=`echo $fn2 | sed "s/.txt\$//"` + + # If the zone file exists, increment the serial number. + # TODO: This needs to be done better so that the existing serial number is + # persisted in the storage area. + serial=`date +"%Y%m%d00"` + if [ -f /etc/nsd3/zones/$fn2 ]; then + existing_serial=`grep "serial number" /etc/nsd3/zones/$fn2 | sed "s/; serial number//"` + if [ ! -z "$existing_serial" ]; then + serial=`echo $existing_serial + 1 | bc` + fi + fi + + cat > /etc/nsd3/zones/$fn2 << EOF; +\$ORIGIN $zone. ; default zone domain +\$TTL 86400 ; default time to live + +@ IN SOA ns1.$zone. domain_contact.$zone. ( + $serial ; serial number + 28800 ; Refresh + 7200 ; Retry + 864000 ; Expire + 86400 ; Min TTL + ) + + NS ns1.$zone. + IN A $PUBLIC_IP + MX 10 mail.$zone. + + 300 TXT "v=spf1 mx -all" + +mail IN A $PUBLIC_IP +EOF + + # If OpenDKIM is set up, append that information to the zone. + if [ -f "$STORAGE_ROOT/mail/dkim/mail.txt" ]; then + cat "$STORAGE_ROOT/mail/dkim/mail.txt" >> /etc/nsd3/zones/$fn2; + fi + + cat >> /etc/nsd3/nsd.conf << EOF; +zone: + name: $zone + zonefile: $fn2 +EOF + + # OpenDKIM + + echo "$zone $zone:mail:$STORAGE_ROOT/mail/dkim/mail.private" >> /etc/opendkim/KeyTable + echo "*@$zone $zone" >> /etc/opendkim/SigningTable + +done + +# Kick nsd. +service nsd3 rebuild +service nsd3 restart # ensure it is running + +# Kick opendkim. +service opendkim restart + diff --git a/scripts/index.sh b/scripts/index.sh index 3e00c593..af6abbc1 100644 --- a/scripts/index.sh +++ b/scripts/index.sh @@ -1,3 +1,6 @@ . scripts/system.sh +. scripts/dns.sh . scripts/mail.sh +. scripts/dkim.sh +. scripts/dns_update.sh diff --git a/scripts/system.sh b/scripts/system.sh index a72431e2..1e8cd6d1 100755 --- a/scripts/system.sh +++ b/scripts/system.sh @@ -20,7 +20,6 @@ apt-get install -q -y ntp fail2ban # Turn on the firewall. First allow incoming SSH, then turn on the firewall. Additional open # ports will be set up in the scripts that set up those services. ufw allow ssh -#ufw allow domain #ufw allow http #ufw allow https ufw --force enable diff --git a/tests/smtp.py b/tests/smtp.py index 8761b899..ba3f0b02 100644 --- a/tests/smtp.py +++ b/tests/smtp.py @@ -1,6 +1,6 @@ import smtplib, sys, os -fromaddr = "testuser@testdomain.com" +fromaddr = "testuser@" + os.environ.get("DOMAIN", "testdomain.com") msg = """From: %s To: %s @@ -10,7 +10,7 @@ This is a test message.""" % (fromaddr, sys.argv[1]) server = smtplib.SMTP(os.environ["INSTANCE_IP"], 587) server.set_debuglevel(1) server.starttls() -server.login("testuser@testdomain.com", "testpw") +server.login(fromaddr, "testpw") server.sendmail(fromaddr, [sys.argv[1]], msg) server.quit()