diff --git a/Vagrantfile b/Vagrantfile index 861f276c..9576c27e 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -19,6 +19,7 @@ Vagrant.configure("2") do |config| # subdomain on our justtesting.email domain so we can get # started quickly. export PUBLIC_IP=auto + export PUBLIC_IPV6=auto export PUBLIC_HOSTNAME=auto-easy export CSR_COUNTRY=US diff --git a/management/dns_update.py b/management/dns_update.py index 7ac9fb2f..66a2bf6c 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -60,9 +60,13 @@ def build_zone(domain, env): records.append((None, "NS", "ns1.%s." % env["PUBLIC_HOSTNAME"])) records.append((None, "NS", "ns2.%s." % env["PUBLIC_HOSTNAME"])) records.append((None, "A", env["PUBLIC_IP"])) + if env.get('PUBLIC_IPV6'): + records.append((None, "AAAA", env["PUBLIC_IPV6"])) records.append((None, "MX", "10 %s." % env["PUBLIC_HOSTNAME"])) records.append((None, "TXT", '"v=spf1 mx -all"')) records.append(("www", "A", env["PUBLIC_IP"])) + if env.get('PUBLIC_IPV6'): + records.append(("www", "AAAA", env["PUBLIC_IPV6"])) # In PUBLIC_HOSTNAME, also define ns1 and ns2. if domain == env["PUBLIC_HOSTNAME"]: diff --git a/setup/functions.sh b/setup/functions.sh index 1a18b28d..210113ac 100644 --- a/setup/functions.sh +++ b/setup/functions.sh @@ -39,11 +39,19 @@ function get_default_publicip { get_publicip_from_web_service || get_publicip_fallback } +function get_default_publicipv6 { + get_publicipv6_from_web_service || get_publicipv6_fallback +} + function get_publicip_from_web_service { # This seems to be the most reliable way to determine the # machine's public IP address: asking a very nice web API # for how they see us. Thanks go out to icanhazip.com. - curl --fail --silent icanhazip.com 2>/dev/null + curl -4 --fail --silent icanhazip.com 2>/dev/null +} + +function get_publicipv6_from_web_service { + curl -6 --fail --silent icanhazip.com 2>/dev/null } function get_publicip_fallback { @@ -53,17 +61,39 @@ function get_publicip_fallback { # have multiple addresses if it has multiple network adapters. set -- $(hostname --ip-address 2>/dev/null) \ $(hostname --all-ip-addresses 2>/dev/null) - while (( $# )) && is_loopback_ip "$1"; do + while (( $# )) && { ! is_ipv4 "$1" || is_loopback_ip "$1"; }; do shift done printf '%s\n' "$1" # return this value } +function get_publicipv6_fallback { + set -- $(hostname --ip-address 2>/dev/null) \ + $(hostname --all-ip-addresses 2>/dev/null) + while (( $# )) && { ! is_ipv6 "$1" || is_loopback_ipv6 "$1"; }; do + shift + done + printf '%s\n' "$1" # return this value +} + +function is_ipv4 { + # helper for get_publicip_fallback + [[ "$1" == *.*.*.* ]] +} + +function is_ipv6 { + [[ "$1" == *:*:* ]] +} + function is_loopback_ip { # helper for get_publicip_fallback [[ "$1" == 127.* ]] } +function is_loopback_ipv6 { + [[ "$1" == ::1 ]] +} + function ufw_allow { if [ -z "$DISABLE_FIREWALL" ]; then # ufw has completely unhelpful output diff --git a/setup/start.sh b/setup/start.sh index 51a1ebdd..301adead 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -24,6 +24,11 @@ fi # Gather information from the user about the hostname and public IP # address of this host. if [ -z "$PUBLIC_HOSTNAME" ]; then + if [ -z "$DEFAULT_PUBLIC_HOSTNAME" ]; then + # set a default on first run + DEFAULT_PUBLIC_HOSTNAME=`get_default_hostname` + fi + echo echo "Enter the hostname you want to assign to this machine." echo "We've guessed a value. Just backspace it if it's wrong." @@ -31,27 +36,35 @@ if [ -z "$PUBLIC_HOSTNAME" ]; then echo "be similar." echo - if [ -z "$DEFAULT_PUBLIC_HOSTNAME" ]; then - # set a default on first run - DEFAULT_PUBLIC_HOSTNAME=`get_default_hostname` - fi - read -e -i "$DEFAULT_PUBLIC_HOSTNAME" -p "Hostname: " PUBLIC_HOSTNAME fi if [ -z "$PUBLIC_IP" ]; then + if [ -z "$DEFAULT_PUBLIC_IP" ]; then + # set a default on first run + DEFAULT_PUBLIC_IP=`get_default_publicip` + fi + echo echo "Enter the public IP address of this machine, as given to" echo "you by your ISP. We've guessed a value, but just backspace" echo "it if it's wrong." echo - if [ -z "$DEFAULT_PUBLIC_IP" ]; then + read -e -i "$DEFAULT_PUBLIC_IP" -p "Public IP: " PUBLIC_IP +fi + +if [ -z "$PUBLIC_IPV6" ]; then + if [ -z "$DEFAULT_PUBLIC_IPV6" ]; then # set a default on first run - DEFAULT_PUBLIC_IP=`get_default_publicip` + DEFAULT_PUBLIC_IPV6=`get_default_publicipv6` fi - read -e -i "$DEFAULT_PUBLIC_IP" -p "Public IP: " PUBLIC_IP + echo + echo "(Optional) Enter the IPv6 address of this machine. Leave blank" + echo " if the machine does not have an IPv6 address." + + read -e -i "$DEFAULT_PUBLIC_IPV6" -p "Public IPv6: " PUBLIC_IPV6 fi if [ -z "$CSR_COUNTRY" ]; then @@ -70,12 +83,17 @@ if [ -z "$CSR_COUNTRY" ]; then fi # Automatic configuration, e.g. as used in our Vagrant configuration. -if [ "$PUBLIC_IP" == "auto" ]; then +if [ "$PUBLIC_IP" = "auto" ]; then # Use a public API to get our public IP address. PUBLIC_IP=`get_default_publicip` echo "IP Address: $PUBLIC_IP" fi -if [ "$PUBLIC_HOSTNAME" == "auto-easy" ]; then +if [ "$PUBLIC_IPV6" = "auto" ]; then + # Use a public API to get our public IP address. + PUBLIC_IPV6=`get_default_publicipv6` + echo "IPv6 Address: $PUBLIC_IPV6" +fi +if [ "$PUBLIC_HOSTNAME" = "auto-easy" ]; then # Generate a probably-unique subdomain under our justtesting.email domain. PUBLIC_HOSTNAME=m`get_default_publicip | sha1sum | cut -c1-5`.justtesting.email echo "Public Hostname: $PUBLIC_HOSTNAME" @@ -97,6 +115,7 @@ cat > /etc/mailinabox.conf << EOF; STORAGE_ROOT=$STORAGE_ROOT PUBLIC_HOSTNAME=$PUBLIC_HOSTNAME PUBLIC_IP=$PUBLIC_IP +PUBLIC_IPV6=$PUBLIC_IPV6 CSR_COUNTRY=$CSR_COUNTRY EOF