Support dual-stack IPv4/IPv6 mail servers
Addresses #3 Added support by adding parallel code wherever `$PUBLIC_IP` was used. Providing an IPv6 address is completely optional. Playing around on my IPv6-enabled mail server revealed that — before this change — mailinabox might try to use an IPv6 address as the value for `$PUBLIC_IP`, which wouldn't work out well.
This commit is contained in:
parent
ca34c1b1ae
commit
ae67409603
|
@ -19,6 +19,7 @@ Vagrant.configure("2") do |config|
|
||||||
# subdomain on our justtesting.email domain so we can get
|
# subdomain on our justtesting.email domain so we can get
|
||||||
# started quickly.
|
# started quickly.
|
||||||
export PUBLIC_IP=auto
|
export PUBLIC_IP=auto
|
||||||
|
export PUBLIC_IPV6=auto
|
||||||
export PUBLIC_HOSTNAME=auto-easy
|
export PUBLIC_HOSTNAME=auto-easy
|
||||||
export CSR_COUNTRY=US
|
export CSR_COUNTRY=US
|
||||||
|
|
||||||
|
|
|
@ -60,9 +60,13 @@ def build_zone(domain, env):
|
||||||
records.append((None, "NS", "ns1.%s." % env["PUBLIC_HOSTNAME"]))
|
records.append((None, "NS", "ns1.%s." % env["PUBLIC_HOSTNAME"]))
|
||||||
records.append((None, "NS", "ns2.%s." % env["PUBLIC_HOSTNAME"]))
|
records.append((None, "NS", "ns2.%s." % env["PUBLIC_HOSTNAME"]))
|
||||||
records.append((None, "A", env["PUBLIC_IP"]))
|
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, "MX", "10 %s." % env["PUBLIC_HOSTNAME"]))
|
||||||
records.append((None, "TXT", '"v=spf1 mx -all"'))
|
records.append((None, "TXT", '"v=spf1 mx -all"'))
|
||||||
records.append(("www", "A", env["PUBLIC_IP"]))
|
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.
|
# In PUBLIC_HOSTNAME, also define ns1 and ns2.
|
||||||
if domain == env["PUBLIC_HOSTNAME"]:
|
if domain == env["PUBLIC_HOSTNAME"]:
|
||||||
|
|
|
@ -39,11 +39,19 @@ function get_default_publicip {
|
||||||
get_publicip_from_web_service || get_publicip_fallback
|
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 {
|
function get_publicip_from_web_service {
|
||||||
# This seems to be the most reliable way to determine the
|
# This seems to be the most reliable way to determine the
|
||||||
# machine's public IP address: asking a very nice web API
|
# machine's public IP address: asking a very nice web API
|
||||||
# for how they see us. Thanks go out to icanhazip.com.
|
# 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 {
|
function get_publicip_fallback {
|
||||||
|
@ -53,17 +61,39 @@ function get_publicip_fallback {
|
||||||
# have multiple addresses if it has multiple network adapters.
|
# have multiple addresses if it has multiple network adapters.
|
||||||
set -- $(hostname --ip-address 2>/dev/null) \
|
set -- $(hostname --ip-address 2>/dev/null) \
|
||||||
$(hostname --all-ip-addresses 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
|
shift
|
||||||
done
|
done
|
||||||
printf '%s\n' "$1" # return this value
|
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 {
|
function is_loopback_ip {
|
||||||
# helper for get_publicip_fallback
|
# helper for get_publicip_fallback
|
||||||
[[ "$1" == 127.* ]]
|
[[ "$1" == 127.* ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_loopback_ipv6 {
|
||||||
|
[[ "$1" == ::1 ]]
|
||||||
|
}
|
||||||
|
|
||||||
function ufw_allow {
|
function ufw_allow {
|
||||||
if [ -z "$DISABLE_FIREWALL" ]; then
|
if [ -z "$DISABLE_FIREWALL" ]; then
|
||||||
# ufw has completely unhelpful output
|
# ufw has completely unhelpful output
|
||||||
|
|
|
@ -54,6 +54,19 @@ if [ -z "$PUBLIC_IP" ]; then
|
||||||
read -e -i "$DEFAULT_PUBLIC_IP" -p "Public IP: " PUBLIC_IP
|
read -e -i "$DEFAULT_PUBLIC_IP" -p "Public IP: " PUBLIC_IP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PUBLIC_IPV6" ]; then
|
||||||
|
echo
|
||||||
|
echo "(Optional) Enter the IPv6 address of this machine. Leave blank"
|
||||||
|
echo " if the machine does not have an IPv6 address."
|
||||||
|
|
||||||
|
if [ -z "$DEFAULT_PUBLIC_IPV6" ]; then
|
||||||
|
# set a default on first run
|
||||||
|
DEFAULT_PUBLIC_IPV6=`get_default_publicipv6`
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -e -i "$DEFAULT_PUBLIC_IPV6" -p "Public IPv6: " PUBLIC_IPV6
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$CSR_COUNTRY" ]; then
|
if [ -z "$CSR_COUNTRY" ]; then
|
||||||
echo
|
echo
|
||||||
echo "Enter the two-letter, uppercase country code for where you"
|
echo "Enter the two-letter, uppercase country code for where you"
|
||||||
|
@ -70,12 +83,17 @@ if [ -z "$CSR_COUNTRY" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Automatic configuration, e.g. as used in our Vagrant configuration.
|
# 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.
|
# Use a public API to get our public IP address.
|
||||||
PUBLIC_IP=`get_default_publicip`
|
PUBLIC_IP=`get_default_publicip`
|
||||||
echo "IP Address: $PUBLIC_IP"
|
echo "IP Address: $PUBLIC_IP"
|
||||||
fi
|
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.
|
# Generate a probably-unique subdomain under our justtesting.email domain.
|
||||||
PUBLIC_HOSTNAME=m`get_default_publicip | sha1sum | cut -c1-5`.justtesting.email
|
PUBLIC_HOSTNAME=m`get_default_publicip | sha1sum | cut -c1-5`.justtesting.email
|
||||||
echo "Public Hostname: $PUBLIC_HOSTNAME"
|
echo "Public Hostname: $PUBLIC_HOSTNAME"
|
||||||
|
@ -97,6 +115,7 @@ cat > /etc/mailinabox.conf << EOF;
|
||||||
STORAGE_ROOT=$STORAGE_ROOT
|
STORAGE_ROOT=$STORAGE_ROOT
|
||||||
PUBLIC_HOSTNAME=$PUBLIC_HOSTNAME
|
PUBLIC_HOSTNAME=$PUBLIC_HOSTNAME
|
||||||
PUBLIC_IP=$PUBLIC_IP
|
PUBLIC_IP=$PUBLIC_IP
|
||||||
|
PUBLIC_IPV6=$PUBLIC_IPV6
|
||||||
CSR_COUNTRY=$CSR_COUNTRY
|
CSR_COUNTRY=$CSR_COUNTRY
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue