mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
dnssec: use RSASHA256 keys for .email domains
This commit is contained in:
parent
ba33669a62
commit
4ae76aa2dd
@ -479,8 +479,18 @@ zone:
|
|||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
|
def dnssec_choose_algo(domain, env):
|
||||||
|
if domain.endswith(".email"):
|
||||||
|
# At least at GoDaddy, this is the only algorithm supported.
|
||||||
|
return "RSASHA256"
|
||||||
|
|
||||||
|
# For any domain we were able to sign before, don't change the algorithm
|
||||||
|
# on existing users. We'll probably want to migrate to SHA256 later.
|
||||||
|
return "RSASHA1-NSEC3-SHA1"
|
||||||
|
|
||||||
def sign_zone(domain, zonefile, env):
|
def sign_zone(domain, zonefile, env):
|
||||||
dnssec_keys = load_env_vars_from_file(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/keys.conf'))
|
algo = dnssec_choose_algo(domain, env)
|
||||||
|
dnssec_keys = load_env_vars_from_file(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/%s.conf' % algo))
|
||||||
|
|
||||||
# In order to use the same keys for all domains, we have to generate
|
# In order to use the same keys for all domains, we have to generate
|
||||||
# a new .key file with a DNSSEC record for the specific domain. We
|
# a new .key file with a DNSSEC record for the specific domain. We
|
||||||
|
@ -210,14 +210,15 @@ def check_dnssec(domain, env, dns_zonefiles, is_checking_primary=False):
|
|||||||
|
|
||||||
# Some registrars may want the public key so they can compute the digest. The DS
|
# Some registrars may want the public key so they can compute the digest. The DS
|
||||||
# record that we suggest using is for the KSK (and that's how the DS records were generated).
|
# record that we suggest using is for the KSK (and that's how the DS records were generated).
|
||||||
dnssec_keys = load_env_vars_from_file(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/keys.conf'))
|
alg_name_map = { '7': 'RSASHA1-NSEC3-SHA1', '8': 'RSASHA256' }
|
||||||
|
dnssec_keys = load_env_vars_from_file(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/%s.conf' % alg_name_map[ds_alg]))
|
||||||
dnsssec_pubkey = open(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/' + dnssec_keys['KSK'] + '.key')).read().split("\t")[3].split(" ")[3]
|
dnsssec_pubkey = open(os.path.join(env['STORAGE_ROOT'], 'dns/dnssec/' + dnssec_keys['KSK'] + '.key')).read().split("\t")[3].split(" ")[3]
|
||||||
|
|
||||||
# Query public DNS for the DS record at the registrar.
|
# Query public DNS for the DS record at the registrar.
|
||||||
ds = query_dns(domain, "DS", nxdomain=None)
|
ds = query_dns(domain, "DS", nxdomain=None)
|
||||||
ds_looks_valid = ds and len(ds.split(" ")) == 4
|
ds_looks_valid = ds and len(ds.split(" ")) == 4
|
||||||
if ds_looks_valid: ds = ds.split(" ")
|
if ds_looks_valid: ds = ds.split(" ")
|
||||||
if ds_looks_valid and ds[0] == ds_keytag and ds[1] == '7' and ds[3] == digests.get(ds[2]):
|
if ds_looks_valid and ds[0] == ds_keytag and ds[1] == ds_alg and ds[3] == digests.get(ds[2]):
|
||||||
if is_checking_primary: return
|
if is_checking_primary: return
|
||||||
env['out'].print_ok("DNSSEC 'DS' record is set correctly at registrar.")
|
env['out'].print_ok("DNSSEC 'DS' record is set correctly at registrar.")
|
||||||
else:
|
else:
|
||||||
@ -236,7 +237,9 @@ def check_dnssec(domain, env, dns_zonefiles, is_checking_primary=False):
|
|||||||
env['out'].print_line("")
|
env['out'].print_line("")
|
||||||
env['out'].print_line("Key Tag: " + ds_keytag + ("" if not ds_looks_valid or ds[0] == ds_keytag else " (Got '%s')" % ds[0]))
|
env['out'].print_line("Key Tag: " + ds_keytag + ("" if not ds_looks_valid or ds[0] == ds_keytag else " (Got '%s')" % ds[0]))
|
||||||
env['out'].print_line("Key Flags: KSK")
|
env['out'].print_line("Key Flags: KSK")
|
||||||
env['out'].print_line("Algorithm: 7 / RSASHA1-NSEC3-SHA1" + ("" if not ds_looks_valid or ds[1] == '7' else " (Got '%s')" % ds[1]))
|
env['out'].print_line(
|
||||||
|
("Algorithm: %s / %s" % (ds_alg, alg_name_map[ds_alg]))
|
||||||
|
+ ("" if not ds_looks_valid or ds[1] == ds_alg else " (Got '%s')" % ds[1]))
|
||||||
# see http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
# see http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||||
env['out'].print_line("Digest Type: 2 / SHA-256")
|
env['out'].print_line("Digest Type: 2 / SHA-256")
|
||||||
# http://www.ietf.org/assignments/ds-rr-types/ds-rr-types.xml
|
# http://www.ietf.org/assignments/ds-rr-types/ds-rr-types.xml
|
||||||
|
27
setup/dns.sh
27
setup/dns.sh
@ -36,25 +36,39 @@ sudo mkdir -p /var/run/nsd
|
|||||||
# Create DNSSEC signing keys.
|
# Create DNSSEC signing keys.
|
||||||
|
|
||||||
mkdir -p "$STORAGE_ROOT/dns/dnssec";
|
mkdir -p "$STORAGE_ROOT/dns/dnssec";
|
||||||
if [ ! -f "$STORAGE_ROOT/dns/dnssec/keys.conf" ]; then
|
|
||||||
echo "Generating DNSSEC signing keys. This may take a few minutes..."
|
# TLDs don't all support the same algorithms, so we'll generate keys using a few
|
||||||
|
# different algorithms.
|
||||||
|
#
|
||||||
|
# Supports RSASHA1-NSEC3-SHA1 (didn't test with RSASHA256):
|
||||||
|
# .info and .me.
|
||||||
|
#
|
||||||
|
# Requires RSASHA256
|
||||||
|
# .email
|
||||||
|
FIRST=1
|
||||||
|
for algo in RSASHA1-NSEC3-SHA1 RSASHA256; do
|
||||||
|
if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then
|
||||||
|
if [ $FIRST == 1 ]; then
|
||||||
|
echo "Generating DNSSEC signing keys. This may take a few minutes..."
|
||||||
|
FIRST=0
|
||||||
|
fi
|
||||||
|
|
||||||
# Create the Key-Signing Key (KSK) (-k) which is the so-called
|
# Create the Key-Signing Key (KSK) (-k) which is the so-called
|
||||||
# Secure Entry Point. Use a NSEC3-compatible algorithm (best
|
# Secure Entry Point. Use a NSEC3-compatible algorithm (best
|
||||||
# practice), and a nice and long keylength. The domain name we
|
# practice), and a nice and long keylength. The domain name we
|
||||||
# provide ("_domain_") doesn't matter -- we'll use the same
|
# provide ("_domain_") doesn't matter -- we'll use the same
|
||||||
# keys for all our domains.
|
# keys for all our domains.
|
||||||
KSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -a RSASHA1-NSEC3-SHA1 -b 2048 -k _domain_);
|
KSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -a $algo -b 2048 -k _domain_);
|
||||||
|
|
||||||
# Now create a Zone-Signing Key (ZSK) which is expected to be
|
# Now create a Zone-Signing Key (ZSK) which is expected to be
|
||||||
# rotated more often than a KSK, although we have no plans to
|
# rotated more often than a KSK, although we have no plans to
|
||||||
# rotate it (and doing so would be difficult to do without
|
# rotate it (and doing so would be difficult to do without
|
||||||
# disturbing DNS availability.) Omit '-k' and use a shorter key.
|
# disturbing DNS availability.) Omit '-k' and use a shorter key.
|
||||||
ZSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -a RSASHA1-NSEC3-SHA1 -b 1024 _domain_);
|
ZSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -a $algo -b 1024 _domain_);
|
||||||
|
|
||||||
# These generate two sets of files like:
|
# These generate two sets of files like:
|
||||||
#
|
#
|
||||||
# * `K_domain_.+007+08882.ds`: DS record to provide to domain name registrar
|
# * `K_domain_.+007+08882.ds`: DS record normally provided to domain name registrar (but it's actually invalid with "_domain_")
|
||||||
# * `K_domain_.+007+08882.key`: public key (goes into DS record & upstream DNS provider like your registrar)
|
# * `K_domain_.+007+08882.key`: public key (goes into DS record & upstream DNS provider like your registrar)
|
||||||
# * `K_domain_.+007+08882.private`: private key (secret!)
|
# * `K_domain_.+007+08882.private`: private key (secret!)
|
||||||
|
|
||||||
@ -62,11 +76,12 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/keys.conf" ]; then
|
|||||||
# options. So we'll store the names of the files we just generated.
|
# options. So we'll store the names of the files we just generated.
|
||||||
# We might have multiple keys down the road. This will identify
|
# We might have multiple keys down the road. This will identify
|
||||||
# what keys are the current keys.
|
# what keys are the current keys.
|
||||||
cat > $STORAGE_ROOT/dns/dnssec/keys.conf << EOF;
|
cat > $STORAGE_ROOT/dns/dnssec/$algo.conf << EOF;
|
||||||
KSK=$KSK
|
KSK=$KSK
|
||||||
ZSK=$ZSK
|
ZSK=$ZSK
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Force the dns_update script to be run every day to re-sign zones for DNSSEC.
|
# Force the dns_update script to be run every day to re-sign zones for DNSSEC.
|
||||||
cat > /etc/cron.daily/mailinabox-dnssec << EOF;
|
cat > /etc/cron.daily/mailinabox-dnssec << EOF;
|
||||||
|
@ -60,6 +60,13 @@ def migration_5(env):
|
|||||||
# The secret key for encrypting backups was world readable. Fix here.
|
# The secret key for encrypting backups was world readable. Fix here.
|
||||||
os.chmod(os.path.join(env["STORAGE_ROOT"], 'backup/secret_key.txt'), 0o600)
|
os.chmod(os.path.join(env["STORAGE_ROOT"], 'backup/secret_key.txt'), 0o600)
|
||||||
|
|
||||||
|
def migration_6(env):
|
||||||
|
# We now will generate multiple DNSSEC keys for different algorithms, since TLDs may
|
||||||
|
# not support them all. .email only supports RSA/SHA-256. Rename the keys.conf file
|
||||||
|
# to be algorithm-specific.
|
||||||
|
basepath = os.path.join(env["STORAGE_ROOT"], 'dns/dnssec')
|
||||||
|
shutil.move(os.path.join(basepath, 'keys.conf'), os.path.join(basepath, 'RSASHA1-NSEC3-SHA1.conf'))
|
||||||
|
|
||||||
def get_current_migration():
|
def get_current_migration():
|
||||||
ver = 0
|
ver = 0
|
||||||
while True:
|
while True:
|
||||||
|
Loading…
Reference in New Issue
Block a user