mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-25 02:47:04 +00:00
have nsd bind to the network interaface that is connected to the Internet, rather than all non-loopback network interfaces
hopefully fixes #121; thanks for the help @sfPlayer1
This commit is contained in:
parent
c74bef12d2
commit
168c06939d
@ -104,7 +104,7 @@ def do_dns_update(env):
|
|||||||
zonefiles[i][1] += ".signed"
|
zonefiles[i][1] += ".signed"
|
||||||
|
|
||||||
# Write the main nsd.conf file.
|
# Write the main nsd.conf file.
|
||||||
if write_nsd_conf(zonefiles):
|
if write_nsd_conf(zonefiles, env):
|
||||||
# Make sure updated_domains contains *something* if we wrote an updated
|
# Make sure updated_domains contains *something* if we wrote an updated
|
||||||
# nsd.conf so that we know to restart nsd.
|
# nsd.conf so that we know to restart nsd.
|
||||||
if len(updated_domains) == 0:
|
if len(updated_domains) == 0:
|
||||||
@ -383,7 +383,7 @@ $TTL 86400 ; default time to live
|
|||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
def write_nsd_conf(zonefiles):
|
def write_nsd_conf(zonefiles, env):
|
||||||
# Basic header.
|
# Basic header.
|
||||||
nsdconf = """
|
nsdconf = """
|
||||||
server:
|
server:
|
||||||
@ -397,15 +397,13 @@ server:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Since we have bind9 listening on localhost for locally-generated
|
# Since we have bind9 listening on localhost for locally-generated
|
||||||
# DNS queries that require a recursive nameserver, we must have
|
# DNS queries that require a recursive nameserver, and the system
|
||||||
# nsd listen only on public network interfaces. Those interfaces
|
# might have other network interfaces for e.g. tunnelling, we have
|
||||||
# may have addresses different from the public IP address that the
|
# to be specific about the network interfaces that nsd binds to.
|
||||||
# Internet sees this machine on. Get those interface addresses
|
for ipaddr in (env.get("PRIVATE_IP", "") + " " + env.get("PRIVATE_IPV6", "")).split(" "):
|
||||||
# from `hostname -i` (which omits all localhost addresses).
|
if ipaddr == "": continue
|
||||||
for ipaddr in shell("check_output", ["/bin/hostname", "-I"]).strip().split(" "):
|
|
||||||
nsdconf += " ip-address: %s\n" % ipaddr
|
nsdconf += " ip-address: %s\n" % ipaddr
|
||||||
|
|
||||||
|
|
||||||
# Append the zones.
|
# Append the zones.
|
||||||
for domain, zonefile in zonefiles:
|
for domain, zonefile in zonefiles:
|
||||||
nsdconf += """
|
nsdconf += """
|
||||||
|
@ -77,62 +77,58 @@ function get_default_publicip {
|
|||||||
# API, but if that fails (maybe we don't have Internet access
|
# API, but if that fails (maybe we don't have Internet access
|
||||||
# right now) then use the IP address that this machine knows
|
# right now) then use the IP address that this machine knows
|
||||||
# itself as.
|
# itself as.
|
||||||
get_publicip_from_web_service || get_publicip_fallback
|
get_publicip_from_web_service 4 || get_default_privateip 4
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_default_publicipv6 {
|
function get_default_publicipv6 {
|
||||||
get_publicipv6_from_web_service || get_publicipv6_fallback
|
get_publicip_from_web_service 6 || get_default_privateip 6
|
||||||
}
|
}
|
||||||
|
|
||||||
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 -4 --fail --silent icanhazip.com 2>/dev/null
|
# See: https://major.io/icanhazip-com-faq/
|
||||||
|
#
|
||||||
|
# Pass '4' or '6' as an argument to this function to specify
|
||||||
|
# what type of address to get (IPv4, IPv6).
|
||||||
|
curl -$1 --fail --silent icanhazip.com 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_publicipv6_from_web_service {
|
function get_default_privateip {
|
||||||
curl -6 --fail --silent icanhazip.com 2>/dev/null
|
# Return the IP address of the network interface connected
|
||||||
}
|
# to the Internet.
|
||||||
|
#
|
||||||
|
# We used to use `hostname -I` and then filter for either
|
||||||
|
# IPv4 or IPv6 addresses. However if there are multiple
|
||||||
|
# network interfaces on the machine, not all may be for
|
||||||
|
# reaching the Internet.
|
||||||
|
#
|
||||||
|
# Instead use `ip route get` which asks the kernel to use
|
||||||
|
# the system's routes to select which interface would be
|
||||||
|
# used to reach a public address. We'll use 8.8.8.8 as
|
||||||
|
# the destination. It happens to be Google Public DNS, but
|
||||||
|
# no connection is made. We're just seeing how the box
|
||||||
|
# would connect to it. There many be multiple IP addresses
|
||||||
|
# assigned to an interface. `ip route get` reports the
|
||||||
|
# preferred. That's good enough for us. See issue #121.
|
||||||
|
#
|
||||||
|
# Also see ae67409603c49b7fa73c227449264ddd10aae6a9 and
|
||||||
|
# issue #3 for why/how we originally added IPv6.
|
||||||
|
#
|
||||||
|
# Pass '4' or '6' as an argument to this function to specify
|
||||||
|
# what type of address to get (IPv4, IPv6).
|
||||||
|
|
||||||
function get_publicip_fallback {
|
target=8.8.8.8
|
||||||
# Return the IP address that this machine knows itself as.
|
|
||||||
# It certainly may not be the IP address that this machine
|
|
||||||
# operates as on the public Internet. The machine might
|
|
||||||
# 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_ipv4 "$1" || is_loopback_ip "$1"; }; do
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
printf '%s\n' "$1" # return this value
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_publicipv6_fallback {
|
# For the IPv6 route, use the corresponding IPv6 address
|
||||||
set -- $(hostname --ip-address 2>/dev/null) \
|
# of Google Public DNS. Again, it doesn't matter so long
|
||||||
$(hostname --all-ip-addresses 2>/dev/null)
|
# as it's an address on the public Internet.
|
||||||
while (( $# )) && { ! is_ipv6 "$1" || is_loopback_ipv6 "$1"; }; do
|
if [ "$1" == "6" ]; then target=2001:4860:4860::8888; fi
|
||||||
shift
|
|
||||||
done
|
|
||||||
printf '%s\n' "$1" # return this value
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_ipv4 {
|
ip -$1 -o route get $target \
|
||||||
# helper for get_publicip_fallback
|
| grep -v unreachable \
|
||||||
[[ "$1" == *.*.*.* ]]
|
| sed "s/.* src \([^ ]*\).*/\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 {
|
function ufw_allow {
|
||||||
|
@ -136,6 +136,26 @@ if [ -z "$PUBLIC_IPV6" ]; then
|
|||||||
read -e -i "$DEFAULT_PUBLIC_IPV6" -p "Public IPv6: " PUBLIC_IPV6
|
read -e -i "$DEFAULT_PUBLIC_IPV6" -p "Public IPv6: " PUBLIC_IPV6
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Get the IP addresses of the local network interface(s) that are connected
|
||||||
|
# to the Internet. We need these when we want to have services bind only to
|
||||||
|
# the public network interfaces (not loopback, not tunnel interfaces).
|
||||||
|
if [ -z "$PRIVATE_IP" ]; then
|
||||||
|
PRIVATE_IP=$(get_default_privateip 4)
|
||||||
|
fi
|
||||||
|
if [ -z "$PRIVATE_IPV6" ]; then
|
||||||
|
PRIVATE_IPV6=$(get_default_privateip 6)
|
||||||
|
fi
|
||||||
|
if [[ -z "$PRIVATE_IP" && -z "$PRIVATE_IPV6" ]]; then
|
||||||
|
echo
|
||||||
|
echo "I could not determine the IP or IPv6 address of the network inteface"
|
||||||
|
echo "for connecting to the Internet. Setup must stop."
|
||||||
|
echo
|
||||||
|
hostname -I
|
||||||
|
route
|
||||||
|
echo
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
# We need a country code to generate a certificate signing request. However
|
# We need a country code to generate a certificate signing request. However
|
||||||
# if a CSR already exists then we won't be generating a new one and there's
|
# if a CSR already exists then we won't be generating a new one and there's
|
||||||
# no reason to ask for the country code now. $STORAGE_ROOT has not yet been
|
# no reason to ask for the country code now. $STORAGE_ROOT has not yet been
|
||||||
@ -199,6 +219,8 @@ STORAGE_ROOT=$STORAGE_ROOT
|
|||||||
PRIMARY_HOSTNAME=$PRIMARY_HOSTNAME
|
PRIMARY_HOSTNAME=$PRIMARY_HOSTNAME
|
||||||
PUBLIC_IP=$PUBLIC_IP
|
PUBLIC_IP=$PUBLIC_IP
|
||||||
PUBLIC_IPV6=$PUBLIC_IPV6
|
PUBLIC_IPV6=$PUBLIC_IPV6
|
||||||
|
PRIVATE_IP=$PRIVATE_IP
|
||||||
|
PRIVATE_IPV6=$PRIVATE_IPV6
|
||||||
CSR_COUNTRY=$CSR_COUNTRY
|
CSR_COUNTRY=$CSR_COUNTRY
|
||||||
MIGRATIONID=$MIGRATIONID
|
MIGRATIONID=$MIGRATIONID
|
||||||
EOF
|
EOF
|
||||||
|
Loading…
Reference in New Issue
Block a user